目錄:javascript
內容:css
1、Vue內部指令:html
一、v-if v-else&v-showvue
v-if與v-show都是選擇性顯示內容的指令,可是兩者之間有區別:java
一、v-if:判斷是否加載,在須要的時候加載,減小服務器壓力node
二、v-show:調整css display屬性,使客戶端操做更加流暢python
v-if:jquery
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> <div v-if="islog">加載</div> <!--<div v-else-if="iselse">能夠加載</div>--> <div v-else="islog">不加載</div> </div> <script type="text/javascript"> window.onload=function () { var app=new Vue({ el:'#app', data:{ islog: false, iselse: true //若是islog=true時,後面兩個不顯示 //當islog爲false v-else-if爲true 顯示第二個內容 ,當第二個爲alse顯示最後一個 } }) } </script> </body> </html>
v-show:webpack
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> <div v-show="islog">加載</div> </div> <script type="text/javascript"> window.onload=function () { var app=new Vue({ el:'#app', data:{ islog: true } }) } </script> </body> </html>
二、v-for 循環模式git
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> <ul> <li v-for="item in items"> {{item}} </li> </ul> </div> <script type="text/javascript"> window.onload=function () { var app=new Vue({ el:'#app', data:{ items: [45,32,77,36,8,54] } }) } </script> </body> </html>
2. 數組排序循環:普通排序有個問題就是隻能按照一位一位來進行,因此須要下面的方法來修正
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> <ul> <li v-for="item in sortItems"> {{item}} </li> </ul> </div> <script type="text/javascript"> window.onload=function () { var app=new Vue({ el:'#app', data:{ items: [45,32,77,36,8,54] }, computed:{ //使用computed對items進行排序 sortItems:function () {//在排序時,computed中的變量名必須和原來不一樣 return this.items.sort(); } } }) } </script> </body> </html>
3. 加強型數字數組排序:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> <ul> <li v-for="item in sortItems"> {{item}} </li> </ul> </div> <script type="text/javascript"> window.onload=function () { var app=new Vue({ el:'#app', data:{ items: [45,32,77,36,8,54] }, computed:{ //使用computed對items進行排序 sortItems:function () {//在排序時,computed中的變量名必須和原來不一樣 return this.items.sort(sortNumber);//引入排序函數 } } }); function sortNumber(a,b) {//添加排序函數 return a-b; } }; </script> </body> </html>
4. 數組中增長對象排序:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> <ul> <li v-for="item in sortItems"> {{item}} </li> </ul> <ul> <li v-for="(student,index) in sortStudent"> <!-- Vue2.0中排序時,index在value後面 --> {{index}}: {{student.name}}-{{student.age}} </li> </ul> </div> <script type="text/javascript"> window.onload=function () { var app=new Vue({ el:'#app', data:{ items: [45,32,77,36,8,54], students:[ {name:'JSPang',age:33}, {name:'JS',age:22}, {name:'Pang',age:14}, {name:'keke',age:50} ] }, computed:{ //使用computed對items進行排序 sortItems:function () {//在排序時,computed中的變量名必須和原來不一樣 return this.items.sort(sortNumber);//引入排序函數 }, sortStudent: function () { return sortByKey(this.students, 'age'); } } }); function sortNumber(a,b) {//添加排序函數 return a-b; }; //數組對象方法排序: function sortByKey(arrary,key) { return arrary.sort(function (a,b) { var x=a[key]; var y=b[key]; return ((x<y)?-1:((x>y)?1:0)); }); } }; </script> </body> </html>
三、v-text v-html
其中v-html不推薦使用,由於會形成代碼泄漏引起安全問題,v-text能夠改善因爲各類問題而致使模板{{}}沒有渲染成功的問題,若是沒有渲染成功v-text不顯示內容
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app" v-text="message"> </div> <script type="text/javascript"> window.onload=function () { var app=new Vue({ el:'#app', data:{ message: 'hello world' } }); }; </script> </body> </html>
四、v-on
v-on對應的是綁定事件並用來監聽
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> 本廠比賽得分: <span v-text="record"></span><br> <button v-on:click="addscore">加分</button> <button @click="reducescore">減分</button> <br> <input type="text" @keyup.enter="onEnter" v-model="incrscore"> </div> <script type="text/javascript"> window.onload=function () { var app=new Vue({ el:'#app', data:{ record: 0, incrscore:0 }, methods:{ addscore:function () { this.record++ }, reducescore:function () { if(this.record <= 0){ this.record = 0 }else{ this.record-- } }, onEnter:function () { this.record=this.record+parseInt(this.incrscore);//有坑 須要將後面轉換爲數字形式 } } }); }; </script> </body> </html>
五、v-model
雙向數據綁定
v-model分爲幾個不一樣類型:
一、文本框類型:
1.v-model.lazy表示在光標離開後才生效
2.v-model.number表示只能夠輸入數字
3.v-model.trim表示去空格
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> <p> <h3>文本框</h3> <p >你想表達的文字是: <span v-text="message"></span></p> <p>普通類型:<input type="text" v-model="message"></p> <p>lazy:<input type="text" v-model.lazy="message"></p> <p>number:<input type="text" v-model.number="message"></p> <p>trim:<input type="text" v-model.trim="message"></p> </p> <p> <h3>多區域框</h3> <p >你想表達的文字是: <span v-text="message"></span></p> <p></p> </p> </div> <script type="text/javascript"> window.onload = function () { var app = new Vue({ el: '#app', data: { message: '' } }) } </script> </body> </html>
二、多區域框
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> <p> <h3>文本框</h3> <p >你想表達的文字是: <span v-text="message"></span></p> <p>普通類型:<input type="text" v-model="message"></p> <p>lazy:<input type="text" v-model.lazy="message"></p> <p>number:<input type="text" v-model.number="message"></p> <p>trim:<input type="text" v-model.trim="message"></p> </p> <p> <h3>多區域框</h3> <p >你想表達的文字是: <span v-text="message"></span></p> <p><textarea cols="30" rows="10" v-model="message"></textarea></p> </p> </div> <script type="text/javascript"> window.onload = function () { var app = new Vue({ el: '#app', data: { message: '' } }) } </script> </body> </html>
三、多選框選中一個值
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> <p> <h3>文本框</h3> <p >你想表達的文字是: <span v-text="message"></span></p> <p>普通類型:<input type="text" v-model="message"></p> <p>lazy:<input type="text" v-model.lazy="message"></p> <p>number:<input type="text" v-model.number="message"></p> <p>trim:<input type="text" v-model.trim="message"></p> </p> <p> <h3>多區域框</h3> <p >你想表達的文字是: <span v-text="message"></span></p> <p><textarea cols="30" rows="10" v-model="message"></textarea></p> </p> <p> <h3>多選框綁定一個值</h3> <input type="checkbox" id="isTrue" v-model="isTrue"> <label for="isTrue"><span v-text="isTrue"></span></label> </p> </div> <script type="text/javascript"> window.onload = function () { var app = new Vue({ el: '#app', data: { message: '', isTrue:true } }) } </script> </body> </html>
四、多選框選中數組
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> <p> <h3>文本框</h3> <p >你想表達的文字是: <span v-text="message"></span></p> <p>普通類型:<input type="text" v-model="message"></p> <p>lazy:<input type="text" v-model.lazy="message"></p> <p>number:<input type="text" v-model.number="message"></p> <p>trim:<input type="text" v-model.trim="message"></p> </p> <p> <h3>多區域框</h3> <p >你想表達的文字是: <span v-text="message"></span></p> <p><textarea cols="30" rows="10" v-model="message"></textarea></p> </p> <p> <h3>多選框綁定一個值</h3> <input type="checkbox" id="isTrue" v-model="isTrue"> <label for="isTrue"><span v-text="isTrue"></span></label> </p> <p> <h3>多選框綁定數組</h3> <input type="checkbox" id="jspang" value="jspang" v-model="web_names"> <label for="jspang">jspang</label> <input type="checkbox" id="panda" value="panda" v-model="web_names"> <label for="panda">panda</label> <input type="checkbox" id="pangzi" value="pangzi" v-model="web_names"> <label for="pangzi">pangzi</label> <p v-text="web_names"></p> </p> </div> <script type="text/javascript"> window.onload = function () { var app = new Vue({ el: '#app', data: { message: '', isTrue:true, web_names:[] } }) } </script> </body> </html>
五、單選框
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> <p> <h3>文本框</h3> <p >你想表達的文字是: <span v-text="message"></span></p> <p>普通類型:<input type="text" v-model="message"></p> <p>lazy:<input type="text" v-model.lazy="message"></p> <p>number:<input type="text" v-model.number="message"></p> <p>trim:<input type="text" v-model.trim="message"></p> </p> <p> <h3>多區域框</h3> <p >你想表達的文字是: <span v-text="message"></span></p> <p><textarea cols="30" rows="10" v-model="message"></textarea></p> </p> <p> <h3>多選框綁定一個值</h3> <input type="checkbox" id="isTrue" v-model="isTrue"> <label for="isTrue"><span v-text="isTrue"></span></label> </p> <p> <h3>多選框綁定數組</h3> <input type="checkbox" id="jspang" value="jspang" v-model="web_names"> <label for="jspang">jspang</label> <input type="checkbox" id="panda" value="panda" v-model="web_names"> <label for="panda">panda</label> <input type="checkbox" id="pangzi" value="pangzi" v-model="web_names"> <label for="pangzi">pangzi</label> <p v-text="web_names"></p> </p> <p> <h3>單選框綁定</h3> <input type="radio" id="sex1" value="male" v-model="gender"> <label for="sex1">男</label> <input type="radio" id="sex2" value="female" v-model="gender"> <label for="sex2">女</label> <p>你選中的性別是:<span v-text="gender"></span></p> </p> <p> </div> <script type="text/javascript"> window.onload = function () { var app = new Vue({ el: '#app', data: { message: '', isTrue:true, web_names:[], gender:'male' } }) } </script> </body> </html>
六、v-bind
v-bind能夠綁定資源也能夠綁定類
一、資源綁定
img操做:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> <p> <h3>資源綁定</h3> <p><img :src="srcUrl" alt="" width="200px"/></p> </p> </div> <script type="text/javascript"> window.onload=function () { var app=new Vue({ el:'#app', data:{ srcUrl: 'https://www.baidu.com/img/bd_logo1.png' } }) } </script> </body> </html>
a操做:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> <p> <h3>資源綁定</h3> <p><img :src="srcUrl" alt="" width="200px"/></p> <p><a :href="aurl">點擊</a></p> </p> </div> <script type="text/javascript"> window.onload=function () { var app=new Vue({ el:'#app', data:{ srcUrl: 'https://www.baidu.com/img/bd_logo1.png', aurl: 'https://www.baidu.com' } }) } </script> </body> </html>
二、類操做
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .classA{ color: red; } .classB{ font-size: 30px; } </style> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> <p> <h3>資源綁定</h3> <p><img :src="srcUrl" alt="" width="200px"/></p> <p><a :href="aurl">點擊</a></p> </p> <p> <h3>類操做</h3> <p :class="classname">1.綁定class</p> <p :class="{classA:isok}">2.綁定class判斷</p> <p :class="[classA,classB]">3.綁定class數組</p> <p :class="isok?classA:classB">4.綁定class數組三元運算</p> <p :style="{color:red,fontSize:font}">5.style綁定</p> <p :style="styeobj">6.style綁定對象</p> <hr> <div> <input type="checkbox" id="isok" v-model="isok"> <label for="isok">綁定->{{isok}}</label> </div> </p> </div> <script type="text/javascript"> window.onload=function () { var app=new Vue({ el:'#app', data:{ srcUrl: 'https://www.baidu.com/img/bd_logo1.png', aurl: 'https://www.baidu.com', classname: 'classA', isok:false, classA:'classA', classB:'classB', red:'red', font:'40px', styeobj:{ color:'green', fontSize:'50px' } } }) } </script> </body> </html>
七、v-pre v-cloak v-once
v-pre:不渲染使用v-pre
v-cloak:所有渲染完畢才顯示
v-once:只渲染一次(v-model操做不對今生效)
2、全局API
全局API並不在構造器裏,而是先聲明全局變量或者直接在Vue上定義一些新功能,Vue內置了一些全局API,好比咱們今天要學習的指令Vue.directive。說的簡單些就是,在構造器外部用Vue提供給咱們的API函數來定義新的功能。
一、Vue.directive自定義指令
Vue.directive能夠建立自定義指令完成某些特定任務,好比能夠定義一個v-gavin的指令,做用是讓文字變成綠色
爲了實現這個功能,能夠寫一個簡單的demo:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> <div v-text="message" v-gavin="color"></div> <button @click="add">增長</button> </div> <script type="text/javascript"> window.onload = function () { Vue.directive('gavin',function (el,binding,vnode) { console.log(el); console.log(binding); el.style='color:'+binding.value; }) var app = new Vue({ el: '#app', data: { message: 0, color: 'red' }, methods: { add: function () { this.message++ } } }) } </script> </body> </html>
fucntion函數中三個參數:
el:指令所綁定的元素,能夠用來直接操做DOM
binding:一個對象,包含指令的不少信息
vnode:Vue編譯生成的虛擬節點
在自定義指令存在生命週期的概念,它包含五個生命週期也叫作五個鉤子函數,分別是:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> <div v-text="message" v-gavin="color"></div> <button @click="add">增長</button> <button onclick="unbind()">解綁</button> </div> <script type="text/javascript"> window.onload = function () { function unbind() { app.$destroy();//Vue提供的銷燬綁定的函數 $destory() }; Vue.directive('gavin',{ bind:function () { console.log('1. bind'); }, inserted:function(){ console.log('2. inserted'); }, update:function(el,binding){ console.log('3. update'); el.style='color:'+binding.value }, componentUpdated:function(){ console.log('4. componentUpdated'); }, unbind:function(){ console.log('5. unbind'); }}) var app = new Vue({ el: '#app', data: { message: 0, color: 'red' }, methods: { add: function () { this.message++ } } }) } </script> </body> </html>
二、Vue.extend構造器的延伸
Vue.extend 返回的是一個「擴展實例構造器」,也就是預設了部分選項的Vue實例構造器。常常服務於Vue.component用來生成組件,能夠簡單理解爲當在模板中遇到該組件名稱做爲標籤的自定義元素時,會自動調用「擴展實例構造器」來生產組件實例,並掛載到自定義元素上。
能夠構建一個小demo來演示一下無參數標籤的實例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"></div> <author></author> <script type="text/javascript"> var authorExtend = Vue.extend({ template:"<p><a :href='authorUrl'><span v-text='authorName'></span></a></p>", data:function () { return{ authorName:'Gavin', authorUrl:'https://www.baidu.com' } } }) new authorExtend().$mount('author')//mount綁定,能夠代替new Vue({el: 'app方式'}) new authorExtend().$mount('#app')//能夠相似於jquery方式綁定 </script> </body> </html>
三、Vue.set
Vue.set 的做用就是在構造器外部操做構造器內部的數據、屬性或者方法。好比在vue構造器內部定義了一個count爲1的數據,咱們在構造器外部定義了一個方法,要每次點擊按鈕給值加1.就須要用到Vue.set。
什麼是外部數據,就是不在Vue構造器裏裏的data處聲明,而是在構造器外部聲明,而後在data處引用就能夠了。外部數據的加入讓程序更加靈活,咱們能夠在外部獲取任何想要的數據形式,而後讓data引用。
demo以下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> {{count}} {{name}} {{arr}} </div> <script type="text/javascript"> window.onload=function () { var outData ={ count:1, name: 'Gain', arr: ['aaa','bbb','ccc'] } var app=new Vue({ el:'#app', data: outData//引用外部數據 }) } </script> </body> </html>
修改外部數據的三種方式:
一、outData++
二、app.count++
三、Vue.set(outData,'count',4); //outData我、是外部數據 count是它裏面的一項 4表示須要改變爲4
因爲Javascript的限制,Vue不能自動檢測如下變更的數組。
*當你利用索引直接設置一個項時,vue不會爲咱們自動更新。
*當你修改數組的長度時,vue不會爲咱們自動更新。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <script type="text/javascript" src="vue.js"></script> <title>Vue.set 全局操做</title> </head> <body> <h1>Vue.set 全局操做</h1> <hr> <div id="app"> <ul> <li v-for=" aa in arr">{{aa}}</li> </ul> </div> <button onclick="add()">外部添加</button> <script type="text/javascript"> function add(){ console.log("我已經執行了"); // app.arr[1]='ddd';//使用該方式無法改變數組內數據 Vue.set(app.arr,1,'d'); } var outData={ arr:['aaa','bbb','ccc'] }; var app=new Vue({ el:'#app', data:outData }) </script> </body> </html>
這時咱們的界面是不會自動跟新數組的,咱們須要用Vue.set(app.arr,1,’d’)來設置改變,vue纔會給咱們自動更新,這就是Vue.set存在的意義。
四、Vue生命週期
Vue一共有10個生命週期函數,咱們能夠利用這些函數在vue的每一個階段都進行操做數據或者改變內容。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> {{message}} <button @click="add">add</button></div> <button onclick="des()">des</button> <script type="text/javascript"> function des() { app.$destroy(); } var app=new Vue({ el: '#app', data:{ message:0 }, methods:{ add:function () { this.message++; } }, beforeCreate:function(){ console.log('1-beforeCreate 初始化以後'); }, created:function(){ console.log('2-created 建立完成'); }, beforeMount:function(){ console.log('3-beforeMount 掛載以前'); }, mounted:function(){ console.log('4-mounted 被建立'); }, beforeUpdate:function(){ console.log('5-beforeUpdate 數據更新前'); }, updated:function(){ console.log('6-updated 被更新後'); }, activated:function(){//vuerouter中生效 console.log('7-activated'); }, deactivated:function(){//vuerouter中生效 console.log('8-deactivated'); }, beforeDestroy:function(){ console.log('9-beforeDestroy 銷燬以前'); }, destroyed:function(){ console.log('10-destroyed 銷燬以後') } }) </script> </body> </html>
五、template
template有三種寫法:
一、直接在Vue中寫模板:直接在構造器裏的template選項後邊編寫。這種寫法比較直觀,可是若是模板html代碼太多,不建議這麼寫。
<body> <div id="app"> </div> <script type="text/javascript"> var app=new Vue({ el: '#app', data:{ message: 'hello world!' }, template:`<h2 style="color:red">我是選項模板</h2>` }) </script> </body>
二、寫在template標籤中的模板
<body> <div id="app"> </div> <template id="dd"> <h2 style="color:red">我是template中的模板</h2> </template> <script type="text/javascript"> var app=new Vue({ el: '#app', data:{ message: 'hello world!' }, template:'#dd' // template:`<h2 style="color:red">我是選項模板</h2>` }) </script> </body>
三、寫在script中的模板
<body> <div id="app"> </div> <template id="dd"> <h2 style="color:red">我是template中的模板</h2> </template> <script type="x-template" id="dd1"> <h2 style="color:red">我是script中的模板</h2> </script> <script type="text/javascript"> var app=new Vue({ el: '#app', data:{ message: 'hello world!' }, template:'#dd1' // template:`<h2 style="color:red">我是選項模板</h2>` }) </script> </body>
六、Component
組件就是製做自定義的標籤,這些標籤在HTML中是沒有的。好比:<j></j>
component分爲兩種狀況:
一、全局組件
二、局部組件
其中全局組件在整個Vue生命週期內均可以調用,而局部組件只在對應的Vue下能夠調用。
demo以下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> <gavin></gavin> </div> <div id="app1"> <gavin></gavin> </div> <template id="t1"> <h2>我是全局組件</h2> </template> <script type="text/javascript"> Vue.component('gavin',{ template: '#t1' }); var app=new Vue({ el:'#app' }); var app1=new Vue({ el: '#app1' }) </script> </body> </html>
demo局部以下,能夠看到ga組件只能在app上調用,在app1上調用會報錯
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> <gavin></gavin> <ga></ga> </div> <div id="app1"> <gavin></gavin> <ga></ga> </div> <template id="t1"> <h2>我是全局組件</h2> </template> <template id="t2"> <h2>我是局部組件</h2> </template> <script type="text/javascript"> Vue.component('gavin',{ template: '#t1' }); var app=new Vue({ el:'#app', components:{ 'ga': { template: '#t2' } } }); var app1=new Vue({ el: '#app1' }) </script> </body> </html>
組件註冊的是一個標籤,而指令註冊的是已有標籤裏的一個屬性。在實際開發中咱們仍是用組件比較多,指令用的比較少。由於指令看起來封裝的沒那麼好
props選項就是設置和獲取標籤上的屬性值的,例如咱們有一個自定義的組件<panda></panda>,這時咱們想給他加個標籤屬性寫成<panda here=’China’></panda> 意思就是熊貓來自中國,固然這裏的China能夠換成任何值。定義屬性的選項是props。
一、定義屬性並獲取值
定義屬性咱們須要用props選項,加上數組形式的屬性名稱,例如:props:[‘here’]。在組件的模板裏讀出屬性值只須要用插值的形式,例如{{ here }}.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> <gavin here="china"></gavin> </div> <template id="t1"> <h2>組件傳參: {{here}}</h2> </template> <script type="text/javascript"> var app=new Vue({ el:'#app', data:{ message: 'china' }, components:{ 'gavin':{ template:'#t1', props:['here'] } } }) </script> </body> </html>
二、屬性若是中間帶‘-’,須要小駝峯式寫法
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> <gavin from-here="china"></gavin> </div> <template id="t1"> <h2>組件傳參: {{fromHere}}</h2> </template> <script type="text/javascript"> var app=new Vue({ el:'#app', data:{ message: 'china' }, components:{ 'gavin':{ template:'#t1', props:['fromHere'] } } }) </script> </body> </html>
三、向組件中傳參- 須要經過v-bind 或者:方式進行
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> <gavin :from-here="message"></gavin> </div> <template id="t1"> <h2>組件傳參: {{fromHere}}</h2> </template> <script type="text/javascript"> var app=new Vue({ el:'#app', data:{ message: 'china' }, components:{ 'gavin':{ template:'#t1', props:['fromHere'] } } }) </script> </body> </html>
父子組件:
注意:須要使用div包裹起來才能使用子組件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> <gavin></gavin> </div> <template id="t2"> <h3>我是子組件</h3> </template> <template id="t1"> <!--須要使用div包裹起來才能使用子組件--> <div> <h2>我是父組件</h2> <sun></sun> </div> </template> <script type="text/javascript"> var sun = { template: '#t2' }; var father = { template: '#t1', components:{ 'sun': sun } }; var app=new Vue({ el:'#app', components:{ 'gavin': father } }) </script> </body> </html>
component標籤:
<component></component>標籤是Vue框架自定義的標籤,它的用途就是能夠動態綁定咱們的組件,根據數據的不一樣更換不一樣的組件。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> <component :is="who"></component> <button @click="changeComponent">Change</button> </div> <template id="t1"> <div style="color:red">I'm Component A</div> </template> <template id="t2"> <div style="color:green">I'm Component B</div> </template> <template id="t3"> <div style="color:blue">I'm Component C</div> </template> <script type="text/javascript"> var componentA = { template: '#t1' }; var componentB = { template: '#t2' }; var componentC = { template: '#t3' }; var app=new Vue({ el:'#app', data:{ who: 'componentA' }, components:{ 'componentA': componentA, 'componentB': componentB, 'componentC': componentC }, methods:{ changeComponent:function () { if(this.who==='componentA'){ this.who = 'componentB'; }else if(this.who==='componentB'){ this.who = 'componentC'; }else{ this.who = 'componentA'; } } } }) </script> </body> </html>
3、選項
一、propsData選項
propsData 不是和屬性有關,他用在全局擴展時進行傳遞數據。先回顧一下全局擴展的知識,做一個<header></header>的擴展標籤出來。實際咱們並比推薦用全局擴展的方式做自定義標籤,咱們學了組件,徹底可使用組件來作,這裏只是爲了演示propsData的用法。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <header></header> <script type="text/javascript"> var header_a = Vue.extend({ template: `<p>{{message}}-{{a}}</p>`, data:function(){ return{ message:'hello world' } }, props:['a'] }); new header_a({propsData:{a:'擴展傳值'}}).$mount('header') </script> </body> </html>
擴展標籤已經作好了,這時咱們要在掛載時傳遞一個數字過去,咱們就用到了propsData。
咱們用propsData三步解決傳值:
一、在全局擴展里加入props進行接收。propsData:{a:1}
二、傳遞時用propsData進行傳遞。props:[‘a’]
三、用插值的形式寫入模板。{{ a }}
總結:propsData在實際開發中咱們使用的並很少,咱們在後邊會學到Vuex的應用,他的做用就是在單頁應用中保持狀態和數據的。
二、computed 選項
computed 的做用主要是對原數據進行改造輸出。改造輸出:包括格式的編輯,大小寫轉換,順序重排,添加符號……。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> <div v-text="newPrice"></div> <ul> <li v-for="item in newslists"><span v-text="item.title"></span>-<span v-text="item.date"></span></li> </ul> </div> <script type="text/javascript"> var app=new Vue({ el:'#app', data:{ price: 100, news:[ {title:'香港或就「裝甲車被扣」事件追責 起訴涉事運輸公司',date:'2017/12/10'}, {title:'日本第二大準航母服役 外媒:針對中國潛艇',date:'2017/12/12'}, {title:'中國北方將有明顯雨雪降溫天氣 南方陰雨持續',date:'2017/12/13'}, {title:'起底「最短命副市長」:不到40天落馬,全家被查',date:'2017/12/23'} ] }, computed:{ newPrice:function () { return this.price = "¥"+this.price+'元' }, newslists:function () { return this.news.reverse(); } } }) </script> </body> </html>
三、methods選項
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> <div v-text="num"></div> <p><button @click="add(money)">add</button></p> <p><input type="text" v-model="money"></p> </div> <script type="text/javascript"> var app=new Vue({ el:'#app', data:{ num:0, money:'' }, methods:{ add:function (mon) { if(mon!=0){ this.num+=parseInt(mon); }else { this.num++; } } } }) </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> <div v-text="num"></div> <p><button @click="add(money,$event)">add</button></p> <p><input type="text" v-model="money"></p> </div> <script type="text/javascript"> var app=new Vue({ el:'#app', data:{ num:0, money:'' }, methods:{ add:function (mon,event) { if(mon!=0){ this.num+=parseInt(mon); }else { this.num++; }; console.log(event); } } }) </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> <div v-text="num"></div> <!--<p><button @click="add(money,$event)">add</button></p>--> <p><button @click="add(money)">add</button></p> <p><input type="text" v-model="money"></p> <btn @click.native="add(money)"></btn> </div> <template id="t1"> <div> <button >add</button> </div> </template> <script type="text/javascript"> var btn={ template:'#t1' }; var app=new Vue({ el:'#app', data:{ num:0, money:'' }, components:{ 'btn': btn }, methods:{ // add:function (mon,event) { add:function (mon) { if(mon!=0){ this.num+=parseInt(mon); }else { this.num++; }; // console.log(event); } } }) </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> <div v-text="num"></div> <!--<p><button @click="add(money,$event)">add</button></p>--> <p><button @click="add(money)">add</button></p> <p><input type="text" v-model="money"></p> <btn @click.native="add(money)"></btn> </div> <div><button onclick="app.add(2)">外部add</button></div> <template id="t1"> <div> <button >add</button> </div> </template> <script type="text/javascript"> var btn={ template:'#t1' }; var app=new Vue({ el:'#app', data:{ num:0, money:'' }, components:{ 'btn': btn }, methods:{ // add:function (mon,event) { add:function (mon) { if(mon!=0){ this.num+=parseInt(mon); }else { this.num++; }; // console.log(event); } } }) </script> </body> </html>
使用方法和正常的javascript傳遞參數的方法同樣,分爲兩部:
一、在methods的方法中進行聲明,好比咱們給add方法加上一個num參數,就要寫出add:function(num){}.
二、調用方法時直接傳遞,好比咱們要傳遞2這個參數,咱們在button上就直接能夠寫。<button @click=」add(2)」></button>.
三、在add()裏面出來能夠傳遞2之外還能夠傳遞$event這個參數,這個參數包括不少mouseEvent操做
四、若是自定義組件時想要使用構造器裏方法,必須使用@click.native=add()方法,native選項能夠保證自定義組件可使用構造器內方法
五、若是外部標籤想要使用構造器方法,能夠直接採用onclick='app.add()'方法直接調用
四、watch選項
數據變化的監控常用,咱們能夠先來看一個簡單的數據變化監控的例子。例如天氣預報的穿衣指數,它主要是根據溫度來進行提示的
demo以下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> <p>溫度:<span v-text="temp"></span></p> <p>穿衣建議:<span v-text="sugg"></span></p> <div><button @click="incrtemp">升高溫度</button><button @click="redutemp">下降溫度</button></div> </div> <script type="text/javascript"> var suggs=['棉衣','夏裝','春裝','秋裝'] var app=new Vue({ el:'#app', data:{ temp:0, sugg:suggs[0] }, methods:{ incrtemp:function () { this.temp+=5; }, redutemp:function () { this.temp-=5; } }, watch:{ temp:function (newVal,oldVal) {//newVal是temp新數值,oldVal是temp原值 if(newVal <=0){ this.sugg=suggs[0]; }else if(newVal>0 && newVal<=16){ this.sugg=suggs[2]; }else if(newVal>16 && newVal<26){ this.sugg=suggs[3] }else{ this.sugg=suggs[1] } } } }) </script> </body> </html>
其中watch:{
temp:function(newVal,oldVal){} //newVal表示temp這個變量的新變化的值,而oldVal表示temp這個變量原來的值
}
爲了下降耦合度,還能夠將watch放在構造器外部書寫:
app.$watch('temp',function (newVal,oldVal) { if(newVal <=0){ this.sugg=suggs[0]; }else if(newVal>0 && newVal<=16){ this.sugg=suggs[2]; }else if(newVal>16 && newVal<26){ this.sugg=suggs[3] }else{ this.sugg=suggs[1] }})
五、mixins混入選項
Mixins通常有兩種用途:
一、在你已經寫好了構造器後,須要增長方法或者臨時的活動時使用的方法,這時用混入會減小源代碼的污染。
二、不少地方都會用到的公用方法,用混入的方法能夠減小代碼量,實現代碼重用。
在mixins插入後,mixin插入優先於構造器的updated,可是同時全局的mixin優先於普通的mixin
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> {{num}} <p><button @click="add(4)">add</button></p> </div> <script type="text/javascript"> var addCon = { updated:function () { console.log('混入方式:'+this.num); } }; Vue.mixin({ updated:function(){ console.log('我是全局被混入的'); } }); var app=new Vue({ el:'#app', data:{ num: 0 }, methods:{ add:function (val) { console.log('原生的方式執行') this.num+=parseInt(val) } }, updated:function () { console.log('原生的更新執行') }, mixins:[addCon] }) </script> </body> </html>
六、extends選項
經過外部增長對象的形式,對構造器進行擴展
extends:後面只能跟一個擴展選項名
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> {{num}} <p><button @click="add(4)">add</button></p> </div> <script type="text/javascript"> var extendobj = { updated:function () { console.log('extend選項插入') } }; var app=new Vue({ el:'#app', data:{ num: 0 }, methods:{ add:function (val) { console.log('原生的方式執行'); this.num+=parseInt(val) } }, updated:function () { console.log('原生的更新執行') }, extends: extendobj }) </script> </body> </html>
七、delimiters
delimiters的做用是改變咱們插值的符號。Vue默認的插值是雙大括號{{}}。但有時咱們會有需求更改這個插值的形式
delimiters:['${','}']
4、實例與內部組件
實例就是在構造器外部操做構造器內部的屬性選項或者方法,就叫作實例?實例的做用就是給原生的或者其餘javascript框架一個融合的接口或者說是機會,讓Vue和其餘框架一塊兒使用
一、Vue與Jquery配合
注意:在調用時必須經過鉤子函數mounted或者updated調用
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> <script type="text/javascript" src="jquery-3.2.1.min.js"></script> </head> <body> <div id="app"> {{message}} </div> <script type="text/javascript"> var app=new Vue({ el:'#app', data:{ message: 'hello world!!!' }, mounted:function () { $('#app').html('這是jquery!') } }) </script> </body> </html>
對於內部方法能夠經過外部引用方式調用
app.add();//外部能夠經過實例方式調用
二、$mount() $destroy()$forceUpdate() $nextTick()方法
mount():
$mount方法是用來掛載咱們的擴展的
$mount須要經過Vue.extend來完成擴展
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> </div> <template id="t1"> <div> <span v-text="message"></span> </div> </template> <script type="text/javascript"> var mountExt = Vue.extend({ template: '#t1', data:function () { return{ message: 'hello world!' } } }); var vm = new mountExt().$mount('#app') </script> </body> </html>
$destroy()
用$destroy()進行卸載
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> </div> <p><button onclick="destroy()">卸載</button></p> <template id="t1"> <div> <span v-text="message"></span> </div> </template> <script type="text/javascript"> var mountExt = Vue.extend({ template: '#t1', data:function () { return{ message: 'hello world!' } }, mounted:function () { console.log('綁定') }, destroyed:function () { console.log('卸載完畢'); } }); var vm = new mountExt().$mount('#app'); function destroy() { vm.$destroy(); } </script> </body> </html>
$forceUpdate()
vm.$forceUpdate()
$nextTick()
修改數據會自動觸發
function tick() {
vm.message='修改數據'
vm.$nextTick(function(){
console.log('message更新完後我被調用了');
})
}
完整demo以下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"></div> <p><button onclick="destroy()">卸載</button></p> <p><button onclick="reload()">更新</button></p> <p><button onclick="tick()">修改數據</button></p> <template id="t1"> <div> <span v-text="message"></span> </div> </template> <script type="text/javascript"> var mountExt = Vue.extend({ template: '#t1', data:function () { return{ message: 'hello world!' } }, mounted:function () { console.log('綁定') }, updated:function () { console.log('數據更新') }, destroyed:function () { console.log('卸載完畢'); } }); var vm = new mountExt().$mount('#app'); function destroy() { vm.$destroy(); } function reload() { vm.$forceUpdate(); } function tick() { vm.message='修改數據' vm.$nextTick(function(){ console.log('message更新完後我被調用了'); }) } </script> </body> </html>
三、實例事件
實例事件就是在構造器外部寫一個調用構造器內部的方法。這樣寫的好處是能夠經過這種寫法在構造器外部調用構造器內部的數據。
咱們仍是寫一個點擊按鈕,持續加1的例子
一、$on
在構造器外部添加事件, $on接收兩個參數,第一個參數是調用時的事件名稱,第二個參數是一個匿名方法。若是按鈕在做用域外部,能夠利用$emit來執行
app.$on('reduce',function (num) {
this.message -=num;
});
function reduce(num) {
app.$emit('reduce',num);
};
二、$once
執行一次的事件
app.$once('reduceOnce',function (num) {
console.log('執行了reduceOnce()');
this.message -=num;
});
function reduceOnce(num) {
app.$emit('reduceOnce',num);
}
三、$off
關閉事件
function off() {
app.$off('reduce')
}
完整代碼以下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> {{message}} <div> <button @click="add(2)">add</button> </div> </div> <div><button onclick="reduce(2)">reduce</button></div> <div><button onclick="reduceOnce(2)">reduceOnce</button></div> <div><button onclick="off()">off</button></div> <script type="text/javascript"> var app=new Vue({ el:'#app', data:{ message: 0 }, methods:{ add:function (num) { console.log('執行了add()'); this.message+=parseInt(num); } } }); app.$on('reduce',function (num) { console.log('執行了reduce()'); this.message -=num; }); function reduce(num) { app.$emit('reduce',num); }; app.$once('reduceOnce',function (num) { console.log('執行了reduceOnce()'); this.message -=num; }); function reduceOnce(num) { app.$emit('reduceOnce',num); }; function off() { app.$off('reduce') } </script> </body> </html>
四、內置組件-slot
slot是標籤的內容擴展,也就是說你用slot就能夠在自定義組件時傳遞給組件內容,組件接收內容並輸出
slot使用分兩步:
一、在html組件中用slot屬性傳遞值:
<gavin> <span slot="Url">{{Dataobj.address}}</span> <span slot="netname">{{Dataobj.username}}</span> <span slot="skill">{{Dataobj.skill}}</span> </gavin>
二、在組件模板中使用slot標籤接收屬性值
<template id="t1"> <div> <p>地址:<slot name="Url"></slot></p> <p>網名:<slot name="netname"></slot></p> <p>技能:<slot name="skill"></slot></p> </div> </template>
完整demo:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="app"> <gavin> <span slot="Url">{{Dataobj.address}}</span> <span slot="netname">{{Dataobj.username}}</span> <span slot="skill">{{Dataobj.skill}}</span> </gavin> </div> <template id="t1"> <div> <p>地址:<slot name="Url"></slot></p> <p>網名:<slot name="netname"></slot></p> <p>技能:<slot name="skill"></slot></p> </div> </template> <script type="text/javascript"> var gavin={ template:'#t1' }; var app=new Vue({ el:'#app', data:{ Dataobj:{ 'address': 'https://www.baidu.com', 'username': 'gavin', 'skill': 'python' } }, components:{ 'gavin':gavin } }) </script> </body> </html>
5、vue-cli
安裝vue-cli的前提是你已經安裝了npm,安裝npm你能夠直接下載node的安裝包進行安裝。你能夠在命令行工具裏輸入npm -v 檢測你是否安裝了npm和版本狀況。出現版本號說明你已經安裝了npm和node,若是該命令不可使用,須要安裝node軟件包,根據你的系統版本選擇下載安裝就能夠了。
下載地址:http://nodejs.cn/download/
npm沒有問題,接下來咱們能夠用npm 命令安裝vue-cli了:
npm install vue-cli -g
-g :表明全局安裝。若是你安裝時報錯,通常是網絡問題,你能夠嘗試用cnpm來進行安裝。安裝完成後,能夠用vue -V來進行查看 vue-cli的版本號。注意這裏的V是大寫的,若是vue -V的命令管用了,說明已經順利的把vue-cli安裝到咱們的計算機裏了
咱們用vue init命令來初始化項目,具體看一下這條命令的使用方法。
vue init <template-name> <project-name>
vue init webpack vuecliTest
init:表示我要用vue-cli來初始化項目
<template-name>:表示模板名稱,vue-cli官方爲咱們提供了5種模板,
webpack-一個全面的webpack+vue-loader的模板,功能包括熱加載,linting,檢測和CSS擴展。
webpack-simple-一個簡單webpack+vue-loader的模板,不包含其餘功能,讓你快速的搭建vue的開發環境。
browserify-一個全面的Browserify+vueify 的模板,功能包括熱加載,linting,單元檢測。
browserify-simple-一個簡單Browserify+vueify的模板,不包含其餘功能,讓你快速的搭建vue的開發環境。
simple-一個最簡單的單頁應用模板。
<project-name>:標識項目名稱,這個你能夠根據本身的項目來起名字。
在實際開發中,通常咱們都會使用webpack這個模板,那咱們這裏也安裝這個模板,在命令行輸入如下命令:
輸入命令後,會詢問咱們幾個簡單的選項,咱們根據本身的須要進行填寫就能夠了。
命令行出現上面的文字,說明咱們已經初始化好了第一步。命令行提示咱們如今能夠做的三件事情。
一、cd vuecliTest 進入咱們的vue項目目錄。
二、npm install 安裝咱們的項目依賴包,也就是安裝package.json裏的包,若是你網速很差,你也可使用cnpm來安裝。
三、npm run dev 開發模式下運行咱們的程序。給咱們自動構建了開發用的服務器環境和在瀏覽器中打開,並實時監視咱們的代碼更改,即時呈現給咱們。
vue-cli文件解釋:
vue-cli腳手架工具就是爲咱們搭建了開發所須要的環境,爲咱們省去了不少精力。有必要對這個環境進行熟悉,咱們就從項目的結構講起。
Ps:因爲版本實時更新和你選擇安裝的不一樣(這裏列出的是模板爲webpack的目錄結構),因此你看到的有可能和下邊的有所差異。
.
|-- build // 項目構建(webpack)相關代碼
| |-- build.js // 生產環境構建代碼
| |-- check-version.js // 檢查node、npm等版本
| |-- dev-client.js // 熱重載相關
| |-- dev-server.js // 構建本地服務器
| |-- utils.js // 構建工具相關
| |-- webpack.base.conf.js // webpack基礎配置
| |-- webpack.dev.conf.js // webpack開發環境配置
| |-- webpack.prod.conf.js // webpack生產環境配置
|-- config // 項目開發環境配置
| |-- dev.env.js // 開發環境變量
| |-- index.js // 項目一些配置變量
| |-- prod.env.js // 生產環境變量
| |-- test.env.js // 測試環境變量
|-- src // 源碼目錄
| |-- components // vue公共組件
| |-- store // vuex的狀態管理
| |-- App.vue // 頁面入口文件
| |-- main.js // 程序入口文件,加載各類公共組件
|-- static // 靜態文件,好比一些圖片,json數據等
| |-- data // 羣聊分析獲得的數據用於數據可視化
|-- .babelrc // ES6語法編譯配置
|-- .editorconfig // 定義代碼格式
|-- .gitignore // git上傳須要忽略的文件格式
|-- README.md // 項目說明
|-- favicon.ico
|-- index.html // 入口頁面
|-- package.json // 項目基本信息
重要文件講解:
package.json文件是項目根目錄下的一個文件,定義該項目開發所須要的各類模塊以及一些項目配置信息(如項目名稱、版本、描述、做者等)。
package.json 裏的scripts字段,這個字段定義了你能夠用npm運行的命令。在開發環境下,在命令行工具中運行npm run dev 就至關於執行 node build/dev-server.js .也就是開啓了一個node寫的開發行建議服務器。由此能夠看出script字段是用來指定npm相關命令的縮寫。
"scripts": {
"dev": "node build/dev-server.js",
"build": "node build/build.js"
},
在執行完npm run build命令後,在你的項目根目錄生成了dist文件夾,這個文件夾裏邊就是咱們要傳到服務器上的文件。
dist文件夾下目錄包括:
main.js是整個項目的入口文件,在src文件夾下:
import Vue from 'vue' import App from './App' import router from './router' Vue.config.productionTip = false //生產環境提示,這裏設置成了false /* eslint-disable no-new */ new Vue({ el: '#app', router, template: '<App/>', components: { App } })
經過代碼能夠看出這裏引進了App的組件和<App/>的模板,它是經過 import App from ‘./App’這句代碼引入的。 咱們找到App.vue文件,打開查看
<template> <div id="app"> <img src="./assets/logo.png"> <router-view></router-view> </div> </template> <script> export default { name: 'app' } </script> <style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>
app.vue文件咱們能夠分紅三部分解讀,
引文在app.vue中咱們看到了路由文件,雖然router的內容比較多,可是咱們先簡單的看一下。下篇文章咱們就開始講Vue-router
import Vue from 'vue'
import Router from 'vue-router'
import Hello from '@/components/Hello'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'Hello',
component: Hello
}
]
})
咱們能夠看到 import Hello from ‘@/components/Hello’這句話, 文件引入了/components/Hello.vue文件。這個文件裏就配置了一個路由,就是當咱們訪問網站時給咱們顯示Hello.vue的內容
Hello.vue文件解讀:
這個文件就是咱們在第一節課看到的頁面文件了。也是分爲<template><script><style>三個部分,之後咱們大部分的工做都是寫這些.vue結尾的文件。如今咱們能夠試着改一些內容,而後預覽一下。
<template> <div class="hello"> <h1>{{ msg }}</h1> <h2>Essential Links</h2> <ul> <li><a href="https://vuejs.org" target="_blank">Core Docs</a></li> <li><a href="https://forum.vuejs.org" target="_blank">Forum</a></li> <li><a href="https://gitter.im/vuejs/vue" target="_blank">Gitter Chat</a></li> <li><a href="https://twitter.com/vuejs" target="_blank">Twitter</a></li> <br> <li><a href="http://vuejs-templates.github.io/webpack/" target="_blank">Docs for This Template</a></li> </ul> <h2>Ecosystem</h2> <ul> <li><a href="http://router.vuejs.org/" target="_blank">vue-router</a></li> <li><a href="http://vuex.vuejs.org/" target="_blank">vuex</a></li> <li><a href="http://vue-loader.vuejs.org/" target="_blank">vue-loader</a></li> <li><a href="https://github.com/vuejs/awesome-vue" target="_blank">awesome-vue</a></li> </ul> </div> </template> <script> export default { name: 'hello', data () { return { msg: 'Welcome to Your Vue.js App' } } } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> h1, h2 { font-weight: normal; } ul { list-style-type: none; padding: 0; } li { display: inline-block; margin: 0 10px; } a { color: #42b983; } </style>
6、vue-router
因爲Vue在開發時對路由支持的不足,後來官方補充了vue-router插件,它在Vue的生態環境中很是重要,在實際開發中只要編寫一個頁面就會操做vue-router。要學習vue-router就要先知道這裏的路由是什麼?這裏的路由並非指咱們平時所說的硬件路由器,這裏的路由就是SPA(單頁應用)的路徑管理器。再通俗的說,vue-router就是咱們WebApp的連接路徑管理系統
有的小夥伴會有疑慮,爲何咱們不能像原來同樣直接用<a></a>標籤編寫連接哪?由於咱們用Vue做的都是單頁應用,就至關於只有一個主的index.html頁面,因此你寫的<a></a>標籤是不起做用的,你必須使用vue-router來進行管理
vue-router是一個插件包,因此咱們仍是須要用npm來進行安裝的。打開命令行工具,進入你的項目目錄,輸入下面命令。
npm install vue-router --save-dev
若是你安裝很慢,也能夠用cnpm進行安裝,若是你在使用vue-cli中已經選擇安裝了vue-router,那這裏不須要重複安裝了
咱們用vue-cli生產了咱們的項目結構,你能夠在src/router/index.js文件,這個文件就是路由的核心文件
import Vue from 'vue' //引入Vue import Router from 'vue-router' //引入vue-router import Hello from '@/components/Hello' //引入根目錄下的Hello.vue組件 Vue.use(Router) //Vue全局使用Router export default new Router({ routes: [ //配置路由,這裏是個數組 { //每個連接都是一個對象 path: '/', //連接路徑 name: 'Hello', //路由名稱, component: Hello //對應的組件模板 } ] })
上邊的代碼中已經對每行都進行了註釋,其實在這個路由文件裏只配置了一個功能,就是在進入項目時,顯示Hello.vue裏邊的內容代碼。
對路由的核心文件熟悉後,咱們試着增長一個路由配置,咱們但願在地址欄輸入 http://localhost:8080/#/hi 的時候出現一個新的頁面,先來看一下咱們但願獲得的效果。
咱們看一下具體的操做步驟:
<template> <div class="hello"> <h1>{{ msg }}</h1> </div> </template> <script> export default { name: 'hi', data () { return { msg: 'Hi, I am JSPang' } } } </script> <style scoped> </style>
import Hi from '@/components/Hi'
{ path:'/hi', name:'Hi', component:Hi }
經過上面的配置已經能夠增長一個新的頁面了。是否是覺的本身的Vue功力一會兒就提高了一個檔次。爲了方便小夥伴查看,貼出如今的路由配置文件:
import Vue from 'vue' //引入Vue import Router from 'vue-router' //引入vue-router import Hello from '@/components/Hello' //引入根目錄下的Hello.vue組件 import Hi from '@/components/Hi' Vue.use(Router) //Vue全局使用Router export default new Router({ routes: [ //配置路由,這裏是個數組 { //每個連接都是一個對象 path: '/', //連接路徑 name: 'Hello', //路由名稱, component: Hello //對應的組件模板 },{ path:'/hi', name:'Hi', component:Hi } ] })
如今經過在地址欄改變字符串地址,已經能夠實現頁面內容的變化了。這並不知足需求,咱們須要的是在頁面上有個像樣的導航連接,咱們只要點擊就能夠實現頁面內容的變化。製做連接須要<router-link>標籤,咱們先來看一下它的語法。
<router-link to="/">[顯示字段]</router-link>
明白了router-link的基本語法,咱們在 src/App.vue文件中的template里加入下面代碼,實現導航。
<p>導航 :
<router-link to="/">首頁</router-link>
<router-link to="/hi">Hi頁面</router-link>
</p>
配置路由子系統
子路由的狀況通常用在一個頁面有他的基礎模版,而後它下面的頁面都隸屬於這個模版,只是部分改變樣式
步驟:
一、改造App.vue的導航代碼
App.vue代碼
<p>導航 :
<router-link to="/">首頁</router-link> |
<router-link to="/hi">Hi頁面</router-link> |
<router-link to="/hi/hi1">-Hi頁面1</router-link> |
<router-link to="/hi/hi2">-Hi頁面2</router-link>
</p>
二、改寫components/Hi.vue頁面
把Hi.vue改爲一個通用的模板,加入<router-view>標籤,給子模板提供插入位置。「Hi頁面1」 和 「Hi頁面2」 都至關於「Hi頁面」的子頁面,有點想繼承關係。咱們在「Hi頁面」里加入<router-view>標籤。
components/Hi.vue,就是第5行的代碼,其餘代碼不變
<template> <div class="hello"> <h1>{{ msg }}</h1> <router-view class="aaa"></router-view> </div> </template> <script> export default { name: 'hi', data () { return { msg: 'Hi, I am JSPang' } } } </script> <style scoped> </style>
三、在components目錄下新建兩個組件模板 Hi1.vue 和 Hi2.vue
新建的模板和Hi.vue沒有太多的差異,知識改變了data中message的值,也就是輸出的結果不太同樣了。
Hi1.vue
<template> <div class="hello"> <h1>{{ msg }}</h1> </div> </template> <script> export default { name: 'hi', data () { return { msg: 'Hi, I am Hi1!' } } } </script> <style scoped> </style>
Hi2.vue
<template> <div class="hello"> <h1>{{ msg }}</h1> </div> </template> <script> export default { name: 'hi', data () { return { msg: 'Hi, I am Hi2' } } } </script> <style scoped> </style>
四、修改router/index.js代碼
咱們如今導航有了,母模板和子模板也有了,只要改變咱們的路由配置文件就能夠了。子路由的寫法是在原有的路由配置下加入children字段。
children:[ {path:'/',component:xxx}, {path:'xx',component:xxx}, ]
children字段後邊跟的是個數組,數組裏和其餘配置路由基本相同,須要配置path和component。具體看一下這個子路由的配置寫法。
import Vue from 'vue' import Router from 'vue-router' import Hello from '@/components/Hello' import Hi from '@/components/Hi' import Hi1 from '@/components/Hi1' import Hi2 from '@/components/Hi2' Vue.use(Router) export default new Router({ routes: [ { path: '/', name: 'Hello', component: Hello },{ path:'/hi', component:Hi, children:[ {path:'/',component:Hi}, {path:'hi1',component:Hi1}, {path:'hi2',component:Hi2}, ] } ] })
vue-router如何傳遞參數
開發中,參數的傳遞是個最基本的業務需求。經過URL地址來傳遞參數是一個形式,咱們先想象一個基本需求,就是在咱們點擊導航菜單時,跳轉頁面上能顯示出當前頁面的路徑,來告訴用戶你想在所看的頁面位置(相似於麪包屑導航)。
一、用name傳遞參數
兩步完成用name傳值並顯示在模板裏:
a、在路由文件src/router/index.js裏配置name屬性。
{ path: 'hi1', name: 'Hi1', component: Hi1, },
b、模板裏(src/App.vue)用$router.name的形勢接收,好比直接在模板中顯示:
<p>{{ $route.name }}</p>
二、經過<router-link> 標籤中的to傳參
咱們用<router-link>標籤中的to屬性進行傳參,須要您注意的是這裏的to要進行一個綁定,寫成:to。
<router-link :to="{name:xxx,params:{key:value}}">valueString</router-link>
這裏的to前邊是帶冒號的,而後後邊跟的是一個對象形勢的字符串.
瞭解基本的語法後,咱們改造一下咱們的src/App.vue裏的<router-link>標籤,咱們把hi1頁面的<router-link>進行修改。
<router-link :to="{name:'hi1',params:{username:'gavin'}}">Hi頁面1</router-link>
把src/reouter/index.js文件裏給hi1配置的路由起個name,就叫hi1.
{path:'/hi1',name:'hi1',component:Hi1},
最後在模板裏(src/components/Hi1.vue)用$route.params.username進行接收.
{{$route.params.username}}
四、單頁面多路由操做
實際需求是這樣的,在一個頁面裏咱們有2個以上<router-view>區域,咱們經過配置路由的js文件,來操做這些區域的內容。例如咱們在src/App.vue里加上兩個<router-view>標籤。咱們用vue-cli創建了新的項目,並打開了src目錄下的App.vue文件,在<router-view>下面新寫了兩行<router-view>標籤,並加入了些CSS樣式。
<router-view ></router-view> <router-view name="left" style="float:left;width:50%;background-color:#ccc;height:300px;"></router-view> <router-view name="right" style="float:right;width:50%;background-color:#c0c;height:300px;"></router-view>
如今的頁面中有了三個<router-view>標籤,也就是說咱們須要在路由裏配置這三個區域,配置主要是在components字段裏進行。
import Vue from 'vue' import Router from 'vue-router' import Hello from '@/components/Hello' import Hi1 from '@/components/Hi1' import Hi2 from '@/components/Hi2' Vue.use(Router) export default new Router({ routes: [ { path: '/', components: { default:Hello, left:Hi1, right:Hi2 } },{ path: '/Hi', components: { default:Hello, left:Hi2, right:Hi1 } } ] })
上邊的代碼咱們編寫了兩個路徑,一個是默認的‘/’,另外一個是’/Hi’.在兩個路徑下的components裏面,咱們對三個區域都定義了顯示內容。
定義好後,咱們須要在component文件夾下,新建Hi1.vue和Hi2.vue頁面就能夠了。
Hi1.vue
<template> <div> <h2>{{ msg }}</h2> </div> </template> <script> export default { name: 'hi1', data () { return { msg: 'I am Hi1 page.' } } } </script>
H2.vue
<template> <div> <h2>{{ msg }}</h2> </div> </template> <script> export default { name: 'hi2', data () { return { msg: 'I am Hi2 page.' } } } </script>
最後在App.vue中配置咱們的<router-link>就能夠了
<router-link to="/">首頁</router-link> | <router-link to="/hi">Hi頁面</router-link> |
五、利用url傳參
在實際開發也是有不少用URL傳值的需求,好比咱們在新聞列表中有不少新聞標題整齊的排列,咱們須要點擊每一個新聞標題打開不一樣的新聞內容,這時在跳轉路由時跟上新聞編號就十分實用。
咱們能夠在路由配置文件裏以:冒號的形式傳遞參數,這就是對參數的綁定。
{ path:'/params/:newsId/:newsTitle', component:Params }
咱們須要傳遞參數是新聞ID(newsId)和新聞標題(newsTitle).因此咱們在路由配置文件裏制定了這兩個值。
2. 在src/components目錄下創建咱們params.vue組件,也能夠說是頁面。咱們在頁面裏輸出了url傳遞的的新聞ID和新聞標題。
<template> <div> <h2>{{ msg }}</h2> <p>新聞ID:{{ $route.params.newsId}}</p> <p>新聞標題:{{ $route.params.newsTitle}}</p> </div> </template> <script> export default { name: 'params', data () { return { msg: 'params page' } } } </script>
3. 在App.vue文件里加入咱們的<router-view>標籤。這時候咱們能夠直接利用url傳值了。
<router-link to="/params/123/gavin website is very good">params</router-link> |
上邊的例子,咱們傳遞了新聞編號,如今需求升級了,咱們但願咱們傳遞的新聞ID只能是數字的形式,這時候咱們就須要在傳遞時有個基本的類型判斷,vue是支持正則的。
加入正則須要在路由配置文件裏(/src/router/index.js)以圓括號的形式加入。
path:'/params/:newsId(\\d+)/:newsTitle',
六、vue-router的redirect
開發中有時候咱們雖然設置的路徑不一致,可是咱們但願跳轉到同一個頁面,或者說是打開同一個組件。這時候咱們就用到了路由的從新定向redirect參數。
咱們只要在路由配置文件中(/src/router/index.js)把原來的component換成redirect參數就能夠了。咱們來看一個簡單的配置export default new Router({ routes: [ {
export default new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
components: {
HelloWorld : HelloWorld
}
},
{
path: '/params/:newsId(\\d{1,4})/:newsTitle',
name: 'Params',
component: Params
},
{
path: '/gohome',
name: 'GOHOME',
redirect: '/' //重定向使用redirect參數
},
{
path: '/goparams/:newsId(\\d{1,4})/:newsTitle',//帶參數的重定向只要照搬初始值便可
name: 'GoParams',
redirect: '/params/:newsId(\\d{1,4})/:newsTitle'//帶參數重定向照搬初始值便可
}
]
})
這裏咱們設置了goback路由,可是它並無配置任何component(組件),而是直接redirect到path:’/’下了,這就是一個簡單的從新定向。
咱們已經學會了經過url來傳遞參數,那咱們重定向時若是也須要傳遞參數怎麼辦?其實vue也已經爲咱們設置好了,咱們只須要在ridirect後邊的參數裏複製重定向路徑的path參數就能夠了。可能你看的有點暈,咱們來看一段代碼:
{ path:'/params/:newsId(\\d+)/:newsTitle', component:Params },{ path:'/goParams/:newsId(\\d+)/:newsTitle', redirect:'/params/:newsId(\\d+)/:newsTitle' }
已經有了一個params路由配置,咱們在設置一個goParams的路由重定向,並傳遞了參數。這時候咱們的路由參數就能夠傳遞給params.vue組件了。參數接收方法和正常的路由接收方法同樣。
七、alias別名的使用
alias也能夠實現相似重定向的效果
1.首先咱們在路由配置文件裏(/src/router/index.js),給上節課的Home路徑起一個別名
{ path: '/hi1', component: Hi1, alias:'/gavin' }
2.配置咱們的<router-link>,起過別名以後,能夠直接使用<router-link>標籤裏的to屬性,進行從新定向。
<router-link to="/gavin">gavin</router-link>
填個小坑:
別名請不要用在path爲’/’中,以下代碼的別名是不起做用的。
{ path: '/', component: Hello, alias:'/home' }
八、路由的過渡動畫
想讓路由有過渡動畫,須要在<router-view>標籤的外部添加<transition>標籤,標籤還須要一個name屬性。
<transition name="fade"> <router-view ></router-view> </transition>
咱們在/src/App.vue文件裏添加了<transition>標籤,並給標籤起了一個名字叫fade。
組件過渡過程當中,會有四個CSS類名進行切換,這四個類名與transition的name屬性有關,好比name=」fade」,會有以下四個CSS類名:
從上面四個類名能夠看出,fade-enter-active和fade-leave-active在整個進入或離開過程當中都有效,因此CSS的transition屬性在這兩個類下進行設置。
那咱們就在App.vue頁面里加入四種CSS樣式效果,並利用CSS3的transition屬性控制動畫的具體效果。代碼以下:
.fade-enter { opacity:0; } .fade-leave{ opacity:1; } .fade-enter-active{ transition:opacity .5s; } .fade-leave-active{ opacity:0; transition:opacity .5s;
上邊的代碼設置了改變透明度的動畫過渡效果,可是默認的mode模式in-out模式,這並非咱們想要的。下面咱們學一下mode模式。
<transition name="fade" mode="out-in"> <router-view/> </transition>
九、mode模式與404頁面處理
export default new Router({ mode: 'history', routes: [ { path: '/', name: 'HelloWorld', component: HelloWorld }, { path: '/params/:newsId(\\d{1,4})/:newsTitle', name: 'Params', component: Params }, { path: '/gohome', name: 'GOHOME', redirect: '/' //重定向使用redirect參數 }, { path: '/goparams/:newsId(\\d{1,4})/:newsTitle',//帶參數的重定向只要照搬初始值便可 name: 'GoParams', redirect: '/params/:newsId(\\d{1,4})/:newsTitle'//帶參數重定向照搬初始值便可 }, { path: '/hi1', name: 'Hi1', component: Hi1, alias: '/gavin' } ] })
404頁面的設置:
用戶會常常輸錯頁面,當用戶輸錯頁面時,咱們但願給他一個友好的提示,爲此美工都會設計一個漂亮的頁面,這個頁面就是咱們常說的404頁面。vue-router也爲咱們提供了這樣的機制.
1.設置咱們的路由配置文件(/src/router/index.js):
{ path:'*', component:Error }
這裏的path:’*’就是找不到頁面時的配置,component是咱們新建的一個Error.vue的文件。
2.新建404頁面:
在/src/components/文件夾下新建一個Error.vue的文件。簡單輸入一些有關錯誤頁面的內容。
<template> <div> <h2>{{ msg }}</h2> </div> </template> <script> export default { data () { return { msg: 'Error:404' } } } </script>
十、路由的鉤子函數
一個組件從進入到銷燬有不少的鉤子函數,一樣在路由中也設置了鉤子函數。路由的鉤子選項能夠寫在路由配置文件中,也能夠寫在咱們的組件模板中。咱們這節課就介紹這兩種鉤子函數的寫法。
咱們能夠直接在路由配置文件(/src/router/index.js)中寫鉤子函數。可是在路由文件中咱們只能寫一個beforeEnter,就是在進入此路由配置時。先來看一段具體的代碼:
{ path:'/params/:newsId(\\d+)/:newsTitle', component:Params, beforeEnter:(to,from,next)=>{ console.log('我進入了params模板'); console.log(to); console.log(from); next(); },
咱們在params路由裏配置了bdforeEnter得鉤子函數,函數咱們採用了ES6的箭頭函數,須要傳遞三個參數。咱們並在箭頭函數中打印了to和from函數。具體打印內容能夠在控制檯查看object。
三個參數:
在配置文件中的鉤子函數,只有一個鉤子-beforeEnter,若是咱們寫在模板中就能夠有兩個鉤子函數可使用:
export default { name: 'params', data () { return { msg: 'params page' } }, beforeRouteEnter:(to,from,next)=>{ console.log("準備進入路由模板"); next(); }, beforeRouteLeave: (to, from, next) => { console.log("準備離開路由模板"); next(); } } </script>
這是咱們寫在params.vue模板裏的路由鉤子函數。它能夠監控到路由的進入和路由的離開,也能夠輕易的讀出to和from的值。
十一、編程式導航
this.$router.go(-1) 和 this.$router.go(1)
<button @click="goback">後退</button>
2.在咱們的script模塊中寫入goback()方法,並使用this.$router.go(-1),進行後退操做。
<script> export default { name: 'app', methods:{ goback(){ this.$router.go(-1); } } } </script>
打開瀏覽器進行預覽,這時咱們的後退按鈕就能夠向之前的網頁同樣後退了。
router.go(1):表明着前進,用法和後退同樣
this.$router.push(‘/xxx ‘):
這個編程式導航都做用就是跳轉,好比咱們判斷用戶名和密碼正確時,須要跳轉到用戶中心頁面或者首頁,都用到這個編程的方法來操做路由。
咱們設置一個按鈕,點擊按鈕後回到站點首頁。
1.先編寫一個按鈕,在按鈕上綁定goHome( )方法。
<button @click="goHome">回到首頁</button>
2.在<script>模塊里加入goHome方法,並用this.$router.push(‘/’)導航到首頁
export default { name: 'app', methods:{ goback(){ this.$router.go(-1); }, goHome(){ this.$router.push('/'); } } }
7、vuex
vuex是一個專門爲vue.js設計的集中式狀態管理架構。狀態?我把它理解爲在data中的屬性須要共享給其餘vue組件使用的部分,就叫作狀態。簡單的說就是data中須要共用的屬性。好比:咱們有幾個頁面要顯示用戶名稱和用戶等級,或者顯示用戶的地理位置。若是咱們不把這些屬性設置爲狀態,那每一個頁面遇到後,都會到服務器進行查找計算,返回後再顯示。在中大型項目中會有不少共用的數據,因此尤大神給咱們提供了vuex。
一、入門小實驗:
首先安裝vuex:
cnpm install vuex --save
新建一個vuex文件夾(這個不是必須的),並在文件夾下新建store.js文件,文件中引入咱們的vue和vuex。
import Vue from 'vue';
import Vuex from 'vuex';
使用咱們vuex,引入以後用Vue.use進行引用。
Vue.use(Vuex);
經過這三步的操做,vuex就算引用成功了
如今咱們store.js文件裏增長一個常量對象。store.js文件就是咱們在引入vuex時的那個文件。
const state={ count:1 }
用export default 封裝代碼,讓外部能夠引用。
export default new Vuex.Store({ state })
新建一個vue的模板,位置在components文件夾下,名字叫count.vue。在模板中咱們引入咱們剛建的store.js文件,並在模板中用{{$store.state.count}}輸出count 的值。
<template> <div> <h2>{{msg}}</h2> <hr/> <h3>{{$store.state.count}}</h3> </div> </template> <script> import store from '@/vuex/store' export default{ data(){ return{ msg:'Hello Vuex', } }, store } </script>
在store.js文件中加入兩個改變state的方法
const mutations={ add(state){ state.count++; }, reduce(state){ state.count--; } }
這裏的mutations是固定的寫法,意思是改變的,咱們到時候會用一節課專門講這個mutations,因此你先不用着急,只知道咱們要改變state的數值的方法,必須寫在mutations裏就能夠了。
在count.vue模板中加入兩個按鈕,並調用mutations中的方法。
<div> <button @click="$store.commit('add')">+</button> <button @click="$store.commit('reduce')">-</button> </div>
這樣進行預覽就能夠實現對vuex中的count進行加減了。
二、state 狀態對象
在第1節咱們已經寫了一個 const state ,這個就是咱們說的訪問狀態對象,它就是咱們SPA(單頁應用程序)中的共享值。今天咱們主要學習狀態對象賦值給內部對象,也就是把stroe.js中的值,賦值給咱們模板裏data中的值。咱們有三種賦值方式,咱們一個一個來學習一下。
一、computed屬性能夠在輸出前,對data中的值進行改變,咱們就利用這種特性把store.js中的state值賦值給咱們模板中的data值。
computed:{ count(){ return this.$store.state.count; } }
這裏須要注意的是return this.$store.state.count這一句,必定要寫this,要不你會找不到$store的。這種寫法很好理解,可是寫起來是比較麻煩的,那咱們來看看第二種寫法。
二、mapState的對象賦值
咱們首先要用import引入mapState。
import {mapState} from 'vuex';
而後還在computed計算屬性裏寫以下代碼:
computed:mapState({ count:state=>state.count })
三、經過mapState數組賦值
computed:mapState(["count"])
這個算是最簡單的寫法了,在實際項目開發當中也常常這樣使用。
三、Mutations狀態修改
Vuex提供了commit方法來修改狀態,咱們粘貼出第一節課的代碼內容,簡單回顧一下,咱們在button上的修改方法。
<button @click="$store.commit('add')">+</button> <button @click="$store.commit('reduce')">-</button>
store.js文件:
onst mutations={ add(state){ state.count++; }, reduce(state){ state.count--; } }
這只是一個最簡單的修改狀態的操做,在實際項目中咱們經常須要在修改狀態時傳值。好比上邊的例子,是咱們每次只加1,而如今咱們要經過所傳的值進行相加。其實咱們只須要在Mutations裏再加上一個參數,並在commit的時候傳遞就就能夠了。咱們來看具體代碼:
如今store.js文件裏給add方法加上一個參數n。添加的地方我已經標黃了。
const mutations={ add(state,n){ state.count+=n; }, reduce(state){ state.count--; } }
在Count.vue裏修改按鈕的commit( )方法傳遞的參數,咱們傳遞10,意思就是每次加10.
<p> <button @click="$store.commit('add',10)">+</button> <button @click="$store.commit('reduce')">-</button> </p>
這樣兩個簡單的修改咱們就完成了傳值,咱們能夠在瀏覽器中實驗一下了。
實際開發中咱們也不喜歡看到$store.commit( )這樣的方法出現,咱們但願跟調用模板裏的方法同樣調用。
例如:@click=」reduce」 就和沒引用vuex插件同樣。
要達到這種寫法,只須要簡單的兩部就能夠了:
import { mapState,mapMutations } from 'vuex';
2. 在模板的<script>標籤裏添加methods屬性,並加入mapMutations
methods:mapMutations([ 'add','reduce' ]),
經過上邊兩步,咱們已經能夠在模板中直接使用咱們的reduce或者add方法了,就像下面這樣。
<button @click="reduce">-</button>
備註:
若是想將編寫完畢的vue項目上傳到服務器上發佈,須要在config目錄下的index.js文件下找到:
assetsPublicPath: '/', 把它變爲assetsPublicPath: './',
而後運行npm run build進行項目打包
四、getters計算過濾操做
getters從表面是得到的意思,能夠把他看做在獲取數據以前進行的一種再編輯,至關於對數據的一個過濾和加工。你能夠把它看做store.js的計算屬性。
好比咱們如今要對store.js文件中的count進行一個計算屬性的操做,就是在它輸出前,給它加上100.
咱們首先要在store.js裏用const聲明咱們的getters屬性。
const getters = { count:function(state){ return state.count +=100; } }
寫好了gettters以後,咱們還須要在Vuex.Store()裏引入,因爲以前咱們已經引入了state盒mutations,因此引入裏有三個引入屬性。代碼以下,
export default new Vuex.Store({ state,mutations,getters })
在store.js裏的配置算是完成了,咱們須要到模板頁對computed進行配置。在vue 的構造器裏邊只能有一個computed屬性,若是你寫多個,只有最後一個computed屬性可用,因此要對上節課寫的computed屬性進行一個改造。改造時咱們使用ES6中的展開運算符」…」。
computed:{ ...mapState(["count"]), count(){ return this.$store.getters.count; } },
須要注意的是,你寫了這個配置後,在每次count 的值發生變化的時候,都會進行加100的操做。
咱們都知道state和mutations都有map的引用方法把咱們模板中的編碼進行簡化,咱們的getters也是有的,咱們來看一下代碼。
首先用import引入咱們的mapGetters
import { mapState,mapMutations,mapGetters } from 'vuex';
在computed屬性中加入mapGetters
...mapGetters(["count"])
五、actoin異步修改狀態
actions和以前講的Mutations功能基本同樣,不一樣點是,actions是異步的改變state狀態,而Mutations是同步改變狀態
actions是能夠調用Mutations裏的方法的,咱們仍是繼續在上節課的代碼基礎上進行學習,在actions裏調用add和reduce兩個方法。
const actions={
addAction(context,n){
context.commit('add',n);
},
reduceAction({commit},n){
commit('reduce',n)
}
}
在actions裏寫了兩個方法addAction和reduceAction,在方法體裏,咱們都用commit調用了Mutations裏邊的方法。細心的小夥伴會發現這兩個方法傳遞的參數也不同。
咱們須要在count.vue模板中編寫代碼,讓actions生效。咱們先複製兩個之前有的按鈕,並改爲咱們的actions裏的方法名,分別是:addAction和reduceAction。
<p>
<button @click="addAction(50)">+</button>
<button @click="reduceAction(50)">-</button>
</p>
改造一下咱們的methods方法,首先仍是用擴展運算符把mapMutations和mapActions加入。
methods:{ ...mapMutations([ 'add','reduce' ]), ...mapActions(['addAction','reduceAction']) },
你還要記得用import把咱們的mapActions引入纔可使用。
咱們如今看的效果和咱們用Mutations做的如出一轍,確定有的小夥伴會好奇,那actions有什麼用,咱們爲了演示actions的異步功能,咱們增長一個計時器(setTimeOut)延遲執行。在addAction裏使用setTimeOut進行延遲執行
const actions={
addAction(context,n){
context.commit('add',n);
setTimeout(()=>context.commit('reduce',n),3000);
console.log('我比reduce先執行')
},
reduceAction({commit},n){
commit('reduce',n)
}
}
六、modules模塊組
隨着項目的複雜性增長,咱們共享的狀態愈來愈多,這時候咱們就須要把咱們狀態的各類操做進行一個分組,分組後再進行按組編寫。那今天咱們就學習一下module:狀態管理器的模塊組操做。
在vuex/store.js中聲明模塊組,咱們仍是用咱們的const常量的方法聲明模塊組。代碼以下:
const moduleA={
state,mutations,getters,actions
}
聲明好後,咱們須要修改原來 Vuex.Stroe裏的值:
export default new Vuex.Store({ modules:{a:moduleA} })
如今咱們要在模板中使用count狀態,要用插值的形式寫入。
<h3>{{$store.state.a.count}}</h3>
若是想用簡單的方法引入,仍是要在咱們的計算屬性中rutrun咱們的狀態。寫法以下:
computed:{ count(){ return this.$store.state.a.count; } },