摘要:二起步在學(xué)習(xí)之前,需要有扎實(shí)的基礎(chǔ)。三核心實(shí)例每個(gè)應(yīng)用都是通過(guò)構(gòu)造函數(shù)創(chuàng)建的一個(gè)新的實(shí)例開(kāi)始的選項(xiàng)對(duì)象在這其中的簡(jiǎn)稱通常都表示實(shí)例的變量名。
重要說(shuō)明:本文會(huì)在我有空閑時(shí)間時(shí)持續(xù)更新,相當(dāng)于是將官網(wǎng)的示例給完全呈現(xiàn),是為了幫助初學(xué)者,也是為了鞏固我自己的技術(shù),我決定將官網(wǎng)給過(guò)濾一道消化,敬請(qǐng)期待。
一.介紹vue是一種漸進(jìn)式框架,被設(shè)計(jì)為自底向上逐層應(yīng)用。所謂漸進(jìn)式框架,我的理解就是vue是循序漸進(jìn)的,一步一步的用。
舉個(gè)簡(jiǎn)單的例子,就算我們不會(huì)webpack,不會(huì)node,但也能很快的入門。更多詳情參閱漸進(jìn)式。
在學(xué)習(xí)vue之前,需要有扎實(shí)的HTML,CSS,JavaScript基礎(chǔ)。任何一個(gè)入門語(yǔ)言都離不開(kāi)hello,world!例子,我們來(lái)寫這樣一個(gè)例子:
新建一個(gè)html文件,helloworld.html,如下:
hello,world {{ message }}
js代碼如下:
var app = new Vue({ el:"#app", data:{ message:"hello,world!" } })
現(xiàn)在我們已經(jīng)成功創(chuàng)建了第一個(gè)vue應(yīng)用,數(shù)據(jù)和DOM已經(jīng)被關(guān)聯(lián),所有的東西都是響應(yīng)式的,我們要如何確定呢,打開(kāi)瀏覽器控制臺(tái),修改app.message的值。
在這其中data對(duì)象的寫法,我們還可以寫成函數(shù)形式,如下:
var app = new Vue({ el:"#app", //這里是重點(diǎn) data(){ return{ message:"hello,world!" } } })2.文本插值
當(dāng)然除了文本插值,我們還可以綁定元素屬性,如下:
v-bind 鼠標(biāo)懸浮上去可以看到
js代碼如下:
var app = new Vue({ el:"#app", data:{ message:"頁(yè)面加載于:" + new Date().toLocaleString() } })
查看效果,前往此處查看效果:
同樣的我們也可以修改message的值,這樣的話,鼠標(biāo)懸浮上去,懸浮的內(nèi)容就會(huì)改變了。在這個(gè)例子中v-bind(或者也可以寫成":")其實(shí)就是一個(gè)指令,指令通常前綴都帶有v-,用于表示vue指定的特殊特性,在渲染DOM的時(shí)候,它會(huì)應(yīng)用特殊的響應(yīng)式行為。這個(gè)指令所表達(dá)的意思就是:將這個(gè)title屬性的值與vue實(shí)例的message值保持一致。
當(dāng)然,我們也可以控制一個(gè)元素的顯隱,那也是非常的簡(jiǎn)單,只需要使用v-show指令即可:
v-if 默認(rèn)你是看不到我的哦
js代碼如下:
var app = new Vue({ el:"#app", data:{ seen:false } })
嘗試在控制臺(tái)中修改seen的值,也就是app.seen = true,然后你就可以看到頁(yè)面中的span元素了,具體示例
4.列表渲染還有v-for指令,用于渲染一個(gè)列表,如下:
v-for {{ item.name }}{{ item.content }}
js代碼如下:
var app = new Vue({ el:"#app", data:{ list:[ { name:"項(xiàng)目一",content:"HTML項(xiàng)目"}, { name:"項(xiàng)目二",content:"CSS項(xiàng)目"}, { name:"項(xiàng)目三",content:"JavaScript項(xiàng)目"}, ] } })
當(dāng)然你也可以自己在控制臺(tái)改變list的值,具體示例
5.事件vue通過(guò)v-on + 事件屬性名(也可以寫成"@" + 事件屬性名)指令添加事件,例如v-on:click或@click如下一個(gè)示例:
v-on {{ message }}
js代碼如下:
var app = new Vue({ el:"#app", data:{ message:"hello,vue.js!" }, methods:{ reverseMessage:function(){ //在這里this指向構(gòu)造函數(shù)構(gòu)造的vue實(shí)例 this.message = this.message.split("").reverse().join(""); } } })
反轉(zhuǎn)信息的思路就是使用split()方法將字符串轉(zhuǎn)成數(shù)組,,然后使用數(shù)組的reverse()方法將數(shù)組倒序,然后再使用join()方法將倒序后的數(shù)組轉(zhuǎn)成字符串。
你也可以嘗試在這里查看示例
6.組件組件是vue中的一個(gè)核心功能,它是一個(gè)抽象的概念,它把所有應(yīng)用抽象成一個(gè)組件樹(shù),一個(gè)組件樹(shù)就是一個(gè)預(yù)定義的vue實(shí)例,在vue中使用Vue.component()注冊(cè)一個(gè)組件,它有兩個(gè)參數(shù),第一個(gè)參數(shù)為組件名(尤其要注意組件名的命名),第二個(gè)參數(shù)為組件屬性配置對(duì)象,如:
//定義一個(gè)簡(jiǎn)單的組件 Vue.component("todo-item",{ template:`
現(xiàn)在我們來(lái)看一個(gè)完整的例子:
component
js代碼如下:
Vue.component("todo-item",{ props:["todo"], template:`
這樣,一個(gè)簡(jiǎn)單的組件就完成了,在這里,我們知道了,父組件app可以通過(guò)props屬性將數(shù)據(jù)傳遞給子組件todo-item,這是vue父子組件之間的一種通信方式。
你可以嘗試在此處具體示例。
每個(gè)vue應(yīng)用都是通過(guò)Vue構(gòu)造函數(shù)創(chuàng)建的一個(gè)新的實(shí)例開(kāi)始的:
var vm = new Vue({ //選項(xiàng)對(duì)象 })
在這其中vm(viewModel的簡(jiǎn)稱)通常都表示vue實(shí)例的變量名。當(dāng)創(chuàng)建一個(gè)vue實(shí)例,你都可以傳入一個(gè)選項(xiàng)對(duì)象作為參數(shù),完整的選項(xiàng)對(duì)象,你可能需要查看API文檔。
一個(gè)vue應(yīng)用應(yīng)該由一個(gè)通過(guò)new Vue構(gòu)造的根實(shí)例和許多可嵌套可復(fù)用的組件構(gòu)成,這也就是說(shuō)所有的組件都是vue實(shí)例。
2.數(shù)據(jù)與方法當(dāng)一個(gè)vue實(shí)例被創(chuàng)建完成之后,就會(huì)向它的vue響應(yīng)系統(tǒng)中加入了data對(duì)象中能找到的所有屬性,當(dāng)這些屬性的值發(fā)生改變之后,視圖就會(huì)發(fā)生響應(yīng),也就是更新相應(yīng)的值。我們來(lái)看一個(gè)例子:
//源數(shù)據(jù)對(duì)象 var obj = { name:"eveningwater" }; //構(gòu)建實(shí)例 var vm = new Vue({ data:obj }) //這兩者是等價(jià)的 vm.name === obj.name; //這也就意味著 //修改data對(duì)象里的屬性也會(huì)影響到源數(shù)據(jù)對(duì)象的屬性 vm.name = "waterXi"; obj.name;//"waterXi" //同樣的,修改源數(shù)據(jù)對(duì)象的屬性也會(huì)影響到data對(duì)象里的屬性 obj.name = "stranger"; vm.name;//"stranger"
可能需要注意的就是,只有data對(duì)象中存在的屬性才是響應(yīng)式的,換句話說(shuō),你為源數(shù)據(jù)對(duì)象添加一個(gè)屬性,根本不會(huì)影響到data對(duì)象。如:
obj.sex = "男"; vm.sex;//undefined obj.sex;//"男" obj.sex = "哈哈哈"; vm.sex;//undefined
這也就意味著你對(duì)sex的修改并不會(huì)讓視圖更新,如此一來(lái),你可能需要在data對(duì)象中初始化一些值,如下:
data:{ str:"", bool:false, arr:[], obj:{}, err:null, num:0 }
查看此處具體示例。
只是還有一個(gè)例外Object.freeze(),這個(gè)方法就相當(dāng)于鎖定(凍結(jié))一個(gè)對(duì)象,使得我們無(wú)法修改現(xiàn)有屬性的特性和值,并且也無(wú)法添加新屬性。因此這會(huì)讓vue響應(yīng)系統(tǒng)無(wú)法追蹤變化:
freeze {{ message }}
js代碼如下:
var obj = { message: "hello,vue.js!" } //阻止對(duì)象 Object.freeze(obj); var app = new Vue({ el: "#app", data:obj, methods: { reverseMessage: function() { this.message = this.message.split("").reverse().join(""); } } });
如此一來(lái),無(wú)論我們?cè)趺袋c(diǎn)擊按鈕,都不會(huì)將信息反轉(zhuǎn),甚至頁(yè)面還會(huì)報(bào)錯(cuò)。
可前往此處具體示例自行查看效果。
當(dāng)然除了數(shù)據(jù)屬性以外,vue還暴露了一些有用的實(shí)例屬性和方法,它們通常都帶有$前綴,這樣做的方式是以便與用戶區(qū)分開(kāi)來(lái)。來(lái)看一個(gè)示例:
property
js代碼:
var obj = { name:"eveningwater" } var vm = new Vue({ data:obj, }); //這行代碼表示將vue實(shí)例掛載到id為app的DOM根節(jié)點(diǎn)上,相當(dāng)于在實(shí)例的選項(xiàng)對(duì)象中的el選項(xiàng),即 //el:"#app" vm.$mount(document.querySelector("#app")) //數(shù)據(jù)是相等的 vm.$data === obj;//true //掛載的根節(jié)點(diǎn) vm.$el === document.querySelector("#app");//true //以上兩個(gè)屬性都是實(shí)例上的屬性,接下來(lái)還有一個(gè)watch即監(jiān)聽(tīng)方法是實(shí)例上的方法 vm.$watch("name",function(oldValue,newValue){ //數(shù)據(jù)原來(lái)的值 console.log(oldValue); //數(shù)據(jù)最新的值 console.log(newValue); })
接下來(lái),可以嘗試在瀏覽器控制臺(tái)修改name的值,你就會(huì)發(fā)現(xiàn)watch()方法的作用了。
這個(gè)示例可前往具體示例。
每個(gè)vue實(shí)例在被創(chuàng)建的時(shí)候都會(huì)經(jīng)歷一些初始化的過(guò)程,這其中提供了一些生命周期鉤子函數(shù),這些鉤子函數(shù)代表不同的生命周期階段,這些鉤子函數(shù)的this就代表調(diào)用它的那個(gè)實(shí)例。對(duì)于生命周期,有一張圖:
你不需要立即這張圖所代表的含義,我們來(lái)看一個(gè)示例:
vue life cycle vue生命周期
js代碼:
var obj = { name:"eveningwater" } var app = new Vue({ data:obj, beforeCreate:function(){ //此時(shí)this指向app這個(gè)vue實(shí)例,但并不能得到data屬性,因此this.name的值是undefined console.log("實(shí)例被創(chuàng)建之前,此時(shí)并不能訪問(wèn)實(shí)例內(nèi)的任何屬性" + this.name) } });
關(guān)于生命周期的全部理解,我們需要理解后續(xù)的組件知識(shí),再來(lái)補(bǔ)充,此處跳過(guò)。這個(gè)示例可前往具體示例
4.模板語(yǔ)法vue使用基于HTML的模板語(yǔ)法,在vue的底層是將綁定數(shù)據(jù)的模板渲染成虛擬DOM,并結(jié)合vue的響應(yīng)式系統(tǒng),從而減少操作DOM的次數(shù),vue會(huì)計(jì)算出至少需要渲染多少個(gè)組件。
最簡(jiǎn)單的模板語(yǔ)法莫過(guò)于插值了,vue使用的是Mustache語(yǔ)法(也就是雙大括號(hào)"{{}}")。這個(gè)只能對(duì)文本進(jìn)行插值,也就是說(shuō)無(wú)論是字符串還是標(biāo)簽都會(huì)被當(dāng)作字符串渲染。如:
Mustache {{ greeting }}World!
js代碼:
var obj = { greeting:"Hello,"}; var vm = new Vue({ data:obj }); vm.$mount(document.getElementById("app"));
如此以來(lái)Mustache標(biāo)簽就會(huì)被data對(duì)象上的數(shù)據(jù)greeting給替代,而且我們無(wú)論怎么修改greeting的值,視圖都會(huì)響應(yīng),具體示例。
我們還可以使用v-once指令對(duì)文本進(jìn)行一次性插值,換句話說(shuō),就是這個(gè)指令讓插值無(wú)法被更新:
Mustache {{ greeting }}World!
js代碼:
var obj = { greeting:"Hello,"}; var vm = new Vue({ data:obj }); vm.$mount(document.getElementById("app"));
在瀏覽器控制臺(tái)中我們輸入vm.greeting="stranger!"可以看到視圖并沒(méi)有被更新,這就是這個(gè)指令的作用,我們需要注意這個(gè)指令對(duì)數(shù)據(jù)造成的影響。具體實(shí)例
既然雙大括號(hào)只能讓我插入文本,那要是我們要插入HTML代碼,我們應(yīng)該怎么辦呢?v-html這個(gè)指令就可以讓我們插入真正的HTML代碼。
v-html {{ message }}
js代碼:
var obj = { message:"hello,world!"};
var vm = new Vue({
data:obj
});
vm.$mount(document.getElementById("app"));
頁(yè)面效果如圖所示;
可前往具體示例。
關(guān)于HTML特性,也就是屬性,我們需要用到v-bind指令,例如:
v-bind 使用v-bind指令給該元素添加id屬性
js代碼:
var obj = { propId:"myDiv"}; var vm = new Vue({ data:obj }); vm.$mount(document.getElementById("app"));
打開(kāi)瀏覽器控制臺(tái),定位到該元素,我們就能看到div元素的id屬性為"myDiv",如下圖所示:
具體示例。
在綁定與元素實(shí)際作用相關(guān)的屬性,比如disabled,這個(gè)指令就被暗示為true,在默認(rèn)值是false,null,undefined,""等轉(zhuǎn)換成false的數(shù)據(jù)類型時(shí),這個(gè)指令甚至不會(huì)表現(xiàn)出來(lái)。如下例:
v-bind
js代碼:
var obj = { isDisabled:123}; var vm = new Vue({ data:obj }); vm.$mount(document.getElementById("app"));
這樣一來(lái),無(wú)論我們?cè)趺袋c(diǎn)擊按鈕都沒(méi)用,因?yàn)?b>123被轉(zhuǎn)換成了布爾值true,也就表示按鈕已經(jīng)被禁用了,我們可以打開(kāi)控制臺(tái)看到:
你可以嘗試這個(gè)示例具體示例。
在使用模板插值的時(shí)候,我們可以使用一些JavaScript表達(dá)式。如下例:
expression {{ number + 1 }}
{{ ok ? "確認(rèn)" : "取消" }}
{{message.split("").reverse().join("")}}
元素的id為myDiv
js代碼:
var obj = { number: 123, ok: true, message: "hello,vue.js!", elementId: "Div", color: "red" }; var vm = new Vue({ data: obj }); vm.$mount(document.getElementById("app"));
這些JavaScript表達(dá)式都會(huì)被vue實(shí)例作為JavaScript代碼解析,具體示例。
值得注意的就是有個(gè)限制,只能綁定單個(gè)表達(dá)式,像語(yǔ)句是無(wú)法生效的。如下例:
sentence {{ var number = 1 }}
{{ if(ok){ return "確認(rèn)"} }}
js代碼:
var obj = { number: 123, ok: true }; var vm = new Vue({ data: obj }); vm.$mount(document.getElementById("app"));
像這樣直接使用語(yǔ)句是不行的,瀏覽器控制臺(tái)報(bào)錯(cuò),如下圖:
不信可以自己試試具體示例。
指令(Directives)是帶有v-前綴的特殊特性,通常指令的預(yù)期值就是單個(gè)JavaScript表達(dá)式(v-for除外),例如v-if與v-show指令,前者表示DOM節(jié)點(diǎn)的插入和刪除,后者則是元素的顯隱。所以,指令的職責(zé)就是根據(jù)表達(dá)式值的改變,響應(yīng)式的作用于DOM?,F(xiàn)在我們來(lái)看兩個(gè)示例:
v-if {{ value }}
{{ value }}
{{ value }}
js代碼:
var obj = { value: 1 }; var vm = new Vue({ el: "#app", data() { return obj; } });
運(yùn)行在瀏覽器效果如圖:
現(xiàn)在你可以嘗試在瀏覽器控制臺(tái)更改vm.value = 2和vm.value = 3我們就可以看到頁(yè)面的變化。你也可以狠狠點(diǎn)擊此處具體示例查看和編輯。
我們?cè)倏?b>v-show的示例:
v-show {{ value }}
{{ value }}
{{ value }}
js代碼:
var obj = { value:1 } var vm = new Vue({ data:obj }); vm.$mount(document.querySelector("#app"))
然后查看效果如圖:
嘗試在控制臺(tái)修改vm.value = 2和vm.value = 3我們就可以看到頁(yè)面的變化。你也可以狠狠點(diǎn)擊具體示例查看。
從上面兩個(gè)示例的對(duì)比,我們就可以看出來(lái)v-show與v-if指令的區(qū)別了,從切換效果來(lái)看v-if顯然不如v-show,這說(shuō)明v-if有很大的切換開(kāi)銷,因?yàn)槊恳淮吻袚Q都要不停的執(zhí)行刪除和插入DOM元素操作,而從渲染效果來(lái)看v-if又比v-show要好,v-show只是單純的改變?cè)氐?b>display屬性,而如果我們只想頁(yè)面存在一個(gè)元素之間的切換,那么v-if就比v-show要好,這也說(shuō)明v-show有很大的渲染開(kāi)銷。
而且v-if還可以結(jié)合v-else-if與v-else指令使用,而v-show不能,需要注意的就是v-else必須緊跟v-if或者v-else-if之后。當(dāng)需要切換多個(gè)元素時(shí),我們還可以使用template元素來(lái)包含,比如:
template {{ value }}
{{ value }}
{{ value }}{{ value }}
js代碼:
var obj = { value: 1 }; var vm = new Vue({ el: "#app", data() { return obj; } });
此時(shí)template相當(dāng)于一個(gè)不可見(jiàn)元素,如下圖所示:
嘗試在控制臺(tái)修改vm.value = 2就可以看到效果了,你也可以狠狠的點(diǎn)擊此處具體示例。
對(duì)于可復(fù)用的元素,我們還可以添加一個(gè)key屬性,比如:
key
js代碼:
var obj = { loginType: "username", count:1 }; var vm = new Vue({ el: "#app", data() { return obj; }, methods: { changeType() { this.count++; if (this.count % 3 === 0) { this.loginType = "username"; } else if (this.count % 3 === 1) { this.loginType = "email"; } else { this.loginType = "mobile"; } } } });
效果如圖:
你可以狠狠的點(diǎn)擊具體示例查看。
從這幾個(gè)示例我們也可以看出v-if就是惰性,只有當(dāng)條件為真時(shí),v-if才會(huì)開(kāi)始渲染。值得注意的就是v-if與v-for不建議合在一起使用。來(lái)看一個(gè)示例:
v-if與v-for
- {{ item.value }}
js代碼:
var obj = { list:[ { value:"html", active:false }, { value:"css", active:false }, { value:"javascript", active:true } ] }; var vm = new Vue({ el: "#app", data() { return obj; } });
雖然以上代碼不會(huì)報(bào)錯(cuò),但這會(huì)造成很大的渲染開(kāi)銷,因?yàn)?b>v-for優(yōu)先級(jí)高于v-if,這就造成每次執(zhí)行v-if指令時(shí)總要先執(zhí)行v-for遍歷一遍數(shù)據(jù)。你可以點(diǎn)擊此處具體示例查看。
遇到這種情況,我們可以使用計(jì)算屬性。如:
v-if和v-for
- {{ item.value }}
js代碼:
var obj = { list: [ { value: "html", active: false }, { value: "css", active: false }, { value: "javascript", active: true } ] }; var vm = new Vue({ el: "#app", //先過(guò)濾一次數(shù)組 computed: { newList: function() { return this.list.filter(function(item) { return item.active; }); } }, data() { return obj; } });
如此一來(lái),就減少了渲染開(kāi)銷,你可以狠狠點(diǎn)擊這里具體示例查看。
指令的用法還遠(yuǎn)不止如此,一些指令是可以帶參數(shù)的,比如v-bind:title,在這里title其實(shí)就是被作為參數(shù)?;旧螲TML5屬性都可以被用作參數(shù)。比如圖片路徑的src屬性,再比如超鏈接的href屬性,甚至事件的添加也屬于參數(shù),如v-on:click中的click其實(shí)就是參數(shù)。來(lái)看一個(gè)示例:
param
js代碼:
var obj = { url: "https://segmentfault.com/", src:"http://eveningwater.com/project/imggallary/img/15.jpg" }; var vm = new Vue({ el: "#app", data() { return obj; } });
效果如圖所示:
你可以點(diǎn)擊此處具體示例查看。
v-on指令還可以添加修飾符,v-bind與v-on指令還可以縮寫成:和@??s寫對(duì)于我們?cè)诜爆嵉氖褂弥噶畹捻?xiàng)目當(dāng)中是一個(gè)很不錯(cuò)的幫助。
5.計(jì)算屬性模板表達(dá)式提供給我們處理簡(jiǎn)單的邏輯,對(duì)于更復(fù)雜的邏輯,我們應(yīng)該使用計(jì)算屬性。來(lái)看兩個(gè)示例的對(duì)比:
mustache {{ message.split("").reverse().join("") }}
js代碼:
var obj = { message:"hello,vue.js!" } var vm = new Vue({ data:obj }) vm.$mount(document.querySelector("#app"))
第二個(gè)示例:
mustache {{ reverseMessage }}
js代碼:
var obj = { message:"hello,vue.js!" } var vm = new Vue({ data:obj, computed:{ reverseMessage:function(){ return this.message.split("").reverse().join(""); } } }) vm.$mount(document.querySelector("#app"))
與第一個(gè)示例有所不同的就是在這個(gè)示例當(dāng)中,我們申明了一個(gè)計(jì)算屬性reverseMessage,并且提供了一個(gè)getter函數(shù)將這個(gè)計(jì)算屬性同數(shù)據(jù)屬性message綁定在一起,也許有人會(huì)有疑問(wèn)getter函數(shù)到底在哪里呢?
如果我們將以上示例修改一下:
var obj = { message:"hello,vue.js!" } var vm = new Vue({ data:obj, computed:{ reverseMessage:{ get:function(){ return this.message.split("").reverse().join(""); } } } }) vm.$mount(document.querySelector("#app"))
相信如此一來(lái),就能明白了。你可以狠狠點(diǎn)擊此處具體示例。你可以通過(guò)控制臺(tái)修改message的值,只要message的值發(fā)生改變,那么綁定的計(jì)算屬性就會(huì)發(fā)生改變。事實(shí)上,在使用reverseMessage綁定的時(shí)候,我們還可以寫成調(diào)用方法一樣的方式,如:
mustache {{ reverseMessage() }}
js代碼:
var obj = { message:"hello,vue.js!" } var vm = new Vue({ data:obj, computed:{ reverseMessage:function(){ return this.message.split("").reverse().join(""); } } }) vm.$mount(document.querySelector("#app"))
那么這兩者有何區(qū)別呢?雖然兩者的結(jié)果都一樣,但計(jì)算屬性是根據(jù)依賴進(jìn)行緩存的,只有相關(guān)依賴發(fā)生改變時(shí)它們才會(huì)重新求值。比如這里計(jì)算屬性綁定的依賴就是message屬性,一旦message屬性發(fā)生改變時(shí),那么計(jì)算屬性就會(huì)重新求值,如果沒(méi)有改變,那么計(jì)算屬性將會(huì)緩存上一次的求值。這也意味著,如果計(jì)算屬性綁定的是方法,那么計(jì)算屬性不是響應(yīng)式的。如下:
mustache {{ date }}
js代碼:
var vm = new Vue({ data:obj, computed:{ reverseMessage:function(){ return Date.now(); } } }) vm.$mount(document.querySelector("#app"))
與調(diào)用方法相比,調(diào)用方法總會(huì)在頁(yè)面重新渲染之后再次調(diào)用方法。我們?yōu)槭裁葱枰彺?,假設(shè)你要計(jì)算一個(gè)性能開(kāi)銷比較大的數(shù)組,而且如果其它頁(yè)面也會(huì)依賴于這個(gè)計(jì)算屬性,如果沒(méi)有緩存,那么無(wú)論是讀取還是修改都會(huì)去多次修改它的getter函數(shù),這并不是我們想要的。
計(jì)算屬性默認(rèn)只有getter函數(shù),讓我們來(lái)嘗試使用一下setter函數(shù),如下:
computed
js代碼:
var vm = new Vue({ el: "#app", data: { first_name: "li", last_name: "qiang" }, computed: { name: { get: function() { return this.first_name + " " + this.last_name; }, set: function(newValue) { var names = newValue.split(" "); this.first_name = names[0]; this.last_name = names[names.length - 1]; } } } });
現(xiàn)在,我們只需要修改vm.name的值就可以看到first_name和last_name的值相應(yīng)的也改變了。你可以狠狠點(diǎn)擊此處具體示例。
6.偵聽(tīng)器雖然計(jì)算屬性在大多數(shù)情況下更合適,但有時(shí)候也可以使用偵聽(tīng)器。vue通過(guò)watch選項(xiàng)提供一個(gè)方法來(lái)響應(yīng)數(shù)據(jù)的變化。如:
watch 可以給我提出一個(gè)問(wèn)題,然后我來(lái)回答?
{{ answer }}
js代碼:
var vm = new Vue({ el:"#app", data(){ return{ answer:"我不能回答你除非你提出一個(gè)問(wèn)題!", question:"", answerImg:"" } }, created:function(){ // `_.debounce` 是一個(gè)通過(guò) Lodash 限制操作頻率的函數(shù)。 // 在這個(gè)例子中,我們希望限制訪問(wèn) yesno.wtf/api 的頻率 // AJAX 請(qǐng)求直到用戶輸入完畢才會(huì)發(fā)出。想要了解更多關(guān)于 // `_.debounce` 函數(shù) (及其近親 `_.throttle`) 的知識(shí), // 請(qǐng)參考:https://lodash.com/docs#debounce this.debounceGetAnswer = _.debounce(this.getAnswer,500); }, //如果question值發(fā)生改變 watch:{ question:function(oldValue,newValue){ this.answer="正在等待你停止輸入!"; this.debounceGetAnswer(); } }, methods:{ getAnswer:function(){ //如果問(wèn)題沒(méi)有以問(wèn)號(hào)結(jié)束,則返回 if(this.question.indexOf("?") === -1){ this.answer = "提出的問(wèn)題需要用問(wèn)號(hào)結(jié)束!"; return; } this.answer = "請(qǐng)稍等"; var self = this; fetch("https://yesno.wtf/api").then(function(response){ //fetch發(fā)送請(qǐng)求,json()就是返回?cái)?shù)據(jù) response.json().then(function(data) { self.answer = _.capitalize(data.answer); self.answerImg = _.capitalize(data.image); }); }).catch(function(error){ self.answer = "回答失敗,請(qǐng)重新提問(wèn)!"; console.log(error); }) } } })
現(xiàn)在咱們來(lái)看一下效果:
你可以狠狠點(diǎn)擊此處具體示例查看。
當(dāng)在頁(yè)面中有一些數(shù)據(jù)需要根據(jù)其它數(shù)據(jù)的變動(dòng)而改變時(shí),就很容易濫用偵聽(tīng)器watch。這時(shí)候命令式的偵聽(tīng)還不如計(jì)算屬性,請(qǐng)看:
watch {{ fullName }}
js代碼:
var vm = new Vue({ el:"#app", data:{ firstName:"li", lastName:"qiang", fullName:"li qiang" }, watch:{ firstName:function(val){ this.fullName = val + " " + this.lastName; }, lastName:function(val){ this.fullName = this.firstName + " " + val; } } })
再看通過(guò)計(jì)算屬性實(shí)現(xiàn)的:
computed {{ fullName }}
js代碼:
var vm = new Vue({ el:"#app", data:{ firstName:"li", lastName:"qiang" }, computed:{ fullName:function(){ return this.firstNmae + " " + this.lastName; } } })
通過(guò)計(jì)算屬性實(shí)現(xiàn)的功能看起來(lái)更好,不是嗎?你可以自行嘗試具體示例(watch)與具體示例(computed)進(jìn)行對(duì)比。
8.class與style綁定操作元素的class和style是構(gòu)建一個(gè)頁(yè)面所常見(jiàn)的需求,因?yàn)樗鼈兌际菍傩?,所以利?b>v-bind指令就可以操作元素的class和style樣式。如;
class 添加一個(gè)class類,改變字體顏色為紅色。
js代碼如下;
var vm = new Vue({ el:"#app", data:{ className:"font-red" } })
你可以狠狠點(diǎn)擊此處具體示例 查看。
再來(lái)看一個(gè)簡(jiǎn)單綁定style的示例。
style 改變?cè)氐淖煮w顏色為紅色。
js代碼:
var vm = new Vue({ el:"#app", data:{ styleProp:"color:#f00;" } })
你可以狠狠點(diǎn)擊此處具體示例查看。
這只是class與style的簡(jiǎn)單用法,vue.js專門在這方面做了增強(qiáng),使得綁定class和style 的值可以是對(duì)象,也可以是數(shù)組,如:
class 改變字體的顏色
js代碼:
var vm = new Vue({ el:"#app", data:{ isRed:true, isBlue:false } })
我們可以看到頁(yè)面效果如圖:
你還可以通過(guò)控制臺(tái)修改vm.isBlue或vm.isRed的值,這充分說(shuō)明這兩個(gè)值是響應(yīng)式的。如:
你可以狠狠的點(diǎn)擊此處具體示例查看。
同樣的,style一樣也可以使用對(duì)象語(yǔ)法,如:
style 字體大小為18px,字體顏色為紅色,并且加粗的字體。
js代碼:
var vm = new Vue({ el: "#app", data: { fontColor: "#f00", font18: "18px", fontBold:"bold" } });
效果如圖:
我們一樣可以修改其中的值,這些值也是響應(yīng)式的,比如修改vm.fontColor="#0f0"就表示將字體顏色改變?yōu)樗{(lán)色。從上例我們也可以看出,我們可以使用駝峰式 (camelCase) 或短橫線分隔 (kebab-case,需要用單引號(hào)括起來(lái))來(lái)定義css屬性名。
你可以狠狠點(diǎn)擊此處具體示例查看。
當(dāng)然在更多時(shí)候,我們直接綁定一個(gè)對(duì)象更有利于讓模板變得清晰,也方便我們理解。
style 字體大小為18px,字體顏色為紅色,并且加粗的字體。
js代碼:
var vm = new Vue({ el: "#app", data: { styleObject:{ fontSize:"18px", color:"#f00", "font-weight":"bold" } } });
這也是一樣的效果,你可以點(diǎn)擊此處具體示例查看。
除了對(duì)象語(yǔ)法,數(shù)組語(yǔ)法也同樣適用于class和style,如:
class 顏色為紅色大小為18px的字體
js代碼:
var vm = new Vue({ el: "#app", data: { fontColor: "font-red", fontSize: "font-18" } });
運(yùn)行效果如圖:
你同樣可以修改class的名字,諸如vm.fontColor="font-blue",這樣頁(yè)面就會(huì)將font-red更改為font-blue,這畢竟是響應(yīng)式的。你可以狠狠點(diǎn)擊此處具體示例查看。
同樣的,style也能如此做,如:
style 顏色為紅色大小為18px的字體
js代碼:
var vm = new Vue({ el: "#app", data: { colorF: { color:"#f00" }, sizeF: { fontSize:"18px" } } });
這里尤其注意如下的寫法是錯(cuò)誤的,vue.js并不能渲染出樣式:
//這說(shuō)明style綁定的數(shù)組項(xiàng)只能是一個(gè)對(duì)象,而不能是字符串 var vm = new Vue({ el: "#app", data: { colorF: "color:#f00;", sizeF: "font-size:18px;" } });
同樣,我們注意修改值的時(shí)候也應(yīng)該修改成一個(gè)對(duì)象,如:
vm.sizeF = { "font-size":"20px" }
這點(diǎn)是需要注意的,另外在遇到帶有前綴的css屬性,如transition時(shí),我們不必寫前綴,因?yàn)?b>vue會(huì)自動(dòng)幫我們添加前綴。你可以狠狠點(diǎn)擊此處具體示例查看。
style的用法還不止如此,我們還可以綁定多重值。如下:
style 顏色為紅色大小為18px的字體
js代碼:
var vm = new Vue({ el: "#app", data: { webkitD:"-webkit-flex", nomarD:"flex" } });
這樣一來(lái),瀏覽器會(huì)根據(jù)支持-webkit-flex或flex而采用支持的寫法,這個(gè)是在vue2.3.0+版本中增加的功能。你可以點(diǎn)擊此處具體示例查看。
9.條件渲染v-if指令用于條件性的渲染一塊內(nèi)容,這個(gè)指令只在它綁定的值為truthy的時(shí)候才會(huì)渲染內(nèi)容。例如:
v-if
你可以狠狠點(diǎn)擊此處具體示例查看效果。
v-if指令也可以與v-else指令結(jié)合使用,注意v-else必須緊跟v-if或者v-else-if之后。比如:
v-if
你可以狠狠點(diǎn)擊此處具體示例查看效果。
v-if也可以直接在標(biāo)簽上使用,這種情況下,我們通常是為了切換多個(gè)元素,因?yàn)?b>v-if必須添加到一個(gè)元素上,而且會(huì)把template當(dāng)作不可見(jiàn)元素來(lái)渲染,也就是說(shuō)最終渲染不會(huì)包含template元素。比如:
v-if 呵呵呵
哈哈哈
嘻嘻嘻嘿嘿嘿
你可以狠狠點(diǎn)擊此處具體示例查看效果。
在vue2.1.0新增了v-else-if,顧名思義,也就是緊跟v-if之后,v-else之前的指令,可以使用多個(gè)v-else-if指令。比如:
v-if 哈哈哈
嘿嘿嘿嘻嘻嘻呵呵呵
你可以狠狠點(diǎn)擊此處具體示例查看效果。在這些示例中,只要綁定的是在vue實(shí)例data選項(xiàng)中的數(shù)據(jù),那么值就是響應(yīng)式的,我們可以直接在控制臺(tái)中修改,比如以上的vm.type = 1,我們就可以看到頁(yè)面的的元素以及內(nèi)容被改變,并重新渲染。
由于vue是簡(jiǎn)單的復(fù)用元素,而不是重新渲染元素,因此,這會(huì)讓vue非常的高效,但這不可避免出現(xiàn)了一個(gè)問(wèn)題,如下:
v-if
你可以狠狠點(diǎn)擊此處具體示例查看效果。在輸入框中輸入值,然后再點(diǎn)擊切換按鈕,你會(huì)發(fā)現(xiàn)input的內(nèi)容并沒(méi)有被清空,這也說(shuō)明vue并不是重新渲染元素,而是高效的復(fù)用元素而已。再實(shí)際開(kāi)發(fā)中,這樣肯定是不符合需求的,那么我們應(yīng)該如何解決這個(gè)問(wèn)題呢?
還好,vue提供了一個(gè)key屬性,我們只需要給每個(gè)復(fù)用的元素綁定一個(gè)key屬性,用于區(qū)分它們是不同的元素。如下:
v-if
現(xiàn)在你再嘗試在輸入框中輸入值,然后點(diǎn)擊切換按鈕,就會(huì)發(fā)現(xiàn)值會(huì)被清空了。請(qǐng)點(diǎn)擊具體示例查看效果。
需要注意的是label元素其實(shí)也是被復(fù)用了,因?yàn)樗鼈儧](méi)有添加key屬性。
v-show的指令用法跟v-if差不多,唯一需要注意的區(qū)別就是v-show僅僅只是改變了元素的display屬性而已,其DOM元素仍然存在于文檔中,
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/108808.html
摘要:哪吒別人的看法都是狗屁,你是誰(shuí)只有你自己說(shuō)了才算,這是爹教我的道理。哪吒去他個(gè)鳥(niǎo)命我命由我,不由天是魔是仙,我自己決定哪吒白白搭上一條人命,你傻不傻敖丙不傻誰(shuí)和你做朋友太乙真人人是否能夠改變命運(yùn),我不曉得。我只曉得,不認(rèn)命是哪吒的命。 showImg(https://segmentfault.com/img/bVbwiGL?w=900&h=378); 出處 查看github最新的Vue...
摘要:前言一個(gè)包含的簡(jiǎn)單,從第一個(gè)開(kāi)始,依次深入學(xué)習(xí),即可快速上手強(qiáng)大的。 前言 一個(gè)包含 vue-router的簡(jiǎn)單demos,從第一個(gè)demo開(kāi)始,依次深入學(xué)習(xí),即可快速上手強(qiáng)大的vue-router。 如何使用 安裝模塊pure 或 http-server來(lái)啟動(dòng)服務(wù)器npm install -g puer or npm install -g http-server 克隆倉(cāng)庫(kù) 啟動(dòng)服...
摘要:第一集從零開(kāi)始實(shí)現(xiàn)環(huán)境的搭建工程定位本套工程定位在端針對(duì)的組件庫(kù)名字的由來(lái)是我從年養(yǎng)到現(xiàn)在的一直大金毛是我的吉祥物原因本人上一份工作參與了大型的保險(xiǎn)公司后臺(tái)管理系統(tǒng)的搭建對(duì)的端框架有過(guò)一定的了解感受到了他們真的很強(qiáng)大同時(shí)也存在少許的不足其實(shí) 第一集: 從零開(kāi)始實(shí)現(xiàn)(環(huán)境的搭建) 工程定位: 本套工程, 定位在pc端針對(duì)vue的ui組件庫(kù) 名字的由來(lái) cc是我從2015年養(yǎng)到現(xiàn)在的...
摘要:最近終于痛定思痛,做了一個(gè)應(yīng)用,目前的產(chǎn)品確實(shí)很一般,但決定以此為起步,逐步完善逐步提高。是以提供游戲下載游戲禮包發(fā)放為核心的移動(dòng)端應(yīng)用??梢院?jiǎn)單理解成一個(gè)游戲的應(yīng)用市場(chǎng)。在寫后端的時(shí)候,產(chǎn)出了一個(gè)基于的授權(quán)的。 移動(dòng)互聯(lián)網(wǎng)時(shí)代,我不想只當(dāng)一個(gè)后端工程師,是時(shí)候?qū)W習(xí)一些新的東西了! 一直以來(lái)想要學(xué)習(xí)一些前端的知識(shí),擴(kuò)寬自己的技術(shù)棧,但是一直以來(lái)對(duì)前端都是進(jìn)行了解,沒(méi)有用一個(gè)產(chǎn)品把這些東...
摘要:第八集從零開(kāi)始實(shí)現(xiàn)輸入框組件本集定位組件是交互的一大利器他與用戶的交流最為密切所以奠定了他在組件界的重要地位也算是一種如果可以的話本集也會(huì)一起說(shuō)完畢竟是一個(gè)類型的一起學(xué)完收獲會(huì)很大古人云組件不封輸入框,一到面試就發(fā)慌一簡(jiǎn)介大家如果對(duì)這個(gè) 第八集: 從零開(kāi)始實(shí)現(xiàn)(輸入框input,textarea組件) 本集定位: input組件是交互的一大利器, 他與用戶的交流最為密切, 所以奠...
閱讀 3262·2021-10-21 17:50
閱讀 3268·2021-10-08 10:05
閱讀 3404·2021-09-22 15:04
閱讀 595·2019-08-30 14:00
閱讀 1970·2019-08-29 17:01
閱讀 1520·2019-08-29 15:16
閱讀 3231·2019-08-26 13:25
閱讀 863·2019-08-26 11:44