奮鬥是這麼個過程,當時不覺累,過後不會悔。走一段再回頭,會發現一個更強的本身,宛如新生。
你好,我是夢陽辰!期待與你相遇!
文章較長,切勿心急氣躁,不然將一事無成!css
學習Vue前,咱們須要先了解一些MVVM,由於它很重要。
雖然沒有徹底遵循 MVVM 模型,可是 Vue 的設計也受到了它的啓發。html
1.什麼是MVVM?
MVVM (Model-View-ViewModel)是一種軟件架構設計模式,由微軟WPF(用於替代
WinForm,之前就是用這個技術開發桌面應用程序的)和Silverlight(相似於Java Applet,簡單點說就是在瀏覽器上運行的 WPF)的架構師Ken Cooper和Ted Peters開發,是一種簡化用戶界面的事件驅動編程方式。由John Gossman(一樣也是WPF和Silverlight的架構師)於2005年在他的博客上發表。前端
MVVM源自於經典的MVC ( Model-View-Controller)模式。MVVM的核心是ViewModeA層,負責轉換 Model中的數據對象來讓數據變得更容易管理和使用,其做用以下:vue
該層向上與視圖層進行雙向數據綁定 向下與 Model層經過接口請求進行數據交互
MVVM已經至關成熟了,主要運用但不只僅在網絡應用程序開發中。當下流行的MVVM框架有Vue.js , Angulars等。
02.爲何要使用MVVMnode
MVVM模式和MVC模式同樣,主要目的是分離視圖(View)和模型(Model),有幾大好處
。
低耦合:視圖(View)能夠獨立於Model變化和修改,一個ViewModel能夠綁定到不一樣的View 上,當View變化的時候Model能夠不變,當Model變化的時候View 也能夠不變。webpack
可複用:你能夠把一些視圖邏輯放在一個ViewModel裏面,讓不少View重用這段視圖邏輯。ios
獨立開發:開發人員能夠專一於業務邏輯和數據的開發(ViewModel),設計人員能夠專一於頁面設計。git
可測試:界面素來是比較難於測試的,而如今測試能夠針對ViewModel來寫。
3.MVVM的組成部分
View
View是視圖層,也就是用戶界面。前端主要由 HTNL和Css來構建,爲了更方便地展示ViewNodel或者Model層的數據,已經產生了各類各樣的先後端模板語言,好比FreeMarker.Thymeleaf等等,各大 MVVM框架如Vue.js,AngularJS,EJS等也都有本身用來構建用戶界面的內置模板語言。es6
Model
Model是指數據模型,泛指後端進行的各類業務邏輯處理和數據操控,主要圍繞數據庫系統展開。這裏的難點主要在於須要和前端約定統一的接口規則
ViewModel
ViewModel是由前端開發人員組織生成和維護的視圖數據層。在這一層,前端開發者對從後端獲取的 Model數據進行轉換處理,作二次封裝,以生成符合View層使用預期的視圖數據模型。github
須要注意的是ViewModel所封裝出來的數據模型包括視圖的狀態和行爲兩部分,而Model層的數據模型是隻包含狀態的。
好比頁面的這一塊展現什麼,那一塊展現什麼這些都屬於視圖狀態(展現)。
頁面加載進來時發生什麼,點擊這一塊發生什麼,這一塊滾動時發生什麼這些都屬於視圖行爲(交互)視圖狀態和行爲都封裝在了ViewModel裏。這樣的封裝使得ViewModel能夠完整地去描述View層`。因爲實現了雙向綁定,ViewModel的內容會實時展示在View層,這是激動人心的,由於前端開發者不再必低效又麻煩地經過操縱DOM去更新視圖。
MVVM框架已經把最髒最累的一塊作好了,咱們開發者只須要處理和維護ViewModel,更新數據視圖就會自動獲得相應更新,真正實現事件驅動編程。
View層展示的不是Model層的數據,而是viewModel 的數據,由ViewModel負責與Model層交互,這就徹底解耦了View層和Model層,這個解耦是相當重要的,它是先後端分離方案實施的重要一環。
Vue(讀音/vju/,相似於view)是一套用於構建用戶界面的漸進式框架,發佈於2014年2月。與其它大型框架不一樣的是,Vue被設計爲能夠自底向上逐層應用。Vue的核心庫只關注視圖層,不只易於上手,還便於與第三方庫(如: vue-router,vue-resource,vuex)或既有項目整合。
漸進式意味着你能夠將Vue做爲你應用的一部分嵌入其中,帶來更豐富的交互體驗。
或者若是你但願將更多的業務邏輯使用Vue實現,那麼Vue的核心庫以及其生態系統。
好比Core+Vue-router+Vuex,也能夠知足你各類各樣的需求。
Vue.js(讀音 /vjuː/, 相似於 view) 是一套構建用戶界面的漸進式框架。
Vue 只關注視圖層, 採用自底向上增量開發的設計。
Vue 的目標是經過儘量簡單的 API 實現響應的數據綁定和組合的視圖組件。
1.MVVM模式的實現者
Model:模型層,在這裏表示JavaScript對象
View:視圖層,在這裏表示 DOM(HTML操做的元素)
ViewModel:鏈接視圖和數據的中間件,Vue.js 就是 MVVM中的ViewModel層的實現者在MVVM架構中,是不容許數據和視圖直接通訊的,只能經過ViewModel來通訊,而ViewModel就是定義了一個 Observer觀察者
ViewModel可以觀察到數據的變化,並對視圖對應的內容進行更新
ViewModel可以監聽到視圖的變化,並可以通知數據發生改變
至此,咱們就明白了,Vue.js 就是一個MVVM的實現者,他的核心就是實現了DOM監聽與據綁定
Vue有不少特色和Web開發中常見的高級功能
解耦視圖和數據
可複用的組件
前端路由技術
狀態管理
虛擬DOM
2.爲何要使用Vue.js
輕量級,體積小是一個重要指標。Vue.js壓縮後有只有20多kb (Angular壓縮後56kb+,React壓縮後44kb+)
移動優先。更適合移動端,好比移動端的Touch事件·易上手,學習曲線平穩,文檔齊全
吸收了Angular(模塊化)和React(虛擬DOM)的長處,並擁有本身獨特的功能,如:計算屬性
開源,社區活躍度高
3.vue初體驗
Vue.js的安裝
方式一:
導入在線的cdn
對於製做原型或學習,你能夠這樣使用最新版本:
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
方式二:到官網下載文件:
https://vuejs.org/js/vue.js
方式三:NPM安裝(重點)
在用 Vue 構建大型應用時推薦使用 NPM 安裝[1]。NPM 能很好地和諸如 webpack 或 Browserify 模塊打包器配合使用。同時 Vue 也提供配套工具來開發單文件組件。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>helloVue</title> <!--1.導入vue.js--> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script></head><body><div id="app"> {{message}}</div><script> var vm = new Vue({ el: "#app", data: { message: "helloVue" } });</script></body></html>
爲了可以更直觀的體驗Vue 帶來的數據綁定功能,咱們須要在瀏覽器測試一番,操做流程以下:
一、在瀏覽器上運行第一個Vue應用程序,進入開發者工具
二、在控制檯輸入vm.message = ‘Hello World’,而後回車,你會發現瀏覽器中顯示的內容會直接變成Hello World
此時就能夠在控制檯直接輸入vm.message來修改值,中間是能夠省略data的,在這個操做中,我並無主動操做DOM,就讓頁面的內容發生了變化,這就是藉助了Vue的數據綁定功能實現的;MVVM模式中要求ViewModel層就是使用觀察者模式來實現數據的監聽與綁定,以作到數據與視圖的快速響應。
建立Vue實例傳入的選項(options)
目前掌握這些選項:
el
√類型: string | HTMLlement
√做用∶決定以後Vue實例會管理哪個DOM。
data:
√類型:Object | Function(組件中data必須是一個函數)
√做用:Vue實例對應的數據對象。
methods:
√類型∶{ [key: string]: Function }
√做用∶定義屬於Vue的一些方法,能夠在其餘地方調用,也能夠在指令中使用。
Mustache語法:雙括號表達式。
mustache語法中,不只能夠直接寫變量,也能夠寫簡單的表達式。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"> {{message}} {{message + name}} {{price*3}}</div><script> const app = new Vue({ el:"#app", data:{ message:"夢陽辰你好!", name:"夢陽辰", price:1000 } });</script></body></html>
不隨數據的改變而改變
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"> {{message}} <h3 v-once>{{name}}</h3><!--不會隨着數據的改變而改變--></div><script> const app = new Vue({ el:"#app", data:{ message:"夢陽辰你好!", name:"夢陽辰", price:1000 } });</script></body></html>
服務器返回的是帶html標籤的數據,v-html將數據展現。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"> <h3 v-html="url"></h3><!----></div><script> const app = new Vue({ el:"#app", data:{ message:"夢陽辰你好!", url:'<a href="https://www.baidu.com">百度一下</a>' } });</script></body></html>
做用和Mustache比較相似。但mustache更加靈活。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"> <h3 v-html="url"></h3> <h2 v-text="message"></h2></div><script> const app = new Vue({ el:"#app", data:{ message:"夢陽辰你好!", url:'<a href="https://www.baidu.com">百度一下</a>' } });</script></body></html>
將標籤中的內容原封不動的輸出。不進行任何解析。
解決js代碼執行慢而致使的內容閃爍問題。(後面採用虛擬dom,就不會存在這個問題)
由於是先加載標籤,在運行js代碼。
在vue解析以前,div中有一個屬性v-cloak
在vue解析以後,div中沒有一個屬性v-cloak.
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script> <style> [v-cloak]{ display: none; } </style></head><body><div id="app" v-cloak> <h2>{{message}}</h2></div><script> setTimeout(function () { const app = new Vue({ el:"#app", data:{ message:"夢陽辰你好!", url:'<a href="https://www.baidu.com">百度一下</a>' } }); },1000)</script></body></html>
注意咱們再也不和 HTML 直接交互了。一個 Vue 應用會將其掛載到一個 DOM 元素上 (對於這個例子是 #app) 而後對其進行徹底控制。那個 HTML 是咱們的入口,但其他都會發生在新建立的 Vue 實例內部。
除了文本插值,咱們還能夠像這樣來綁定元素 attribute:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title></head><body><!--view層 模板--><div id="app2"> <span v-bind:title="message">鼠標懸停幾秒鐘查看此處動態綁定的提示信息!</span></div></body><!--導入js--><script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script><script> var vm = new Vue({ el: "#app2", data: { message: "hello,vue" } })</script></html>
語法糖::
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script> <style> [v-cloak]{ display: none; } </style></head><body><div id="app" v-cloak> <img :src="imgUrl" alt="風景"></div><script> setTimeout(function () { const app = new Vue({ el:"#app", data:{ message:"夢陽辰你好!", imgUrl:"https://dss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=2853553659,1775735885&fm=26&gp=0.jpg" } }); },1000)</script></body></html>
v-bind attribute 被稱爲指令。指令帶有前綴 v-,以表示它們是 Vue 提供的特殊 attribute。可能你已經猜到了,它們會在渲染的 DOM 上應用特殊的響應式行爲。在這裏,該指令的意思是:「將這個元素節點的 title attribute 和 Vue 實例的 message property 保持一致」。
若是你再次打開瀏覽器的 JavaScript 控制檯,輸入 app2.message = ‘新消息’,就會再一次看到這個綁定了 title attribute 的 HTML 已經進行了更新。
綁定classs
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script> <style> .first{ color: lawngreen; } </style></head><body><div id="app"> <h3 :class="active">{{message}}</h3></div><script> const app = new Vue({ el:"#app", data:{ message:"夢陽辰你好!", active:'first' } });</script></body></html>
案例二(對象語法)
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script> <style> .active{ color: lawngreen; } </style></head><body><div id="app"> <!--<h3 :class="active">{{message}}</h3>--> <h3 :class="{active:isActive,line:isLine}">{{message}}</h3><!--對象--> <h3 :class="getClasses()">{{message}}</h3><!--對象--> <button v-on:click="btn">改變顏色</button></div><script> const app = new Vue({ el:"#app", data:{ message:"夢陽辰你好!", isActive:true, isLine:false }, methods:{ btn:function () { this.isActive=!this.isActive; }, getClasses:function () { return {active:this.isActive,line:this.isLine}; } } });</script></body></html>
案例三(數組語法)瞭解
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script> <style> .active{ color: lawngreen; } </style></head><body><div id="app"> <h3 class="title" :class="[active,line]">{{message}}</h3></div><script> const app = new Vue({ el:"#app", data:{ message:"夢陽辰你好!", active:"active", line:"fasd" } });</script></body></html>
v-bind動態綁定樣式(style)
組件開發時經常使用。
若是不加單或雙引號會看成變量使用。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script> <style> .active{ color: lawngreen; } </style></head><body><div id="app"><!--<h3 class="title" :style="{key(屬性名):value(屬性值))}">{{message}}</h3>--> <h3 class="title" :style="{color:'red'}">{{message}}</h3> <h3 class="title" :style="{color:red}">{{message}}</h3></div><script> const app = new Vue({ el:"#app", data:{ message:"夢陽辰你好!", red:"yellow" } });</script></body></html>
數組語法:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script> <style> .active{ color: lawngreen; } </style></head><body><div id="app"> <h3 class="title" :style="[style1,style2]">{{message}}</h3></div><script> const app = new Vue({ el:"#app", data:{ message:"夢陽辰你好!", style1:{fontSize:"50px"}, style2:{color:"green"} } });</script></body></html>
控制切換一個元素是否顯示至關簡單:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title></head><body><!--view層 模板--><div id="app-3"> <p v-if="seen">如今你看到我了</p></div></body><!--導入js--><script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script><script> var app3 = new Vue({ el: '#app-3', data: { seen: true } })</script></html>
繼續在控制檯輸入 app3.seen = false,你會發現以前顯示的消息消失了。
例二:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title></head><body><!--view層 模板--><div id="app"> <h3 v-if="type==='A'">A</h3> <h3 v-else-if="type==='B'">B</h3> <h3 v-else>C</h3></div></body><!--導入js--><script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script><script> var vm = new Vue({ el: "#app", data: { type: "1" } })</script></html>
登陸切換:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"> <span v-if="isUser"> <label for="userName" key="userName">用戶帳號</label> <input type="text" id="userName" placeholder="用戶帳號"> </span> <span v-else> <label for="email" key="email">用戶郵箱</label> <input type="text" id="email" placeholder="用戶郵箱"> </span> <button @click="isUser = !isUser">切換登陸</button></div><script> const app = new Vue({ el:"#app", data:{ message:"你好,夢陽辰!", isUser:true } });</script></body></html>
vue在進行Dom渲染時,出於性能的考慮會進行復用已經存在的元素,會根據key的值決定是否複用。
和v-if做用相同。
區別:
當v-show爲false不顯示時:它的元素仍是存在,只不過它的display屬性的值爲none。
而v-if爲false時:它的元素根本就不會存在在dom中。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"> <h3 v-if="isUser">你好,夢陽辰!</h3> <h3 v-show="isUser">你好,夢陽辰!</h3></div><script> const app = new Vue({ el:"#app", data:{ message:"你好,夢陽辰!", isUser:false } });</script></body></html>
遍歷數組:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"> <ul> <li v-for="(item,index) in names"> {{index+1}}.{{item}} </li> </ul></div><script> const app = new Vue({ el:"#app", data:{ message:"你好,夢陽辰!", names:["夢陽辰","mengyangchen"] } });</script></body></html>
遍歷對象:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"> <ul> <li v-for="(value,key) in info"> {{key}}.{{value}} </li> </ul> <ul> <li v-for="(value,key,index) in info"> {{key}}:{{value}}---{{index}} </li> </ul></div><script> const app = new Vue({ el:"#app", data:{ message:"你好,夢陽辰!", info:{ name:"夢陽辰", age:20, height:171 } } });</script></body></html>
v-for綁定key與不綁定key區別:
綁定key能夠高效的更新虛擬DOM。
在中間插入元素:(diff算法)
綁定的key若是值沒有變化,能夠複用。
可是沒有綁定的話,會將指定的值改成插入的值,後續的值依次改(效率較低)
綁定的key的值應該和顯示的內容一致。
數組哪些方法是響應式的:
數據改變,界面內容也隨之改變。
push()後面添加 pop()最後一個刪除 shift()第一個刪除 unshift()數組最前面添加元素 splice()刪除/插入/替換元素 splice(start,刪除元素的個數) splice(start,0,你要插入的元素) splice(start,替換元素的個數,新的替換值) sort()排序 reverse()反轉
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"> <ul> <li v-for="item in names" :key="item" > {{item}} </li> </ul> <button @click="way">操做數組</button></div><script> const app = new Vue({ el:"#app", data:{ message:"你好,夢陽辰!", names:["夢陽辰","mengyangchen"] }, methods:{ way(){ this.names.splice(0,1,"你好"); /*Vue.set(this.names,0,"fafd");*/ } } });</script></body></html>
點擊哪一個值,哪一個值就亮色
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script> <style> .active{ color: lawngreen; } </style></head><body><div id="app"> <ul> <li v-for="(item,index) in moives" :class="{active:currentIndex===index}" @click="way(index)">{{item}}</li> </ul></div><script> const app = new Vue({ el:"#app", data:{ message:"夢陽辰你好!", moives:["海王","海賊王","魁拔"], currentIndex:0 }, methods:{ way(index){ this.currentIndex=index; } } });</script></body></html>
爲了讓用戶和你的應用進行交互,咱們能夠用 v-on 指令添加一個事件監聽器,經過它調用在 Vue 實例中定義的方法:
<!DOCTYPE html><html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml"><head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script></head><body><div id="app-5"> <p>{{ message }}</p> <button v-on:click="reverseMessage">反轉消息</button></div><script> var app5 = new Vue({ el: '#app-5', data: { message: 'Hello Vue.js!' }, methods: { reverseMessage: function () { this.message = this.message.split('').reverse().join('') } } })</script></body></html>
計數器:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body> <div id="app"> <h2>當前計數:{{counter}}</h2> <!--<button v-on:click="counter++">+</button> <button v-on:click="counter--">-</button>--> <button v-on:click="way1">+</button> <button @click="way2">-</button> </div> <script> const app = new Vue({ el:"#app", data:{ counter:0, }, methods:{ way1:function () { this.counter++; }, way2:function () { this.counter--; } } }); </script></body></html>
@click爲v-on:click的簡寫。
methods屬性:定義方法。
注意在 reverseMessage 方法中,咱們更新了應用的狀態,但沒有觸碰 DOM——全部的 DOM 操做都由 Vue 來處理,你編寫的代碼只須要關注邏輯層面便可。
當經過methods中定義方法,以供@click調用時,須要注意參數問題:狀況一∶若是該方法不須要額外參數,那麼方法後的()能夠不添加。
可是注意:若是方法自己中有一個參數,那麼會默認將原生事件event參數傳遞進去
狀況二∶若是須要同時傳入某個參數,同時須要event時,能夠經過**$event**傳入事件。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"> <button @click="way1">1</button> <button @click="way1('你好')">2</button> <button @click="way2('夢陽辰',$event)">3</button></div><script> const app = new Vue({ el:"#app", data:{ counter:0, }, methods:{ way1:function (abc) { alert(abc); }, way2:function (abc,event) { alert(event); } } });</script></body></html>
v-on的修飾符:
Vue提供了修飾符來幫助咱們方便的處理一些事件
.stop-調用event.stopPropagation()阻止冒泡 .prevent -調用event.preventDefault() .{(keyCode | kelyAlias}-只當事件是從特定鍵觸發時才觸發回調。 .native -監聽組件根元素的原生事件。 .once -只觸發一次回調。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"> <!--.stop--> <div @click="divClick"> aaaaa <button @click.stop="btnClick">按鈕</button> </div> <!--2.prevent修飾符--> <form action="baidu"> <input type="submit" value="提交" @click.prevent="submitClick"> </form> <!--監聽某個鍵帽--> <input type="text" @keyup.enter="keyUp"></div><script> const app = new Vue({ el:"#app", data:{ counter:0, }, methods:{ divClick(){ alert("div觸發") }, btnClick(){ alert("按鈕觸發") }, submitClick(){ alert("阻止提交") }, keyUp(){ alert("它按我了!") } } });</script></body></html>
Vue 還提供了 v-model 指令,它能輕鬆實現表單輸入和應用狀態之間的雙向綁定。
1. 什麼是雙向綁定
Vue.js是一個MVVM框架,即數據雙向綁定,即當數據發生變化的時候,視圖也就發生變化,當視圖發生變化的時候,數據也會跟着同步變化。這也算是Vue.js的精髓之處了。
值得注意的是,咱們所說的數據雙向綁定,必定是對於UI控件來講的,非UI控件不會涉及到數據雙向綁定。單向數據綁定是使用狀態管理工具的前提。若是咱們使用vuex,那麼數據流也是單項的,這時就會和雙向數據綁定有衝突。
2. 爲何要實現數據的雙向綁定
在Vue.js 中,若是使用vuex ,實際上數據仍是單向的,之因此說是數據雙向綁定,這是用的UI控件來講,對於咱們處理表單,Vue.js的雙向數據綁定用起來就特別舒服了。即二者並不互斥,在全局性數據流使用單項,方便跟蹤;局部性數據流使用雙向,簡單易操做。
3. 在表單中使用雙向數據綁定
你能夠用v-model指令在表單 、 及 元素上建立雙向數據綁定。它會根據控件類型自動選取正確的方法來更新元素。儘管有些神奇,但v-model本質上不過是語法糖。它負責監聽戶的輸入事件以更新數據,並對一些極端場景進行一些特殊處理。
本身實現雙向綁定:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"><!--<input type="text" v-model= "message">--><input type="text" :value="message" @input="valuechange"><!--<input type="text" :value="message" @input= "message =$event.target.value">--> <h2 :key="message">{{message}}</h2><!--key表示--></div><script>const app = new Vue({ el:"#app", data: { message: "你好" }, methods: { valuechange(event){ this.message = event.target.value; } }})</script></body></html>
注意:v-model會忽略全部元素的value、checked、selected特性的初始值而老是將Vue實例的數據做爲數據來源,你應該經過JavaScript在組件的data選項中聲明。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script></head><body><div id="app-6"> <p>{{ message }}</p> <input v-model="message"></div><script> var app6 = new Vue({ el: '#app-6', data: { message: 'Hello Vue!' } });</script></body></html>
radio:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"> <input type="radio" value="男" v-model="gender">男 <input type="radio" value="女" v-model="gender">女 <h3 :key="gender">你選擇的是:{{gender}}</h3></div><script> const app = new Vue({ el:"#app", data: { message: "你好", gender:"" } })</script></body></html>
select:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script></head><body><!--view層 模板--><div id="app"> 下拉框: <select v-model="selected"> <option value="" disabled>-請選擇-</option> <option>A</option> <option>B</option> <option>C</option> </select> <p>value:{{selected}}</p></div></body><script> var vm = new Vue({ el: "#app", data: { selected: "" } })</script></html>
在select標籤上加multiple
能夠選擇多個值。
單選框和多選框:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"> <label for="agree"> <input type="checkbox" id="agree" v-model="isAgree">贊成協議 </label> <h3>你選擇的是:{{ isAgree}}</h3> <button :disabled=!isAgree>下一步</button> <!--多選框--><p>---------------------愛好-------------------</p> <input type="checkbox" value="籃球" v-model="hobbies">籃球 <input type="checkbox" value="足球" v-model="hobbies">足球 <input type="checkbox" value="乒乓球" v-model="hobbies">乒乓球 <h3 :key="hobbies">你的愛好是:{{hobbies}}</h3></div><script> const app = new Vue({ el:"#app", data: { message: "你好", isAgree:false, hobbies:[] } })</script></body></html>
值綁定
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"> <label v-for="item in originHobbies" > <input type="checkbox" :value=item v-model="hobbies">{{item}} </label> <h3 :key="hobbies">你的愛好是:{{hobbies}}</h3></div><script> const app = new Vue({ el:"#app", data: { message: "你好", isAgree:false, hobbies:[], originHobbies:['籃球','足球','乒乓球'] } })</script></body></html>
v-model的修飾符
lazy 取消實時綁定,當按下回車鍵或失去焦點時進行數據的更新。 number v-model默認給變量賦值的時候,賦值爲string類型。加上number修飾符後... trim 去除左右兩邊的空格
組件系統是 Vue 的另外一個重要概念,由於它是一種抽象,容許咱們使用小型、獨立和一般可複用的組件構建大型應用。仔細想一想,幾乎任意類型的應用界面均可以抽象爲一個組件樹:
它提供了一種抽象,讓咱們能夠開發出一個個獨立可複用的小組件來構造咱們的應用。
任何的應業用都會被抽象出一顆組件樹。
有了組件化的思想,咱們在以後的開發中就要充分的利用它。儘量的將頁面拆分紅一個個小的、可複用的組件。
這樣讓咱們的代碼更加方便組織和管理,而且擴展性也更強。
組件的使用分紅三個步驟:
建立組件構造器
註冊組件
使用組件
原始方式(不推薦使用,建議使用語法糖)
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><cpn></cpn><div id="app"> <my-cpn></my-cpn> <my-cpn></my-cpn> <my-cpn></my-cpn></div><script> /*es6可使用`來代替"和' * */ //1.建立組件構造器對象 const cpn = Vue.extend({ template:`<div> <h3>我是標題</h3> <p>我是內容1</p> <p>我是內容2</p> </div>` }) //2.註冊組件 Vue.component('my-cpn',cpn) const app = new Vue({ el:"#app", data:{ message:"夢陽辰你好!", } })</script></body></html>
在 Vue 裏,一個組件本質上是一個擁有預約義選項的一個 Vue 實例。在 Vue 中註冊組件很簡單:
語法糖:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script></head><body><ol id="app"> <!-- 建立一個 todo-item 組件的實例 --> <todo-item></todo-item></ol></body><script> // 定義名爲 todo-item 的新組件 Vue.component('todo-item', { template: '<li>這是個待辦項</li>' }); var app = new Vue({ el:"#app" });</script></html>
可是這樣會爲每一個待辦項渲染一樣的文本,這看起來並不炫酷。咱們應該能從父做用域將數據傳到子組件纔對。讓咱們來修改一下組件的定義,使之可以接受一個 prop:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script></head><body><ol id="app"> <!-- 如今咱們爲每一個 todo-item 提供 todo 對象 todo 對象是變量,即其內容能夠是動態的。 咱們也須要爲每一個組件提供一個「key」,稍後再 做詳細解釋。 --> <todo-item v-for="item in groceryList" v-bind:todo="item" v-bind:key="item.id" ></todo-item> </ol></body><script> Vue.component('todo-item', { // todo-item 組件如今接受一個 // "prop",相似於一個自定義 attribute。 // 這個 prop 名爲 todo。 props: ['todo'], template: '<li>{{ todo.text }}</li>' }) var app7 = new Vue({ el: '#app', data: { groceryList: [ { id: 0, text: '蔬菜' }, { id: 1, text: '奶酪' }, { id: 2, text: '隨便其它什麼人吃的東西' } ] } })</script></html>
咱們已經設法將應用分割成了兩個更小的單元。子單元經過 prop 接口與父單元進行了良好的解耦。咱們如今能夠進一步改進 <todo-item>
組件,提供更爲複雜的模板和邏輯,而不會影響到父單元。
全局組件和局部組件
能夠在多個vue實例下使用。
在Vue實例中註冊就是局部組件:
//1.建立組件構造器對象 const cpn = Vue.extend({ template:`<div> <h3>我是標題</h3> <p>我是內容1</p> <p>我是內容2</p> </div>` }) var app = new Vue({ el:"#app", components:{//mycpn就是使用組件時的標籤名mycpn:cpn} });
父組件和子組件的區別:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"> <mycpn2></mycpn2></div><script> /*es6可使用`來代替"和' * */ //1.建立組件構造器對象 //子 const cpn1 = Vue.extend({ template:`<div> <h3>我是標題</h3> <p>我是內容1</p> <p>我是內容2</p> </div>` }) //父 const cpn2 = Vue.extend({ template:`<div> <h3>我是頭部</h3> <p>我是內容1</p> <p>我是尾部</p> <cpn></cpn> </div>` , components:{ cpn:cpn1 } }) //2.註冊組件 Vue.component('my-cpn',cpn1); const app = new Vue({ el:"#app", data:{ message:"夢陽辰你好!", }, components:{ mycpn2:cpn2 } });</script></body></html>
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><cpn></cpn><div id="app"> <my-cpn></my-cpn></div><!--方法1--><!--<script type="text/x-template" id="cpn"> <div> <h3>我是標題</h3> <p>我是內容1</p> <p>我是內容2</p> </div></script>--><!--方法二--><template id="cpn"> <div> <h3>我是標題</h3> <p>我是內容1</p> <p>我是內容2</p> </div></template><script> /*es6可使用`來代替"和' * */ //2.註冊組件 Vue.component('my-cpn',{ template:id='#cpn' }) const app = new Vue({ el:"#app", data:{ message:"夢陽辰你好!", } })</script></body></html>
咱們發現不能訪問,並且即便能夠訪問,若是將全部的數據都放在Vue實例中,Vue實例就會變的很是臃腫。
結論: Vue組件應該有本身保存數據的地方。
組件對象也有一個data屬性(也能夠有methods等屬性,下面咱們有用到)只是這個data屬性必須是一個函數。
並且這個函數返回一個對象,對象內部保存着數據
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><cpn></cpn><div id="app"> <my-cpn></my-cpn></div><template id="cpn"> <div> <h3>{{title}}</h3> <p>我是內容1</p> <p>我是內容2</p> </div></template><script> /*es6可使用`來代替"和' * */ //2.註冊組件 Vue.component('my-cpn',{ template:`#cpn`, data(){ return{ title:'有點東西!' } } }) const app = new Vue({ el:"#app", data:{ message:"夢陽辰你好!", } })</script></body></html>
data屬性爲何必須是一個函數?
若是是一個屬性(對象),應用重複來利用這個主鍵,可是但願各個組件中的數據是互不影響的,data是屬性就沒法作到,可是是函數的話就能夠作到各個組件實例互不影響。
咱們提到了子組件是不能引用父組件或者Vue實例的數據的。可是,在開發中,每每一些數據確實須要從上層傳遞到下層∶
好比在一個頁面中,咱們從服務器請求到了不少的數據。
其中一部分數據,並不是是咱們整個頁面的大組件來展現的,而是須要下面的子組件進行展現。
這個時候,並不會讓子組件再次發送一次網絡請求,而是直接讓大組件(父組件)將數據傳遞給小組件(子組件)。
如何進行父子組件的通訊呢?
經過props向子組件傳遞數據 經過事件向父組件發送消息
vue實例能夠看做是根組件。
props的使用
在組件中,使用選項props來聲明須要從父級接收到的數據。
props的值有兩種方式︰
方式一︰字符串數組,數組中的字符串就是傳遞時的名稱。
方式二∶對象,對象能夠設置傳遞時的類型,也能夠設置默認值等。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><cpn></cpn><div id="app"> <mycpn v-bind:cmovies="movies" :cmessage="message"></mycpn></div><template id="cpn"> <div> <p>我是內容1</p> <p>我是內容2</p> {{cmessage}} <ul> <li v-for="item in cmovies">{{item}}</li> </ul> </div></template><script> const cpn ={ template:`#cpn`, // props:['cmovies','cmessage'], //類型限制 /* props:{ cmovies:Array, cmessage:String, },*/ //提供默認值 /* props:{ cmessage:{ type:String, default:"fasdf", required:true//加上後表示必傳的值 } }*/ //類型是對象或者數組時,默認值必須時一個函數 props:{ cmovies:{ type:Array, default(){ return [] } } } , data(){ return{ title:'有點東西!' } }, methods:{ } } const app = new Vue({ el:"#app", data:{ message:"夢陽辰你好!", movies: ["海王","海賊王"] }, components:{ mycpn:cpn } })</script></body></html>
對於命名問題:
標籤(如img)、屬性名(如class) 均會自動在瀏覽器轉化爲小寫,對大小寫不敏感,因此用駝峯命名對存在問題。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><cpn></cpn><div id="app"> <mycpn v-bind:c-info="info" ></mycpn></div><template id="cpn"> <div> <p>我是內容1</p> <p>我是內容2</p> <h3>{{cInfo}}</h3> </div></template><script> const cpn ={ template:`#cpn`, //類型是對象或者數組時,默認值必須時一個函數 props:{ cInfo:{ type:Object, default(){ return {} } } }, data(){ return{ title:'有點東西!' } }, methods:{ } } const app = new Vue({ el:"#app", data:{ message:"夢陽辰你好!", info:{ name:"夢陽辰", age:20, gender:"男" } }, components:{ mycpn:cpn } })</script></body></html>
當子組件須要向父組件傳遞數據時,就要用到自定義事件了。
咱們以前學習的v-on不只僅能夠用於監聽DOM事件,也能夠用於組件間的自定義事件。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"> <mycpn v-bind:c-info="info" v-on:item-click="cpnClick"></mycpn></div><template id="cpn"> <div> <button v-for="item in categories" @click="btn(item)"> {{item.name}} </button> </div></template><script> /*子組件*/ const cpn ={ template:`#cpn`, //類型是對象或者數組時,默認值必須時一個函數 props:{ cInfo:{ type:Object, default(){ return {} } } }, data(){ return{ categories:[ {id:"a",name:"熱門推薦"}, {id:"b",name:"筆記本電腦"}, {id:"c",name:"手機"}, {id:"d",name:"化妝品"}, ] } }, methods:{ btn(item){ /*將信息傳遞給父組件,自定義事件*/ this.$emit('item-click',item); } } } /*父組件*/ const app = new Vue({ el:"#app", data:{ message:"夢陽辰你好!", info:{ name:"夢陽辰", age:20, gender:"男" } }, components:{ mycpn:cpn }, methods:{ cpnClick(item){ console.log(item) } } })</script></body></html>
父子互相影響數據
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body> <div id="app"> <cpn :number1="num1" :number2="num2" @num1_change="num1_change" @num2_change="num2_change" ></cpn> </div><template id="cpn"> <div> <h3 :key="number1">{{number1}}</h3> <h3 :key="temp_number1">{{temp_number1}}</h3> <input type="text" :value="temp_number1" @input="num1Input"> <h3 :key="number2">{{number2}}</h3> <h3 :key="temp_number2">{{temp_number2}}</h3> <input type="text" :value="temp_number2" @input="num2Input"> </div></template><script> //子組件 //父組件 const app = new Vue({ el:"#app", data:{ message:"夢陽辰", num1:0, num2:1 }, methods:{ num1_change(num){ this.num1=parseFloat(num) }, num2_change(num){ this.num2=parseFloat(num) } }, components:{ cpn:{//子組件 template:`#cpn`, props:{ number1:Number, number2:Number }, data(){ return{ temp_number1:this.number1, temp_number2:this.number2, } }, methods:{ num1Input(event){ this.temp_number1=event.target.value; /*將信息傳遞給父組件,自定義事件*/ this.$emit("num1_change",this.temp_number1); }, num2Input(event){ this.temp_number2=event.target.value; /*將信息傳遞給父組件,自定義事件*/ this.$emit("num2_change",this.temp_number2) } } } } })</script></body></html>
有時候咱們須要父組件直接訪問子組件,子組件直接訪問父組件,或者是子組件訪問根組件。
父組件訪問子組件:使用$children $refs reference
(引用)
子組件訪問父組件:使用$parent
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"> <cpn></cpn> <cpn></cpn> <cpn ref="aa"></cpn> <button @click="btn">按鈕</button></div><template id="cpn"> <div> <div>子組件</div> </div></template><script> //子組件 //父組件 const app = new Vue({ el:"#app", data:{ message:"夢陽辰", }, methods:{ btn(){ console.log(this.$children); this.$children[0].showMessage(); //alert(this.$children[2].name);//下標會改變,因此儘可能不要用下標拿屬性(這種適合遍歷拿全部的) /*$refs是對象類型,默認是一個空的對象,必須在組件上加ref屬性*/ alert(this.$refs.aa.name);//用這種方式最佳 } }, components:{ cpn:{//子組件 template:`#cpn`, data(){ return{ name:"我是夢陽辰!" } }, methods:{ showMessage(){ alert("你好!") } } } } })</script></body></html>
子組件訪問父組件:使用$parent
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"> <cpn></cpn></div><template id="cpn"> <div> <div>子組件1</div> <cpn1></cpn1> </div></template><template id="cpn1"> <div> <div>子組件2</div> <button @click="btn">按鈕</button> </div></template><script> //子組件 //父組件 const app = new Vue({ el:"#app", data:{ message:"夢陽辰", }, components:{ cpn:{//子組件 template:`#cpn`, /*第二個子組件,這裏不建議嵌套,只爲練習使用(由於耦合度高,複用性差)*/ data(){ return{ name:"我是夢陽辰1" } }, components: { cpn1:{ template: `#cpn1`, methods:{ btn(){ //訪問父組件 console.log(this.$parent) alert(this.$parent.name) /*訪問根組件*/ console.log(this.$root) } } } } } } })</script></body></html>
計算屬性的重點突出在屬性兩個字上(屬性是名詞),首先它是個屬性其次這個屬性有計算的能力(計算是動詞),這裏的計算就是個函數;簡單點說,它就是一個可以將計算結果緩存起來的屬性(將行爲轉化成了靜態的屬性),僅此而已;能夠想象爲緩存!
模板內的表達式很是便利,可是設計它們的初衷是用於簡單運算的。在模板中放入太多的邏輯會讓模板太重且難以維護。例如:
<div id="example"> {{ message.split('').reverse().join('') }}</div>
在這個地方,模板再也不是簡單的聲明式邏輯。你必須看一段時間才能意識到,這裏是想要顯示變量 message 的翻轉字符串。當你想要在模板中的多處包含此翻轉字符串時,就會更加難以處理。
因此,對於任何複雜邏輯,你都應當使用計算屬性。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title></head><body><!--view層 模板--><div id="app"> <div>currentTime1: {{currentTime1()}}</div> <div>currentTime2: {{currentTime2}}</div></div></body><!--導入js--><script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script><script> var vm = new Vue({ el: "#app", data: { message: "hello,world!" }, methods: { currentTime1: function () { return Date.now(); // 返回一個時間戳 } }, computed: { //計算屬性:methods,computed 方法名不能重名,重名字後,只會調用methods的方法 currentTime2: function () { this.message; // 返回一個時間戳 return Date.now(); } } })</script></html>
結論:
調用方法時,每次都須要進行計算,既然有計算過程則一定產生系統開銷,那若是這個結果是不常常變化的呢?此時就能夠考慮將這個結果緩存起來,採用計算屬性能夠很方便的作到這一點,計算屬性的主要特性就是爲了將不常常變化的計算結果進行緩存,以節約咱們的系統開銷。
實例生命週期鉤子
每一個 Vue 實例在被建立時都要通過一系列的初始化過程——例如,須要設置數據監聽、編譯模板、將實例掛載到 DOM 並在數據變化時更新 DOM 等。同時在這個過程當中也會運行一些叫作生命週期鉤子的函數,這給了用戶在不一樣階段添加本身的代碼的機會。
好比 created 鉤子能夠用來在一個實例被建立以後執行代碼:
new Vue({ data: { a: 1 }, created: function () { // `this` 指向 vm 實例 console.log('a is: ' + this.a) }})// => "a is: 1"
也有一些其它的鉤子,在實例生命週期的不一樣階段被調用,如 mounted、updated 和 destroyed。生命週期鉤子的 this 上下文指向調用它的 Vue 實例。
不要在選項 property 或回調上使用箭頭函數,好比 created: () => console.log(this.a) 或 vm.$watch('a', newValue => this.myMethod())。由於箭頭函數並無 this,this 會做爲變量一直向上級詞法做用域查找,直至找到爲止,常常致使 Uncaught TypeError: Cannot read property of undefined 或 Uncaught TypeError: this.myMethod is not a function 之類的錯誤。
生命週期圖示
Vue 實例有一個完整的生命週期,也就是從開始建立、初始化數據、編譯模板、掛載DOM、渲染→更新→渲染、卸載等一系列過程,咱們稱這是Vue的生命週期。通俗說就是Vue 實例從建立到銷燬的過程,就是生命週期。
在Vue的整個生命週期中,它提供了一系列的事件,可讓咱們在事件觸發時註冊JS方法,可讓咱們用本身註冊的JS方法控制整個大局,在這些事件響應方法中的this直接指向的是Vue 的實例。
1. 什麼是Axios
Axios是一個開源的能夠用在瀏覽器端和NodeJS 的異步通訊框架,它的主要做用就是實現AJAX異步通訊,其功能特色以下:
從瀏覽器中建立XMLHttpRequests
從node.js建立http請求
支持Promise API [JS中鏈式編程]
攔截請求和響應
轉換請求數據和響應數據
取消請求
自動轉換JSON數據
客戶端支持防護XSRF (跨站請求僞造)
GitHub: https://github.com/ axios/axios
中文文檔: http://www.axios-js.com/
cdn:
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.19.2/axios.min.js"></script>
2. 爲何要使用Axios
因爲Vue.js是一個視圖層框架且做者(尤雨溪) 嚴格準守SoC (關注度分離原則),因此Vue.js並不包含Ajax的通訊功能,爲了解決通訊問題,做者單獨開發了一個名爲vue-resource的插件,不過在進入2.0 版本之後中止了對該插件的維護並推薦了Axios 框架。少用jQuery,由於它操做Dom太頻繁 !
測試:
模擬後臺返回的json數據:
{ "name": "mengyangchen", "age": "20", "sex": "男", "url":"https://www.baidu.com", "address": { "street": "文苑路", "city": "南京", "country": "中國" }, "links": [ { "name": "bilibili", "url": "https://www.bilibili.com" }, { "name": "baidu", "url": "https://www.baidu.com" }, { "name": "cqh video", "url": "https://www.4399.com" } ]}
vue
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title></head><body><!--view層 模板--><div id="vue"> <div>{{info.name}}</div> <div>{{info.address.street}}</div> <a v-bind:href="info.url">點我進入</a></div></body><!--1.導入vue.js--><script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script><!--導入axios--><script src="https://cdn.bootcdn.net/ajax/libs/axios/0.19.2/axios.min.js"></script><script> var vm = new Vue({ el: "#vue", data: { items: ['Java','Python','Php'] }, //data:vm的屬性 //data():vm方法 data(){ return{ //請求的返回參數,必須和json字符串同樣 info:{ name: null, age: null, sex: null, url: null, address: { street: null, city: null, country: null } } } }, //鉤子函數,鏈式編程,ES6新特性 mounted(){ axios.get("../res/package.json").then(res => (this.info=res.data)) } })</script></html>
首頁
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="style.css" > <script src="../res/js/vue.js"></script></head><body><div id="app"> <div v-if="books.length"> <table> <thead> <tr> <th></th> <th>書籍名稱</th> <th>出版日期</th> <th>價格</th> <th>購買數量</th> <th>操做</th> </tr> </thead> <tbody> <tr v-for="(item,index) in books"> <td>{{item.id}}</td> <td>{{item.name}}</td> <td>{{item.date}}</td> <td>{{item.price | showPrice}}</td> <td> <button @click="way1(index)">+</button> {{item.count}} <button @click="way2(index)" v-bind:disabled="item.count<=1">-</button> </td> <td><button @click="remove(index)">移除</button></td> </tr> </tbody> </table> <h3>總價爲:{{totalPrice | showPrice}}</h3> </div> <h3 v-else>購物車爲空!</h3></div><script src="main.js"></script></body></html>
js代碼
const app = new Vue({ el:"#app", data:{ books:[ {id:23,name:"算法第四版",date:"1999-9-26",price:198,count:5}, {id:24,name:"計算機基礎",date:"1999-9-26",price:198,count:5}, {id:25,name:"Java核心卷",date:"1999-9-26",price:198,count:5}, {id:26,name:"深刻理解計算機原理",date:"1999-9-26",price:198,count:5} ] }, methods:{ way1(index){ this.books[index].count++; }, way2(index){ this.books[index].count--; }, remove(index){ this.books.splice(index,1) } }, /*過濾器*/ filters:{ showPrice(price){ return '¥'+price.toFixed(2); } }, computed:{ totalPrice(){ let totalPrice=0; for(let i=0;i<this.books.length;i++){ totalPrice+=this.books[i].price*this.books[i].count; } return totalPrice; } }});
css代碼
table { border: 1px solid #e9e9e9; border-collapse: collapse; border-spacing: 0;}th,td { padding: 8px 16px; border: 1px solid #e9e9e9; text-align: left;}th { background-color: #f7f7f7; color: #5c6b77; font-weight: 600;}
for of直接取出數組的內容 i即表明數組中的每一項。 for(let i of this.books){ }
filter/map/reduce filter中的回調函數:必須返回一個boolean值 當返回true時,函數內部會自動將此次回調的n假如到新的數組中。若是爲false,函數內部就會過濾掉此次的n。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"></div><script> const app = new Vue({ el:"#app", data:{ message:"你好,夢陽辰!", isTrue:1 } }); const nums=[1,344,5,64,45,78]; /*filter函數的使用*/ let newNums = nums.filter(function (n) { return n < 100 }) console.log(newNums) /*map函數的使用,對原數組進行操做*/ let newNums2 = nums.map(function (n) { return n*2; }) alert(newNums2) /*reduce函數,對數組中全部的內容進行彙總*/ let newNums3 = nums.reduce(function (preValue,n) { return preValue+n; },0) alert(newNums3)</script></body></html>
簡潔的寫法(箭頭函數):
let total = nums.filter(n => n <100).map(n=>n*2).reduce((pre,n)=>pre+n);
If you find a path with no obstacles, it probably doesn’t lead anywhere.