Vue 快速上手
實(shí)例1: 渲染聲明
渲染聲明是 vue 的最核心模塊。
vue 基于傳統(tǒng)的 HTML 模板語法,將 DOM 綁定到 vue 實(shí)例上,然后 vue 在底層的實(shí)現(xiàn)上,將 模板編譯成虛擬 DOM 渲染函數(shù)(render function)。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id='app'>
<!-- Mustache 標(biāo)簽將會(huì)被替代為對(duì)應(yīng)數(shù)據(jù)對(duì)象上 message 屬性的值 -->
{{ message }}
<!-- 如果只想一次性的插值,不想被數(shù)據(jù)驅(qū)動(dòng)改變,用 v-once -->
<div v-once>{{ messageForOnce }}</div>
<!-- 也可以渲染模板,用 v-html -->
<div v-html="messageHtml"></div>
</div>
</body>
<script src="../utils/vue.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
message: 'Hello vue for message!',
messageForOnce: 'Hello vue for once message',
messageHtml: '<span style="color: red;"> Hello vue for template render</span>'
}
})
</script>
</html>
打開瀏覽器 Console,感受 v-once 的不同
app.message = 'Hello vue for message, Updated'
app.messageForOnce = 'Hello vue for once, Updated' // 無效
指令 (Directives)
帶有 v- 前綴的 v-once
、v-html
、v-bind
、v-on
、v-if
... 稱指令。它的作用是當(dāng)它的值(表達(dá)式)改變時(shí),其帶來的影響,響應(yīng)式地作用于 DOM。
實(shí)例2: 屬性綁定
可以將 html 的屬性和 數(shù)據(jù) 進(jìn)行綁定,動(dòng)態(tài)的更改屬性。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id='app'>
<span v-bind:title="title">
這個(gè) DOM 具有動(dòng)態(tài)的 Title
</span>
<img v-bind:src="imgUrl"></img>
</div>
</body>
<script src="../utils/vue.js"></script>
<script>
// http://o9h4emdrs.bkt.clouddn.com/atomatom-boom2.gif
var app2 = new Vue({
el: '#app',
data: {
title: 'title-1',
imgUrl: 'http://o9h4emdrs.bkt.clouddn.com/live.jpg'
}
})
</script>
</html>
打開瀏覽器 Console,驗(yàn)證動(dòng)態(tài)的 title
app2.message = 'title-2'
app2.imgUrl="http://o9h4emdrs.bkt.clouddn.com/atomatom-boom2.gif"
指令參數(shù)
在指令名稱之后以冒號(hào)表示的是指令的參數(shù),一些指令能夠接收一個(gè)“參數(shù)”.
比如: v-bind:title="title"
和 v-bind:src="imgUrl"
,這里的 v-bind 指令可以用于響應(yīng)式地更新 HTML 的特性。
實(shí)例3: 條件雙向綁定
用 條件雙向綁定 切換展示不同的 DOM。涉及到的指令有 v-if
、v-else
、v-if-else
和 v-show
。
-
v-show
只是簡單地切換元素的 CSS 屬性 display,DOM 始終會(huì)被渲染并被保留,只是隱藏和顯示;
-
v-if
是真正的 銷毀和重建 DOM,有更大的開銷。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id='app'>
<p v-if="isShow">
Now you can see.
</p>
</div>
</body>
<script src="../utils/vue.js"></script>
<script>
var app3 = new Vue({
el: '#app',
data: {
isShow: true
}
})
</script>
</html>
打開瀏覽器 Console
app3.isShow = false
app3.isShow = true
實(shí)例4:列表渲染 v-for
可以使用 v-for
對(duì)列表或?qū)ο筮M(jìn)行渲染,v-for 指令需要使用 item in items 形式的特殊語法,items是數(shù)據(jù)源,item是items的別名,這里的in 也可以改成 of,如果循環(huán)是數(shù)組,也可以這樣寫 (item,index) in items,index為值的下標(biāo) 。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id='app'>
<!--// index為下標(biāo) -->
<p v-for="(todo, index) in todos">
<span :key="index">{{ index }}: {{ todo.text }}</span>
</p>
</div>
</body>
<script src="../utils/vue.js"></script>
<script>
var app4 = new Vue({
el: '#app',
data: {
todos: [
{ text: 'Learn Vue' },
{ text: 'Learn Javascript' },
{ text: 'Learn PHP' },
{ text: 'Learn Golang' }
]
}
})
</script>
</html>
打開瀏覽器 Console
# 添加一條數(shù)據(jù)
app4.todos.push({ text: 'Learn Java' })
# 刪除下標(biāo)為2的數(shù)據(jù),刪除一次
app4.todos.splice(2, 1)
實(shí)例5: 事件處理 v-on
可以用 v-on 指令監(jiān)聽 DOM 事件,并在觸發(fā)時(shí)運(yùn)行一些 JavaScript 代碼。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id='app'>
<button v-on:click="getRandomColor">
換個(gè)顏色
</button>
{{ value }}
<div v-bind:style="{background: value, width: '168px', height: '100px', marginTop: '10px'}"></div>
</div>
</body>
<script src="../utils/vue.js"></script>
<script>
var app5 = new Vue({
el: '#app',
data: {
value: 'blue'
},
methods: {
getRandomColor() {
this.value = '#'+(Math.random() * 0xffffff << 0).toString(16)
}
}
})
</script>
</html>
實(shí)例6: 表單的輸入綁定 v-model
使用 v-model 我們可以在 <input>
、<textarea>
、<select>
等元素上創(chuàng)建雙向數(shù)據(jù)綁定。
v-model 本質(zhì)上是一個(gè)語法糖,在單向數(shù)據(jù)綁定的基礎(chǔ)上,增加了監(jiān)聽用戶輸入事件并更新數(shù)據(jù)的功能
修飾符
- .trim: 去掉頭和尾的空白字符
- .lazy: input 更新改為 輸入更新
- .number: 將用戶的輸入值轉(zhuǎn)為數(shù)值類型
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id='app'>
<div>
<p>輸入框</p>
<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>
</div>
<div>
<p>復(fù)選框</p>
<input type="checkbox" id="Jack" value="Jack" v-model="checkedNames">
<label for="Jack">Jack</label>
<input type="checkbox" id="john" value="John" v-model="checkedNames">
<label for="john">John</label>
<input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
<label for="mike">Mike</label>
{{ checkedNames }}
</div>
<div>
<p>選擇框</p>
<select v-model="selected">
<option v-for="option in options" v-bind:value="option.value">
{{ option.text }}
</option>
</select>
<span>Selected: {{ selected }}</span>
</div>
<!-- 實(shí)現(xiàn)一個(gè) v-model, 也是一個(gè)沒有任何修飾符的 v-model -->
<input type="text" :value="value" v-on:input="value = $event.target.value">
Value is: {{ value }}
</div>
</body>
<script src="../utils/vue.js"></script>
<script>
var app6 = new Vue({
el: '#app',
data: {
message: '',
checked: '',
checkedNames: [],
selected: '',
options: [
{ text: 'One', value: 'A' },
{ text: 'Two', value: 'B' },
{ text: 'Three', value: 'C' }
],
value: ''
}
})
</script>
</html>
實(shí)例7:計(jì)算屬性,方法,偵聽器
有時(shí)候我們需要對(duì)接收的數(shù)據(jù)進(jìn)行轉(zhuǎn)化,在模板中太多的邏輯不利于維護(hù),這個(gè)時(shí)候我們可以使用 計(jì)算屬性 computed
和偵聽器 watch
。
computed: 不能接收參數(shù),因?yàn)槭歉鶕?jù)依賴偵聽的。計(jì)算屬性會(huì)基于它的依賴進(jìn)行緩存,無副作用。
methods: 用于接收參數(shù)時(shí)使用。不會(huì)緩存,每次都會(huì)重新計(jì)算。
watch: 一種更通用的方式來觀察和響應(yīng) Vue 實(shí)例上的數(shù)據(jù)變動(dòng)。用于有副作用的操作,開銷大的操作。
computed 和 watch 區(qū)別:從屬性名上,computed是計(jì)算屬性,也就是依賴其它的屬性計(jì)算所得出最后的值。watch是去監(jiān)聽一個(gè)值的變化,然后進(jìn)行相應(yīng)的操作。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id='app'>
// {{message}} 插值表達(dá)式 執(zhí)行計(jì)算屬性
// {{methnewmessage()}} 調(diào)用方法
// {{newmess}} 偵聽器
<p>輸入框</p>
<input type="text" v-model="message" />
<p>newmessage is :{{newmessage}}</p>
<p>methnewmessage is :{{methnewmessage()}}</p>
<p>watch is : {{newmess}}</p>
<p>輸入框</p>
<input type="text" :value="value" v-on:input="value=$event.target.value" />
<p>{{value}}</p>
</body>
<script src="../utils/vue.js"></script>
<script>
var app7 = new Vue({
el: '#app',
data: {
message: "hello vue",
value: "",
newmess: "",
},
// 計(jì)算屬性,有緩存機(jī)制
computed: {
newmessage() {
return this.message.split('').reverse().join('')
}
},
// 偵聽器 ,有緩沖機(jī)制
watch: {
message: {
handler(value) {
console.log(value)
if (value === 'hello'){
this.newmess = value.split('').reverse().join('')
}else {
this.newmess = value
}
},
immediate: true
}
}
},
// 方法,無緩存機(jī)制,值改變就重新計(jì)算一次
methods: {
methnewmessage: function () {
return this.message.split('').reverse().join('')
}
}
})
</script>
</html>
實(shí)例8:計(jì)算屬性的setter 和getter
<!DOCTYPE html>
<html>
<head>
<title>計(jì)算屬性的getter和setter</title>
<script src=".ue.js"></script>
</head>
<body>
<div id='app'>
{{fullName}}
</div>
<script>
var vm = new Vue({
el:'#app',
data: {
firstName: "Dell",
lastName: "Dll"
},
computed: {
fullName: {
get: function() {
return this.firstName + " " + this.lastName;
},
set: function(vaule) {
var arr = vaule.split(" ");
this.firstName = arr[0];
this.lastName = arr[1];
}
}
}
})
</script>
</body>
</html>
縮寫
- v-bind 縮寫 :
<!-- 完整語法 -->
<a v-bind:href="url">...</a>
<!-- 縮寫 -->
<a :href="url">...</a>
- v-on 縮寫 @
<!-- 完整語法 -->
<a v-on:click="doSomething">...</a>
<!-- 縮寫 -->
<a @click="doSomething">...</a>
實(shí)例9: vue實(shí)例 和 生命周期
創(chuàng)建 vue 的過程: vue 的生命周期
有兩個(gè)關(guān)鍵的點(diǎn)需要注意:
- 掛載節(jié)點(diǎn) el
- template or outerHTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app-3">
{{message}}
</div>
</body>
<script src="../utils/vue.js"></script>
<script>
var app3 = new Vue({
el: "#app-3",
data() {
return {
message: "hello vue",
}
},
beforeCreate() {
console.log('調(diào)用beforecreate鉤子',this.message)
},
created() {
console.log('調(diào)用created鉤子',this.message)
},
beforeMount() {
console.log('調(diào)用beforeMount鉤子',this.message)
},
mounted() {
console.log('調(diào)用mounted鉤子',this.message)
},
beforeUpdate() {
console.log('調(diào)用beforeUpdate鉤子',this.message)
},
updated() {
console.log('調(diào)用updated鉤子',this.message)
},
beforeDestroy() {
console.log('調(diào)用beforeDestroy鉤子',this.message)
},
destroyed() {
console.log('調(diào)用destroyed鉤子',this.message)
},
})
</script>
</html>
實(shí)例10: 組件化開發(fā)
什么是組件
組件,是包含了 HTML、CSS、JavaScript,也就是說包含了組件的模板、樣式和交互邏輯等內(nèi)容,然后暴露出合適的接口。外部只要按照組件設(shè)定的屬性、函數(shù)及事件處理等進(jìn)行調(diào)用即可,完全不用考慮組件的內(nèi)部實(shí)現(xiàn)邏輯,對(duì)外部來說,組件是一個(gè)完全的黑盒。
組件和模塊的區(qū)別:組件強(qiáng)調(diào) 高復(fù)用
和 低耦合
。模塊強(qiáng)調(diào) 高內(nèi)聚
和 低耦合
。
組件化開發(fā)
一個(gè)大的應(yīng)用,由若干個(gè)組件組合而成。每個(gè)組件之間是相互獨(dú)立的,通過組件接口進(jìn)行通信。
最初是通過使用 html、css、js 以頁面作為開發(fā)單位,當(dāng)時(shí)我們的思維方式就是那樣。
后來我們的前端開發(fā)從頁面轉(zhuǎn)變?yōu)榱藨?yīng)用。應(yīng)用就會(huì)有模塊封裝和切分的需求,很快我們發(fā)現(xiàn)應(yīng)用是可以拆分為組件樹的,這是偏展示的一個(gè)理解,react的出現(xiàn)揭示了一個(gè)事實(shí),就是組件可以是函數(shù),所以后來,vue 也有了 render 函數(shù)。
如圖所示,想象一下,整個(gè)應(yīng)用是一個(gè)大的函數(shù),函數(shù)里面可以調(diào)用別的函數(shù),每個(gè)組件是一個(gè)函數(shù),一個(gè)組件可以調(diào)用別的函數(shù),返回 viture dom,這突破了我們原來對(duì)靜態(tài)頁面的理解方式。
定義一個(gè)組件
兩種方式:
- 通過 Vue.component() 對(duì)象來注冊,全局注冊
Vue.component('my-component', { /* ... */ })
// 通過 Vue.component() 對(duì)象來注冊,全局注冊
Vue.component('todo-item', {
props: ['todo'],
template: '<li>this is a {{ todo }} item.</li>'
})
var app9 = new Vue({
el: '#app',
data() {
return {
todos: [
{ text: 'Learn Vue' },
{ text: 'Learn Javascript' },
{ text: 'Learn PHP' },
{ text: 'Learn Golang' }
]
}
}
})
- 通過普通JS對(duì)象,定義屬性的方式來注冊,局部注冊
let MyComponent = { /* ... */ }
// 通過一個(gè)普通的 JavaScript 對(duì)象來定義局部組件
var TodoItem = {
props: ['todo'],
template: `<li class="item">this is a {{ todo }} item.</li>`
}
var app9 = new Vue({
el: '#app',
data() {
return {
todos: [
{ text: 'Learn Vue' },
{ text: 'Learn Javascript' },
{ text: 'Learn PHP' },
{ text: 'Learn Golang' }
]
}
},
components: {
'todo-item': TodoItem
}
})
組件通信
子組件接受父組件傳的值用props
子組件向父組件(上層)觸發(fā)事件用$emit
- $emit and props
組件交互(todi list)實(shí)例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app-4">
<input type="text" v-model='value' @keyup.enter="add">
<todo-item v-for='todo in todos' :todo='todo.text' @remove="removeIt"></todo-item>
</div>
</body>
<script src="../utils/vue.js"></script>
<script>
// 全局組件
// Vue.component('todo-item',{
// props: ['todo'],
// template: '<li>this is {{todo}} item</li>'
// })
// 通過一個(gè)普通的 JavaScript 對(duì)象來定義局部組件
var todoItem = {
props: ['todo'],
template:`
<li>this is a {{ todo }} item
<button @click="remove">remove</button>
</li>
`,
methods: {
remove() {
this.$emit("remove",this.todo)
}
}
}
var app4 = new Vue({
el: "#app-4",
components : {
// 'todo-item':todoItem
todoItem
},
data() {
return {
value : "",
todos: [
{text: "hello1"},
{text: "hello2"},
{text: "hello3"},
{text: "hello4"},
]
}
},
methods: {
removeIt(deleteText) {
this.todos = this.todos.filter(function(todo) {
return todo.text !== deleteText
});
},
add() {
console.log(this.value)
// some() 方法用于檢測數(shù)組中的元素是否滿足指定條件(函數(shù)提供)。
// some() 方法會(huì)依次執(zhí)行數(shù)組的每個(gè)元素:
// 如果有一個(gè)元素滿足條件,則表達(dá)式返回true , 剩余的元素不會(huì)再執(zhí)行檢測。
// 如果沒有滿足條件的元素,則返回false。
let isvalid = this.todos.some(todo =>{
console.log(todo.text,this.value)
// let isvalid = this.todos.some(function(todo){
return todo.text === this.value
})
console.log(isvalid)
if (isvalid){
alert('重復(fù)啦')
return
}else {
this.todos.push({text:this.value})
this.value = ""
}
}
},
})
</script>
</html>