一. vue中的指令
1.1 v-text
v-text
主要是用來更新textContent
,可以等同於js中的text
屬性
<span v-text="msg"></span>
複製程式碼
這兩者等同於
<span>{{msg}}</span>
複製程式碼
1.2 v-html
雙大括號的方式會將資料解釋為純文字,而非html,為了輸出真正的html,可以用
v-html
指令,它等同於js中的innerHTML
。
<div v-html="rawHtml"></div>
複製程式碼
這個div的內容將會替換成屬性rawHTML
,直接作為HTML進行渲染。
<div v-html="message">{{message}}</div>
export default {
data () {
return {
message: "這裡可以包含html標籤"
}
}
}
複製程式碼
message
可以包含html標籤,來展示一個頁面的內容
特別是,如果後端返回包含了標籤的內容,可以轉化為html頁面的形式展示。
1.3 v-pre
v-pre
主要是用來跳過這個元素和它的子元素編譯過程。可以用來顯示原始的Mustache
標籤,跳過大量沒有指令的節點加快編譯。
<div>
<span v-pre>{{message}}</span> //這條語句不進行編譯
<span>{{message}}</span>
</div>
複製程式碼
最終僅顯示第二個div的內容。
1.4 v-cloak
這個指令是用來保持在元素上直到關聯例項結束時進行編譯。
<div id="app" v-cloak>
<div>
{{message}}
</div>
</div>
<script type="text/javascript">
new Vue({
el : "#app",
data : {
message:"hello world"
}
})
</script>
複製程式碼
在頁面載入時會先顯示:
<div>
{{message}}
</div>
複製程式碼
然後才會編譯為:
<div>
<div>
hello world!
</div>
</div>
複製程式碼
1.5 v-once
v-once
關聯的示例,只會渲染一次。之後的重新渲染,例項及其所有的子節點將被視為靜態內容跳過,這可以用於優化更新效能。
<span v-once>This never change : {{msg}}</span> //單個元素
<div v-once> //有子元素
<h1>comment</h1>
<p>{{msg}}</p>
</div>
<my-component v-once:comment="msg"></my-component> //元件
<ul>
<li v-for="i in list">{{i}}</li>
</ul>
複製程式碼
上面的例子中,msg
,list
即使產生改變,也不會重新渲染。
1.6 v-if
v-if
可以實現條件渲染,vue會根據表示式的值的真假條件來渲染元素。
<a v-if="ok">yes</a>
複製程式碼
如果屬性值ok為true,則顯示,否則,不會渲染這個元素。
1.7 v-else
v-else
是搭配v-if
使用的,它必須緊跟在v-if
或者v-else-if
後面,否則不起作用。
<a v-if="ok">yes</a>
<a v-else>no</a>
複製程式碼
1.8 v-else-if
v-else-if
充當v-if
的else-if
塊,可以鏈式的使用多次。可以更加方便的實現switch
語句。
<div v-if="type===A">
A
</div>
<div v-if="type===B">
B
</div>
<div v-if="type===C">
C
</div>
<div v-else>
Not A,B,C
</div>
複製程式碼
1.9 v-show
也是根據條件展示元素。和
v-if
不同的是,如果v-if
的值是false
,則這個元素會被銷燬,不再dom中。但是v-show
的元素會始終被渲染並儲存在dom中,它只是簡單的切換css的display
屬性。
<h1 v-show="ok">hello world</h1>
複製程式碼
注意:
- v-if有更高的切換開銷
v-show
有更高的初始渲染開銷 - 如果要非常頻繁的切換,則使用
v-show
較好 - 如果在執行時條件不太可能改變,則使用
v-if
較好
1.10 v-for
用
v-for
指令根據遍歷陣列來進行渲染
有下面兩種遍歷形式:
<div v-for="(item,index) in items"></div> //使用in,index是一個可選引數,表示當前項的索引
<div v-for="item of items"></div> //使用of
複製程式碼
下面是一個例子,並且在v-for
中,擁有對父級作用域屬性的完全訪問許可權:
<ul>
<li v-for="item in items">
{{parent}}-{{item.text}}
</li>
</ul>
<script>
var example = new Vue({
el:"#app",
data:{
parent:"父級作用域"
items:[
{text:"文字1"},
{text:"文字2"}
]
}
})
</script>
複製程式碼
會被渲染為:
<ul id="app">
<li>父作用域-文字1</li>
<li>父作用域-文字2</li>
</ul>
複製程式碼
注意:當v-for和v-if處於同一個節點時,v-for的優先順序比v-if更高,這意味著v-if將執行在每個v-for迴圈中
1.11 v-bind
v-bind
用來動態的繫結一個或者多個特性,沒有引數時,可以繫結到一個包含鍵值對的物件,常用於動態繫結class
和style
。以及href
等。簡寫為一個冒號【:】
1.11.1 物件語法
//進行類似切換的例子
<div class="app">
//當data裡面定義的isActive等於true時,is-active這個類才會被新增起作用
//當data裡面定義的hasError等於true時,text-danger這個類才會被新增起作用
<div :class="{'is-active' :isActive , 'text-danger' :hasError }"></div>
</div>
<script>
var app = new Vue({
el : '#app',
data : {
isActive : true,
hasError : false,
}
})
</script>
渲染結果:
//因為hasError:false,所以text-danger不被渲染
<div class="is-active"></div>
複製程式碼
1.11.2 陣列語法
<div id="app">
//陣列語法:errorClass在data對應的類中一定會新增
//is-active是物件語法,根據activeClass對應的取值決定是否新增
<p :class="[{'is-active' : activeClass} , errorClass]">123456</p>
</div>
<script>
var app = new Vue({
el : '#app',
data : {
activeClass : false,
errorClass : 'text-danger'
}
})
</script>
渲染結果:
//因為activeClass:false,所以is-active不被渲染
<p class="text-danger"></p>
複製程式碼
1.11.3 直接繫結資料物件
<div>
//在vue例項的data中定義了classObject物件,這個物件裡面是所有類名及其值
//當裡面的類的值是true時會被渲染
<div :class="classObject">123456</div>
</div>
<script>
var app = new Vue({
el : "#app",
data : {
classObject:{
'is-active' : false,
'text-danger' : true
}
}
})
</script>
渲染結果:
//因為'is-active' : false, 所以is-active不會被渲染
<div class="text-danger"></div>
複製程式碼
1.12 v-model
這個指令用於在表單上建立雙向資料繫結
v-model
會自動忽略所有表單元素的value
,checked
,selected
特性的初始值。因為它選擇vue例項資料作為具體的值。
<div id="app">
<input v-model="somebody">
<p> hello {{somebody}}</p>
</div>
<script>
var app = new Vue({
el : "#app",
data : {
somebody:"小黃瓜"
}
})
</script>
複製程式碼
這個例子中直接在瀏覽器input
中輸入別的名字,下面的p的內容會直接跟著變。這就是雙向資料繫結。
v-model修飾符
<1>. lazy
預設情況下,
v-model
同步輸入框的值和資料,可以通過這個修飾符,轉變在change
事件同步。
<input v-model.lazy = 'msg'>
複製程式碼
<2>.number
自動將使用者的輸入值轉化為數值型別
<input v-model.number = 'msg'>
複製程式碼
<3>.trim
自動過濾使用者輸入的首尾空格
<input v-model.trim='msg'>
複製程式碼
1.13 v-on
v-on
主要是用來監聽dom事件,以便執行一些程式碼塊,表示式可以是一個方法名。簡寫為:【@】
<div>
<button @click="consolog"></button>
</div>
<script>
var app = new Vue({
el : "#app",
methods : {
consoleLog:function(event){
console.log(1)
}
}
})
</script>
複製程式碼
事件修飾符
.stop
阻止事件繼續傳播.prevent
事件不再過載頁面.capture
使用事件捕獲模式,即元素自身觸發的事件先在此處處理,然後才交由內部元 素進行處理.self
只在event.target
是當前元素自身時觸發處理函式.once
事件將只會觸發一次.passive
告訴瀏覽器你不想阻止事件的預設行為
//阻止單擊事件繼續傳播
<a v-on:click.stop="doThis"></a>
//提交事件不再過載頁面
<form v-on:submit.prevent="onSubmit"></form>
//修飾符可以串聯
<a v-on:click.stop.prevent="doThat"></a>
//只有修飾符
<form v-on="submit.prevent"></form>
//新增事件監聽時使用事件捕獲模式
//即元素自身觸發的事件先在此處處理,然後才交由內部元素進行處理
<div v-on:click.capture="doThis"> ... </div>
//只當在event.target是當前元素自身時觸發處理函式
//即事件不是從內部元素觸發的
<div v-on:click.self="doThat"> ... </div>
//點選事件只會觸發一次
<a v-on:click.once="doThis"></a>
//滾動事件的預設行為(即滾動行為)將會立即觸發
//而不會等待'onScroll'完成
//這其中包含 'enent.preventDefault()'的情況
<div v-on:scroll.passive="onScroll"> ... </div>
複製程式碼
使用修飾符時,順序很重要,相應的程式碼會以同樣的順序產生。因此,用v-on:click.prevent.self
會阻止所有的點選,而v-on:click.self.prevent
只會阻止對元素自身的點選。
二.全域性API
2.1 Vue.extend(option)
引數:
{Object} options
使用基礎Vue構造器,建立一個“子類”,引數是一個包含元件選項的物件。
可以簡單的理解為當在模板中遇到該元件名稱作為標籤的自定義元素時,會自動呼叫擴充套件例項構造器來生產元件例項,並掛載到自定義元素上。
data
選項是特例,需要注意,在Vue.extend()
中它必須是函式
<div id="mount-point"></div>
//建立構造器
var Profile = Vue.extend({
templete:'<p>{{firstName}}{{lastName}} aka {{alias}}</p>',
data : function(){
return{
firstName : 'Walter',
lastName : 'White',
alias : '小黃瓜',
}
}
})
//建立Profile例項,並掛載到一個元素
new Profile().$mount('#mount-point')
複製程式碼
結果如下:
<p>Walter White ake 小黃瓜</p>
複製程式碼
2.2 Vue.nextTick([callback , context])
引數:
{Function} [callback]
{Object} [context]
在下次DOM更新迴圈結束之後執行延遲迴調。在修改資料之後立即使用這個方法,獲取更新後的DOM。
因為Vue在修改資料後,檢視不會立刻更新,而是等同一事件迴圈中的所有資料變化完成之後,再統一進行檢視更新。
//改變資料
vm.message = 'change'
//想要立即使用更新後的資料,不可以,因為設定message後的DOM還沒有更新
console.log(vm.$el.textContent) //並不會得到'changed'
//這樣可以,因為nextTick裡面的程式碼會在DOM更新後執行
Vue.nextTick(function(){
console.log(vm.$el.textContent) //可以得到'change'
})
複製程式碼
Vue例項
new Vue({
el: '.app',
data: {
msg: 'Hello Vue.',
msg1: '',
msg2: '',
msg3: ''
},
methods: {
changeMsg() {
this.msg = "Hello world."
this.msg1 = this.$refs.msgDiv.innerHTML
this.$nextTick(() => {
this.msg2 = this.$refs.msgDiv.innerHTML
})
this.msg3 = this.$refs.msgDiv.innerHTML
}
}
})
複製程式碼
那麼什麼時候需要用的到Vue.nextTick()
呢?
- 1.你在Vue生命週期的created()鉤子函式進行的DOM操作一定要放在
Vue.nextTick()
的回撥函式中。原因是什麼呢,原因是在created()
鉤子函式執行的時候DOM 其實並未進行任何渲染,而此時進行DOM操作無異於徒勞,所以此處一定要將DOM操作的js程式碼放進Vue.nextTick()
的回撥函式中。與之對應的就是mounted
鉤子函式,因為該鉤子函式執行時所有的DOM掛載和渲染都已完成,此時在該鉤子函式中進行任何DOM操作都不會有問題 。 - 2.在資料變化後要執行的某個操作,而這個操作需要使用隨資料改變而改變的DOM結構的時候,這個操作都應該放進
Vue.nextTick()
的回撥函式中。
原因是,Vue是非同步執行dom更新的,一旦觀察到資料變化,Vue就會開啟一個佇列,然後把在同一個事件迴圈 (event loop)
當中觀察到資料變化的 watcher
推送進這個佇列。如果這個watcher
被觸發多次,只會被推送到佇列一次。這種緩衝行為可以有效的去掉重複資料造成的不必要的計算和DOm操作。而在下一個事件迴圈時,Vue會清空佇列,並進行必要的DOM更新。
當你設定 vm.someData = 'new value'
,DOM 並不會馬上更新,而是在非同步佇列被清除,也就是下一個事件迴圈開始時執行更新時才會進行必要的DOM更新。如果此時你想要根據更新的 DOM 狀態去做某些事情,就會出現問題。。為了在資料變化之後等待 Vue 完成更新 DOM ,可以在資料變化之後立即使用 Vue.nextTick(callback)
。這樣回撥函式在 DOM 更新完成後就會呼叫。
2.3.set(target,key,value)
引數:
-
{Object | Array} target
-
{string | number} key
-
{any} value
-
target
: 要修改的資料來源(可以是物件或者是陣列) -
key
: 要更改的資料 -
value
:重新賦的值
響應式修改 , 在列表中動態新增一條資料
根據push新增:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="node_modules/vue/dist/vue.js"></script>
</head>
<body>
<div class="app">
<p v-for="item in arr">{{item.title}}</p>
<button @click="change">新增</button>
</div>
<script>
let app = new Vue({
el : '.app',
data:{
arr:[
{title : '小黃瓜'},
{title : '小番茄'},
{title : '小橘子'},
{title : '小嗨瓜'},
]
},
methods: {
change(){
this.arr.push({title : '這是push插入的'});
}
},
})
</script>
</body>
</html>
複製程式碼
通過陣列的變異方法,我們可以動態的控制資料的增減,但是我們卻無法做到對某條資料的修改,這時候需要set
方法:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="node_modules/vue/dist/vue.js"></script>
</head>
<body>
<div class="app">
<p v-for="item in arr" :key="item.id">{{item.title}}</p>
<button @click="change">修改</button>
<button @click="change1">新增</button>
</div>
<script>
let app = new Vue({
el : '.app',
data:{
arr:[
{title : '小黃瓜' , id : '0'},
{title : '小番茄' , id : '1'},
{title : '小橘子' , id : '2'},
{title : '小嗨瓜' , id : '3'},
]
},
methods: {
change(){
this.$set(this.arr,0,{title : '長出來一根刺' , id : '7'})
},
change1(){
let chang = this.arr.length;
Vue.set(this.arr,chang, {title : "第二根刺" , id : chang});
}
},
})
</script>
</body>
</html>
複製程式碼
警惕! 當寫慣了js之後,有可能想改變陣列中某個下標中的資料我直接this.arr[ ]就修改了,如:
change(){
this.arr[0] = {title : "小黃瓜" , id : "7"}
}
複製程式碼
檢視結果:
這種情況,是Vue文件中明確指出的注意事項,由於 JavaScript 的限制,Vue 不能檢測出資料的改變,所以當我們需要動態改變資料的時候,Vue.set()
完全可以滿足我們的需求。
這裡可以看出,Vue.set()
不光能修改資料,還能新增資料,彌補了Vue陣列變異方法的不足
Tip:Vue.set()在methods中也可以寫成this.$set()
2.4 Vue.delete(target , key)
引數:
{Object | Array} target
{string | number} key/index
刪除物件的屬性,如果物件是響應式的,確保刪除能觸發更新檢視。這個方法主要用於避開vue不能檢測到屬性被刪除的限制,但是很少用。
data : {
nameliat : {
id : 1,
name : '小黃瓜',
}
}
複製程式碼
//刪除name
delete this.namelist.name; //js方法
Vue.delete(this.namelist, 'name'); //vue方法
複製程式碼
2.5 Vue.directive(id , [ definition])
引數:
{string} id
{Function | Object} [definition]
註冊或獲取全域性指令
//註冊一個全域性自定義指令
Vue.directive('focus' , {
//當被繫結的元素插入到DOM中時。。
inserted : function(el){
//聚焦元素
el.focus()
}
})
複製程式碼
註冊區域性元件,元件接受一個directives
選項:
directives : {
focus : {
//指令的定義
inserted : function(el){
el.focus()
}
}
}
複製程式碼
可以在模板的任意元素上使用新的v-focus
屬性,如下 :
<input v-focus>
複製程式碼
自定義指令的生命週期
自定義指令有五個生命週期(也叫鉤子函式),分別是
bind
,inserted
,update
,componentUpdated
,unbind
-
bind
:只呼叫一次,指令第一次繫結到元素時呼叫,用這個鉤子函式可以定義一個繫結時執行一次的初始化動作。
-
inserted
:被繫結元素插入父節點時呼叫(父節點存在即可呼叫,不必存在於document中)。
-
update
:被繫結於元素所在的模板更新時呼叫,而無論繫結值是否變化。通過比較更新前後的繫結值,可以忽略不必要的模板更新。
-
componentUpdated
:被繫結元素所在模板完成一次更新週期時呼叫。
-
unbind
:只呼叫一次,指令與元素解綁時呼叫。
2.6 Vue.filter( id, [definition] )
引數:
{string} id
{Function} [definition]
註冊或獲取全域性過濾器。
過濾器可在new Vue例項前註冊全域性的,也可以在元件上寫區域性
//全域性過濾器
Vue.filter('Father', function (value) {
return value
})
//元件中的區域性過濾器
filters:{
componentFather:function(value){
return value
}
},
複製程式碼
注意:全域性註冊時是filter,沒有s。而元件過濾器是filters,是有s的,雖然你寫的時候沒有s不報錯,但是過濾器是沒有效果.
2.7 Vue.component( id, [definition] )
引數:
-
{string} id
-
{Function | Object} [definition]
-
第一個引數是自定義元素名稱,也就是將來在別的元件中使用這個元件的標籤名稱。
-
第二個引數是將要註冊的Vue元件。
//全域性
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8">
<script src="vue.js"></script>
</head>
<body>
<div id="box">
<test></test>
</div>
<script type="text/javascript">
//註冊
Vue.component('test', {
template: '<div @click="change">{{msg}}</div>',
data:function(){
return {msg:'我的元件'}
},
methods:{
change:function(){
//todo
console.log(this);
}
}
});
//建立根例項
var vm = new Vue({
el:'#box',
});
</script>
</body>
</html>
複製程式碼
//區域性註冊
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8">
<script src="vue.js"></script>
</head>
<body>
<div id="box">
<test></test>
</div>
<script type="text/javascript">
///定義元件
var testTemplate = {
template: '<div @click="change">{{msg}}</div>',
data:function(){
return {msg:'我的區域性元件'}
},
methods:{
change:function(){
console.log(this);
}
}
};
//建立根例項
var vm = new Vue({
el:'#box',
components:{
'test': testTemplate
}
});
</script>
</body>
</html>
複製程式碼
2.8 Vue.use( plugin )
引數:
{Object | Function} plugin
安裝 Vue.js 外掛。如果外掛是一個物件,必須提供
install
方法。如果外掛是一個函式,它會被作為install
方法。install 方法呼叫時,會將 Vue 作為引數傳入。
該方法需要在呼叫 new Vue() 之前被呼叫。
當 install 方法被同一個外掛多次呼叫,外掛將只會被安裝一次。
通過全域性方法 Vue.use()
使用外掛。它需要在你呼叫 new Vue() 啟動應用之前完成:
// 呼叫 `MyPlugin.install(Vue)`
Vue.use(MyPlugin)
new Vue({
// ...元件選項
})
複製程式碼
也可以傳入一個可選的選項物件:
Vue.use(MyPlugin, { someOption: true })
複製程式碼
Vue.use
會自動阻止多次註冊相同外掛,屆時即使多次呼叫也只會註冊一次該外掛。
Vue.js 官方提供的一些外掛 (例如 vue-router
) 在檢測到 Vue 是可訪問的全域性變數時會自動呼叫 Vue.use()
。然而在像 CommonJS 這樣的模組環境中,你應該始終顯式地呼叫 Vue.use()
:
// 用 Browserify 或 webpack 提供的 CommonJS 模組環境時
var Vue = require('vue')
var VueRouter = require('vue-router')
// 不要忘了呼叫此方法
Vue.use(VueRouter)
複製程式碼
2.9 Vue.mixin( mixin )
引數:
{Object} mixin
全域性註冊一個混入,影響註冊之後所有建立的每個 Vue 例項。
基礎示例:
//首先定義一個混入物件
var myMixin = {
created: function () {
this.hello()
},
methods: {
hello: function () {
console.log('hello 小黃瓜')
}
}
}
// 定義一個使用混入物件的元件
var Component = Vue.extend({
mixins: [myMixin]
})
var component = new Component() // "hello 小黃瓜"
複製程式碼
選項合併 :
//當元件和混入物件含有同名選項時,這些選項將以恰當的方式進行“合併”。
//資料物件在內部會進行遞迴合併,並在發生衝突時以元件資料優先。
var mixin = {
data: function () {
return {
message: 'hello',
foo: 'abc'
}
}
}
new Vue({
mixins: [mixin],
data: function () {
return {
message: 'goodbye',
bar: 'def'
}
},
created: function () {
console.log(this.$data)
// { message: "goodbye", foo: "abc", bar: "def" }
}
})
複製程式碼
同名鉤子函式將合併為一個陣列,因此都將被呼叫。另外,混入物件的鉤子將在元件自身鉤子之前呼叫。
var mixin = {
created: function () {
console.log('混入物件的鉤子被呼叫')
}
}
new Vue({
mixins: [mixin],
created: function () {
console.log('元件鉤子被呼叫')
}
})
// "混入物件的鉤子被呼叫"
// "元件鉤子被呼叫"
複製程式碼
值為物件的選項,例如 methods
、components
和 directives
,將被合併為同一個物件。兩個物件鍵名衝突時,取元件物件的鍵值對。
var mixin = {
methods: {
foo: function () {
console.log('Foo')
},
conflicting: function () {
console.log('from mixin')
}
}
}
var exm = new Vue({
mixins: [mixin],
methods: {
bar: function () {
console.log('bar')
},
conflicting: function () {
console.log('from self')
}
}
})
exm.foo() // "Foo"
exm.bar() // "bar"
exm.conflicting() // "from self"
複製程式碼
混入也可以進行全域性註冊。
// 為自定義的選項 'myCompontent' 注入一個處理器。
Vue.mixin({
created: function () {
var myCompontent = this.$options.myCompontent
if (myCompontent) {
console.log(myCompontent)
}
}
})
new Vue({
myCompontent: 'hello!'
})
// "hello!"
複製程式碼
注意: 一旦使用全域性混入,它將影響每一個之後建立的 Vue 例項。
2.10 Vue.compile( template )
引數:
{string} template
在
render
函式中編譯模板字串。只在獨立構建時有效
var res = Vue.compile('<div><span>{{ msg }}</span></div>')
new Vue({
data: {
msg: 'hello 小黃瓜'
},
render: res.render,
staticRenderFns: res.staticRenderFns
})
複製程式碼
2.11 Vue.observable( object )
2.6.0新增
引數:
{Object} object
讓一個物件可響應。Vue 內部會用它來處理 data
函式返回的物件。
返回的物件可以直接用於渲染函式和計算屬性內,並且會在發生改變時觸發相應的更新。也可以作為最小化的跨元件狀態儲存器
const state = Vue.observable({ count: 0 })
const Demo = {
render(h) {
return h('button', {
on: { click: () => { state.count++ }}
}, `count is: ${state.count}`)
}
}
複製程式碼
2.12 Vue.version
提供字串形式的 Vue 安裝版本號。
var version = Number(Vue.version.split('.')[0])
if (version === 2) {
// Vue v2.x.x
} else if (version === 1) {
// Vue v1.x.x
} else {
// Unsupported versions of Vue
}
複製程式碼
本文參考VUE官方文件