前幾天咱們已經對後端的技術棧有了初步的瞭解、而且已經搭建了整個後端微服務的平臺。接下來要作的事情就是功能開發了。可是沒有前端頁面,咱們確定無從下手,所以今天咱們就要來了解一下前端的一些技術,完成前端頁面搭建。javascript
先聊一下前端開發模式的發展。php
靜態頁面html
最初的網頁以HTML爲主,是純靜態的網頁。網頁是隻讀的,信息流只能從服務端到客戶端單向流通。開發人員也只關心頁面的樣式和內容便可。前端
異步刷新,操做DOMvue
1995年,網景工程師Brendan Eich 花了10天時間設計了JavaScript語言.java
隨着JavaScript的誕生,咱們能夠操做頁面的DOM元素及樣式,頁面有了一些動態的效果,可是依然是以靜態爲主。node
ajax盛行:jquery
MVVM,關注模型和視圖ios
2008年,google的Chrome發佈,隨後就以極快的速度佔領市場,超過IE成爲瀏覽器市場的主導者。git
2009年,Ryan Dahl在谷歌的Chrome V8引擎基礎上,打造了基於事件循環的異步IO框架:Node.js。
node.js的偉大之處不在於讓JS邁向了後端開發,而是構建了一個龐大的生態系統。
2010年,NPM做爲node.js的包管理系統首次發佈,開發人員能夠遵循Common.js規範來編寫Node.js模塊,而後發佈到NPM上供其餘開發人員使用。目前已是世界最大的包模塊管理系統。
隨後,在node的基礎上,涌現出了一大批的前端框架:
MVVM模式
在MVVM以前,開發人員從後端獲取須要的數據模型,而後要經過DOM操做Model渲染到View中。然後當用戶操做視圖,咱們還須要經過DOM獲取View中的數據,而後同步到Model中。
而MVVM中的VM要作的事情就是把DOM操做徹底封裝起來,開發人員不用再關心Model和View之間是如何互相影響的:
把開發人員從繁瑣的DOM操做中解放出來,把關注點放在如何操做Model上。
而咱們今天要學習的,就是一款MVVM模式的框架:Vue
Vue (讀音 /vjuː/,相似於 view) 是一套用於構建用戶界面的漸進式框架。與其它大型框架不一樣的是,Vue 被設計爲能夠自底向上逐層應用。Vue 的核心庫只關注視圖層,不只易於上手,還便於與第三方庫或既有項目整合。另外一方面,當與現代化的工具鏈以及各類支持類庫結合使用時,Vue 也徹底可以爲複雜的單頁應用提供驅動。
前端框架三巨頭:Vue.js、React.js、AngularJS,vue.js以其輕量易用著稱,vue.js和React.js發展速度最快,AngularJS仍是老大。
複製代碼
Git地址:github.com/vuejs
尤雨溪,Vue.js 創做者,Vue Technology創始人,致力於Vue的研究開發。
前面說過,NPM是Node提供的模塊管理工具,能夠很是方便的下載安裝不少前端框架,包括Jquery、AngularJS、VueJs都有。爲了後面學習方便,咱們先安裝node及NPM工具。
下載地址:nodejs.org/en/
推薦下載LTS版本。
課程中採用的是8.11.3版本。也是目前最新的。你們自行下載或者使用課前資料中提供的安裝包。而後下一步安裝便可。
完成之後,在控制檯輸入:
node -v
複製代碼
看到版本信息:
Node自帶了NPM了,在控制檯輸入npm -v
查看:
npm默認的倉庫地址是在國外網站,速度較慢,建議你們設置到淘寶鏡像。可是切換鏡像是比較麻煩的。推薦一款切換鏡像的工具:nrm
咱們首先安裝nrm,這裏-g
表明全局安裝。可能須要一點兒時間
npm install nrm -g
複製代碼
而後經過nrm ls
命令查看npm的倉庫列表,帶*的就是當前選中的鏡像倉庫:
經過nrm use taobao
來指定要使用的鏡像源:
而後經過nrm test npm
來測試速度:
注意:
接下來,咱們快速領略下vue的魅力
建立一個新的空工程:
而後新建一個module:
選中static web,靜態web項目:
位置信息:
下載地址:github.com/vuejs/vue
能夠下載2.5.16版本https://github.com/vuejs/vue/archive/v2.5.16.zip
下載解壓,獲得vue.js文件。
或者也能夠直接使用公共的CDN服務:
<!-- 開發環境版本,包含了用幫助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
複製代碼
或者:
<!-- 生產環境版本,優化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
複製代碼
在idea的左下角,有個Terminal按鈕,點擊打開控制檯:
進入hello-vue目錄,先輸入:npm init -y
進行初始化
安裝Vue,輸入命令:npm install vue --save
而後就會在hello-vue目錄發現一個node_modules目錄,而且在下面有一個vue目錄。
node_modules是經過npm安裝的全部模塊的默認位置。
在hello-vue目錄新建一個HTML
在hello.html中,咱們編寫一段簡單的代碼:
h2中要輸出一句話:xx 很是帥。前面的xx是要渲染的數據。
而後咱們經過Vue進行渲染:
<body>
<div id="app">
<h2>{{name}},很是帥!!!</h2>
</div>
</body>
<script src="node_modules/vue/dist/vue.js" ></script>
<script> // 建立vue實例 var app = new Vue({ el:"#app", // el即element,該vue實例要渲染的頁面元素 data:{ // 渲染頁面須要的數據 name: "峯哥" } }); </script>
複製代碼
h2
元素中,咱們經過{{name}}的方式,來渲染剛剛定義的name屬性。打開頁面查看效果:
更神奇的在於,當你修改name屬性時,頁面會跟着變化:
咱們對剛纔的案例進行簡單修改:
<body>
<div id="app">
<input type="text" v-model="num">
<h2>
{{name}},很是帥!!!有{{num}}位女神爲他着迷。
</h2>
</div>
</body>
<script src="node_modules/vue/dist/vue.js" ></script>
<script> // 建立vue實例 var app = new Vue({ el: "#app", // el即element,該vue實例要渲染的頁面元素 data: { // 渲染頁面須要的數據 name: "峯哥", num: 5 } }); </script>
複製代碼
num
input
元素,經過v-model
與num
進行綁定。{{num}}
在頁面輸出效果:
咱們能夠觀察到,輸入框的變化引發了data中的num的變化,同時頁面輸出也跟着變化。
{{num}}
與數據num綁定,所以num值變化,引發了頁面效果變化。沒有任何dom操做,這就是雙向綁定的魅力。
咱們在頁面添加一個按鈕:
<button v-on:click="num++">點我</button>
複製代碼
v-on
指令綁定點擊事件,而不是普通的onclick
,而後直接操做num效果:
每一個 Vue 應用都是經過用 Vue
函數建立一個新的 Vue 實例開始的:
var vm = new Vue({
// 選項
})
複製代碼
在構造函數中傳入一個對象,而且在對象中聲明各類Vue須要的數據和方法,包括:
等等
接下來咱們一 一介紹。
每一個Vue實例都須要關聯一段Html模板,Vue會基於此模板進行視圖渲染。
咱們能夠經過el屬性來指定。
例如一段html模板:
<div id="app">
</div>
複製代碼
而後建立Vue實例,關聯這個div
var vm = new Vue({
el:"#app"
})
複製代碼
這樣,Vue就能夠基於id爲app
的div元素做爲模板進行渲染了。在這個div範圍之外的部分是沒法使用vue特性的。
當Vue實例被建立時,它會嘗試獲取在data中定義的全部屬性,用於視圖的渲染,而且監視data中的屬性變化,當data發生改變,全部相關的視圖都將從新渲染,這就是「響應式「系統。
html:
<div id="app">
<input type="text" v-model="name"/>
</div>
複製代碼
js:
var vm = new Vue({
el:"#app",
data:{
name:"劉德華"
}
})
複製代碼
input
的值Vue實例中除了能夠定義data屬性,也能夠定義方法,而且在Vue實例的做用範圍內使用。
html:
<div id="app">
{{num}}
<button v-on:click="add">加</button>
</div>
複製代碼
js:
var vm = new Vue({
el:"#app",
data:{
num: 0
},
methods:{
add:function(){
// this表明的當前vue實例
this.num++;
}
}
})
複製代碼
每一個 Vue 實例在被建立時都要通過一系列的初始化過程 :建立實例,裝載模板,渲染模板等等。Vue爲生命週期中的每一個狀態都設置了鉤子函數(監聽函數)。每當Vue實例處於不一樣的生命週期時,對應的函數就會被觸發調用。
生命週期:
beforeCreated:咱們在用Vue時都要進行實例化,所以,該函數就是在Vue實例化時調用,也能夠將他理解爲初始化函數比較方便一點,在Vue1.0時,這個函數的名字就是init。
created:在建立實例以後進行調用。
beforeMount:頁面加載完成,沒有渲染。如:此時頁面仍是{{name}}
mounted:咱們能夠將他理解爲原生js中的window.onload=function({.,.}),或許你們也在用jquery,因此也能夠理解爲jquery中的$(document).ready(function(){….}),他的功能就是:在dom文檔渲染完畢以後將要執行的函數,該函數在Vue1.0版本中名字爲compiled。 此時頁面中的{{name}}已被渲染成峯哥
beforeDestroy:該函數將在銷燬實例前進行調用 。
destroyed:改函數將在銷燬實例時進行調用。
beforeUpdate:組件更新以前。
updated:組件更新以後。
例如:created表明在vue實例建立後;
咱們能夠在Vue中定義一個created函數,表明這個時期的鉤子函數:
// 建立vue實例
var app = new Vue({
el: "#app", // el即element,該vue實例要渲染的頁面元素
data: { // 渲染頁面須要的數據
name: "峯哥",
num: 5
},
methods: {
add: function(){
this.num--;
}
},
created: function () {
this.num = 100;
}
});
複製代碼
結果:
咱們能夠看下在vue內部的this變量是誰,咱們在created的時候,打印this
methods: {
add: function(){
this.num--;
console.log(this);
}
},
複製代碼
控制檯的輸出:
什麼是指令?
指令 (Directives) 是帶有 v-
前綴的特殊特性。指令特性的預期值是:單個 JavaScript 表達式。指令的職責是,當表達式的值改變時,將其產生的連帶影響,響應式地做用於 DOM。
例如咱們在入門案例中的v-on,表明綁定事件。
格式:
{{表達式}}
複製代碼
說明:
示例:
HTML:
<div id="app">{{name}}</div>
複製代碼
JS:
var app = new Vue({
el:"#app",
data:{
name:"Jack"
}
})
複製代碼
使用{{}}方式在網速較慢時會出現問題。在數據未加載完成時,頁面會顯示出原始的{{}}
,加載完畢後才顯示正確數據,咱們稱爲插值閃爍。
咱們將網速調慢一些,而後試試看剛纔的案例:
刷新頁面:
使用v-text和v-html指令來替代{{}}
說明:
示例:
HTML:
<div id="app">
v-text:<span v-text="hello"></span> <br/>
v-html:<span v-html="hello"></span>
</div>
複製代碼
JS:
var vm = new Vue({
el:"#app",
data:{
hello: "<h1>你們好,我是峯哥</h1>"
}
})
複製代碼
效果:
而且不會出現插值閃爍,當沒有數據時,會顯示空白。
剛纔的v-text和v-html能夠看作是單向綁定,數據影響了視圖渲染,可是反過來就不行。接下來學習的v-model是雙向綁定,視圖(View)和模型(Model)之間會互相影響。
既然是雙向綁定,必定是在視圖中能夠修改數據,這樣就限定了視圖的元素類型。目前v-model的可以使用元素有:
基本上除了最後一項,其它都是表單的輸入項。
舉例:
html:
<div id="app">
<input type="checkbox" v-model="language" value="Java" />Java<br/>
<input type="checkbox" v-model="language" value="PHP" />PHP<br/>
<input type="checkbox" v-model="language" value="Swift" />Swift<br/>
<h1>
你選擇了:{{language.join(',')}}
</h1>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript"> var vm = new Vue({ el:"#app", data:{ language: [] } }) </script>
複製代碼
CheckBox
對應一個model時,model的類型是一個數組,單個checkbox值默認是boolean類型text
和textarea
默認對應的model是字符串select
單選對應字符串,多選對應也是數組效果:
v-on指令用於給頁面元素綁定事件。
語法:
v-on:事件名="js片斷或函數名"
複製代碼
示例:
<div id="app">
<!--事件中直接寫js片斷-->
<button v-on:click="num++">增長一個</button><br/>
<!--事件指定一個回調函數,必須是Vue實例中定義的函數-->
<button v-on:click="decrement">減小一個</button><br/>
<h1>有{{num}}個女神迷戀峯哥</h1>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript"> var app = new Vue({ el:"#app", data:{ num:100 }, methods:{ decrement(){ this.num--; } } }) </script>
複製代碼
效果:
另外,事件綁定能夠簡寫,例如v-on:click='add'
能夠簡寫爲@click='add'
在事件處理程序中調用 event.preventDefault()
或 event.stopPropagation()
是很是常見的需求。儘管咱們能夠在方法中輕鬆實現這點,但更好的方式是:方法只有純粹的數據邏輯,而不是去處理 DOM 事件細節。
爲了解決這個問題,Vue.js 爲 v-on
提供了事件修飾符。修飾符是由點開頭的指令後綴來表示的。
.stop
:阻止事件冒泡到父元素.prevent
:阻止默認事件發生*.capture
:使用事件捕獲模式.self
:只有元素自身觸發事件才執行。(冒泡或捕獲的都不執行).once
:只執行一次阻止默認事件
<div id="app">
<!--右擊事件,並阻止默認事件發生-->
<button v-on:contextmenu.prevent="num++">增長一個</button>
<br/>
<!--右擊事件,不阻止默認事件發生-->
<button v-on:contextmenu="decrement($event)">減小一個</button>
<br/>
<h1>有{{num}}個女神迷戀峯哥</h1>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript"> var app = new Vue({ el: "#app", data: { num: 100 }, methods: { decrement(ev) { // ev.preventDefault(); this.num--; } } }) </script>
複製代碼
效果:(右鍵「增長一個」,不會觸發默認的瀏覽器右擊事件;右鍵「減小一個」,會觸發默認的瀏覽器右擊事件)
在監聽鍵盤事件時,咱們常常須要檢查常見的鍵值。Vue 容許爲 v-on
在監聽鍵盤事件時添加按鍵修飾符:
<!-- 只有在 `keyCode` 是 13 時調用 `vm.submit()` -->
<input v-on:keyup.13="submit">
複製代碼
記住全部的 keyCode
比較困難,因此 Vue 爲最經常使用的按鍵提供了別名:
<!-- 同上 -->
<input v-on:keyup.enter="submit">
<!-- 縮寫語法 -->
<input @keyup.enter="submit">
複製代碼
所有的按鍵別名:
.enter
*.tab
.delete
(捕獲「刪除」和「退格」鍵).esc
.space
.up
.down
.left
.right
能夠用以下修飾符來實現僅在按下相應按鍵時才觸發鼠標或鍵盤事件的監聽器。
.ctrl
.alt
.shift
例如:
<!-- Alt + C -->
<input @keyup.alt.67="clear">
<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>
複製代碼
遍歷數據渲染頁面是很是經常使用的需求,Vue中經過v-for指令來實現。
語法:
v-for="item in items"
複製代碼
示例
<div id="app">
<ul>
<li v-for="user in users">
{{user.name}} - {{user.gender}} - {{user.age}}
</li>
</ul>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript"> var app = new Vue({ el: "#app", data: { users:[ {name:'柳巖', gender:'女', age: 21}, {name:'峯哥', gender:'男', age: 18}, {name:'范冰冰', gender:'女', age: 24}, {name:'劉亦菲', gender:'女', age: 18}, {name:'古力娜扎', gender:'女', age: 25} ] }, }) </script>
複製代碼
效果:
在遍歷的過程當中,若是咱們須要知道數組角標,能夠指定第二個參數:
語法
v-for="(item,index) in items"
複製代碼
示例
<ul>
<li v-for="(user, index) in users">
{{index + 1}}. {{user.name}} - {{user.gender}} - {{user.age}}
</li>
</ul>
複製代碼
效果:
v-for除了能夠迭代數組,也能夠迭代對象。語法基本相似
語法:
v-for="value in object"
v-for="(value,key) in object"
v-for="(value,key,index) in object"
複製代碼
示例:
<div id="app">
<ul>
<li v-for="(value, key, index) in user">
{{index + 1}}. {{key}} - {{value}}
</li>
</ul>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript"> var vm = new Vue({ el:"#app", data:{ user:{name:'峯哥', gender:'男', age: 18} } }) </script>
複製代碼
效果:
當 Vue.js 用 v-for
正在更新已渲染過的元素列表時,它默認用「就地複用」策略。若是數據項的順序被改變,Vue 將不會移動 DOM 元素來匹配數據項的順序, 而是簡單複用此處每一個元素,而且確保它在特定索引下顯示已被渲染過的每一個元素。
這個功能能夠有效的提升渲染的效率。
可是要實現這個功能,你須要給Vue一些提示,以便它能跟蹤每一個節點的身份,從而重用和從新排序現有元素,你須要爲每項提供一個惟一 key
屬性。理想的 key
值是每項都有的且惟一的 id。
示例:
<ul>
<li v-for="(item,index) in items" :key=index></li>
</ul>
複製代碼
:key=""
咱們後面會講到,它可讓你讀取vue中的屬性,並賦值給key屬性v-if,顧名思義,條件判斷。當獲得結果爲true時,所在的元素纔會被渲染。
語法:
v-if="布爾表達式"
複製代碼
示例:
<div id="app">
<button v-on:click="show = !show">點我呀</button>
<br>
<h1 v-if="show">
看到我啦?!
</h1>
<h1 v-show="show">
看到我啦?!show
</h1>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript"> var app = new Vue({ el: "#app", data: { show: true } }) </script>
複製代碼
效果:
當v-if和v-for出如今一塊兒時,v-for優先級更高。也就是說,會先遍歷,再判斷條件。
修改v-for中的案例,添加v-if:
<ul>
<li v-for="(user, index) in users" v-if="user.gender == '女'">
{{index + 1}}. {{user.name}} - {{user.gender}} - {{user.age}}
</li>
</ul>
複製代碼
效果:
只顯示女性用戶信息
你可使用 v-else
指令來表示 v-if
的「else 塊」:
<div id="app">
<h1 v-if="Math.random() > 0.5">
看到我啦?!if
</h1>
<h1 v-else>
看到我啦?!else
</h1>
</div>
複製代碼
v-else
元素必須緊跟在帶 v-if
或者 v-else-if
的元素的後面,不然它將不會被識別。
v-else-if
,顧名思義,充當 v-if
的「else-if 塊」,能夠連續使用:
<div id="app">
<button v-on:click="random=Math.random()">點我呀</button><span>{{random}}</span>
<h1 v-if="random >= 0.75">
看到我啦?!if
</h1>
<h1 v-else-if="random > 0.5">
看到我啦?!if 0.5
</h1>
<h1 v-else-if="random > 0.25">
看到我啦?!if 0.25
</h1>
<h1 v-else>
看到我啦?!else
</h1>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript"> var app = new Vue({ el: "#app", data: { random: 1 } }) </script>
複製代碼
相似於 v-else
,v-else-if
也必須緊跟在帶 v-if
或者 v-else-if
的元素以後。
演示:
另外一個用於根據條件展現元素的選項是 v-show
指令。用法大體同樣:
<h1 v-show="ok">Hello!</h1>
複製代碼
不一樣的是帶有 v-show
的元素始終會被渲染並保留在 DOM 中。v-show
只是簡單地切換元素的 CSS 屬性 display
。
示例:
<div id="app">
<!--事件中直接寫js片斷-->
<button v-on:click="show = !show">點擊切換</button><br/>
<h1 v-if="show">
你好
</h1>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript"> var app = new Vue({ el:"#app", data:{ show:true } }) </script>
複製代碼
代碼:
html屬性不能使用雙大括號形式綁定,只能使用v-bind指令。
在將 v-bind
用於 class
和 style
時,Vue.js 作了專門的加強。表達式結果的類型除了字符串以外,還能夠是對象或數組。
<div id="app">
<!--能夠是數據模型,能夠是具備返回值的js代碼塊或者函數-->
<div v-bind:title="title" style="border: 1px solid red; width: 50px; height: 50px;"></div>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript"> var app = new Vue({ el: "#app", data: { title: "title", } }) </script>
複製代碼
效果:
在將 v-bind
用於 class
和 style
時,Vue.js 作了專門的加強。表達式結果的類型除了字符串以外,還能夠是對象或數組。
數組語法
咱們能夠藉助於v-bind
指令來實現:
HTML:
<div id="app">
<div v-bind:class="activeClass"></div>
<div v-bind:class="errorClass"></div>
<div v-bind:class="[activeClass, errorClass]"></div>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript"> var app = new Vue({ el: "#app", data: { activeClass: 'active', errorClass: ['text-danger', 'text-error'] } }) </script>
複製代碼
渲染後的效果:(具備active和hasError的樣式)
對象語法
咱們能夠傳給 v-bind:class
一個對象,以動態地切換 class:
<div v-bind:class="{ active: isActive }"></div>
複製代碼
上面的語法表示 active
這個 class 存在與否將取決於數據屬性 isActive
的 truthiness(全部的值都是真實的,除了false,0,「」,null,undefined和NaN)。
你能夠在對象中傳入更多屬性來動態切換多個 class。此外,v-bind:class
指令也能夠與普通的 class 屬性共存。以下模板:
<div class="static" v-bind:class="{ active: isActive, 'text-danger': hasError }">
</div>
複製代碼
和以下 data:
data: {
isActive: true,
hasError: false
}
複製代碼
結果渲染爲:
<div class="static active"></div>
複製代碼
active樣式和text-danger樣式的存在與否,取決於isActive和hasError的值。本例中isActive爲true,hasError爲false,因此active樣式存在,text-danger不存在。
數組語法
數組語法能夠將多個樣式對象應用到同一個元素上:
<div v-bind:style="[baseStyles, overridingStyles]"></div>
複製代碼
數據:
data: {
baseStyles: {'background-color': 'red'},
overridingStyles: {border: '1px solid black'}
}
複製代碼
渲染後的結果:
<div style="background-color: red; border: 1px solid black;"></div>
複製代碼
對象語法
v-bind:style
的對象語法十分直觀——看着很是像 CSS,但實際上是一個 JavaScript 對象。CSS 屬性名能夠用駝峯式 (camelCase) 或短橫線分隔 (kebab-case,記得用單引號括起來) 來命名:
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
複製代碼
數據:
data: {
activeColor: 'red',
fontSize: 30
}
複製代碼
效果:
<div style="color: red; font-size: 30px;"></div>
複製代碼
v-bind:class
能夠簡寫爲:class
在插值表達式中使用js表達式是很是方便的,並且也常常被用到。
可是若是表達式的內容很長,就會顯得不夠優雅,並且後期維護起來也不方便,例以下面的場景,咱們有一個日期的數據,可是是毫秒值:
data:{
birthday:1529032123201 // 毫秒值
}
複製代碼
咱們在頁面渲染,但願獲得yyyy-MM-dd的樣式:
<h1>您的生日是:{{
new Date(birthday).getFullYear() + '-'+ new Date(birthday).getMonth()+ '-' + new Date(birthday).getDay()
}}
</h1>
複製代碼
雖然能獲得結果,可是很是麻煩。
Vue中提供了計算屬性,來替代複雜的表達式:
var vm = new Vue({
el:"#app",
data:{
birthday:1429032123201 // 毫秒值
},
computed:{
birth(){// 計算屬性本質是一個方法,可是必須返回結果
const d = new Date(this.birthday);
return d.getFullYear() + "-" + d.getMonth() + "-" + d.getDay();
}
}
})
複製代碼
頁面使用:
<div id="app">
<h1>您的生日是:{{birth}} </h1>
</div>
複製代碼
效果:
咱們能夠將同一函數定義爲一個方法而不是一個計算屬性。兩種方式的最終結果確實是徹底相同的。然而,不一樣的是計算屬性是基於它們的依賴進行緩存的。計算屬性只有在它的相關依賴發生改變時纔會從新求值。這就意味着只要birthday
尚未發生改變,屢次訪問 birthday
計算屬性會當即返回以前的計算結果,而沒必要再次執行函數。
watch可讓咱們監控一個值的變化。從而作出相應的反應。
示例:
<div id="app">
<input type="text" v-model="message">
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript"> var vm = new Vue({ el:"#app", data:{ message:"" }, watch:{ message(newVal, oldVal){ console.log(newVal, oldVal); } } }) </script>
複製代碼
效果:
在大型應用開發的時候,頁面能夠劃分紅不少部分。每每不一樣的頁面,也會有相同的部分。例如可能會有相同的頭部導航。
可是若是每一個頁面都獨自開發,這無疑增長了咱們開發的成本。因此咱們會把頁面的不一樣部分拆分紅獨立的組件,而後在不一樣頁面就能夠共享這些組件,避免重複開發。
在vue裏,全部的vue實例都是組件
咱們經過Vue的component方法來定義一個全局組件。
<div id="app">
<!--使用定義好的全局組件-->
<counter></counter>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript"> // 定義全局組件,兩個參數:1,組件名稱。2,組件參數 Vue.component("counter",{ template:'<button v-on:click="count++">你點了我 {{ count }} 次,我記住了.</button>', data(){ return { count:0 } } }) var app = new Vue({ el:"#app" }) </script>
複製代碼
效果:
定義好的組件,能夠任意複用屢次:
<div id="app">
<!--使用定義好的全局組件-->
<counter></counter>
<counter></counter>
<counter></counter>
</div>
複製代碼
效果:
你會發現每一個組件互不干擾,都有本身的count值。怎麼實現的?
組件的data屬性必須是函數!
當咱們定義這個 <counter>
組件時,它的data 並非像以前直接提供一個對象:
data: {
count: 0
}
複製代碼
取而代之的是,一個組件的 data 選項必須是一個函數,所以每一個實例能夠維護一份被返回對象的獨立的拷貝:
data: function () {
return {
count: 0
}
}
複製代碼
若是 Vue 沒有這條規則,點擊一個按鈕就會影響到其它全部實例!
一旦全局註冊,就意味着即使之後你再也不使用這個組件,它依然會隨着Vue的加載而加載。
所以,對於一些並不頻繁使用的組件,咱們會採用局部註冊。
咱們先在外部定義一個對象,結構與建立組件時傳遞的第二個參數一致:
const counter = {
template:'<button v-on:click="count++">你點了我 {{ count }} 次,我記住了.</button>',
data(){
return {
count:0
}
}
};
複製代碼
而後在Vue中使用它:
var app = new Vue({
el:"#app",
components:{
counter:counter // 將定義的對象註冊爲組件
}
})
複製代碼
一般一個單頁應用會以一棵嵌套的組件樹的形式來組織:
各個組件之間以嵌套的關係組合在一塊兒,那麼這個時候不可避免的會有組件間通訊的需求。
父組件使用子組件,並自定義了title屬性:
<div id="app">
<h1>打個招呼:</h1>
<!--使用子組件,同時傳遞title屬性-->
<introduce title="你們好,我是鋒哥"/>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript"> Vue.component("introduce",{ // 直接使用props接收到的屬性來渲染頁面 template:'<h1>{{title}}</h1>', props:['title'] // 經過props來接收一個父組件傳遞的屬性 }) var app = new Vue({ el:"#app" }) </script>
複製代碼
效果:
咱們定義一個子組件,並接收復雜數據:
const myList = {
template: '\ <ul>\ <li v-for="item in items" :key="item.id">{{item.id}} : {{item.name}}</li>\ </ul>\ ',
props: {
items: {
type: Array,
default: [],
required: true
}
}
};
複製代碼
當 prop 驗證失敗的時候,(開發環境構建版本的) Vue 將會產生一個控制檯的警告。
咱們在父組件中使用它:
<div id="app">
<h2>傳智播客已開設以下課程:</h2>
<!-- 使用子組件的同時,傳遞屬性,這裏使用了v-bind,指向了父組件本身的屬性lessons -->
<my-list :items="lessons"/>
</div>
複製代碼
var app = new Vue({
el:"#app",
components:{
myList // 當key和value同樣時,能夠只寫一個
},
data:{
lessons:[
{id:1, name: 'java'},
{id:2, name: 'php'},
{id:3, name: 'ios'},
]
}
})
複製代碼
效果:
type類型,能夠有:
注意:子組件模板有且只有一個根標籤
給 prop 傳入一個靜態的值:
<introduce title="你們好,我是鋒哥"/>
複製代碼
給 prop 傳入一個動態的值: (經過v-bind從數據模型中,獲取title的值)
<introduce :title="title"/>
複製代碼
靜態傳遞時,咱們傳入的值都是字符串類型的,但實際上任何類型的值均可以傳給一個 props。
<!-- 即使 `42` 是靜態的,咱們仍然須要 `v-bind` 來告訴 Vue -->
<!-- 這是一個JavaScript表達式而不是一個字符串。-->
<blog-post v-bind:likes="42"></blog-post>
<!-- 用一個變量進行動態賦值。-->
<blog-post v-bind:likes="post.likes"></blog-post>
複製代碼
來看這樣的一個案例:
<div id="app">
<h2>num: {{num}}</h2>
<!--使用子組件的時候,傳遞num到子組件中-->
<counter :num="num"></counter>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript"> Vue.component("counter", {// 子組件,定義了兩個按鈕,點擊數字num會加或減 template:'\ <div>\ <button @click="num++">加</button> \ <button @click="num--">減</button> \ </div>', props:['num']// count是從父組件獲取的。 }) var app = new Vue({ el:"#app", data:{ num:0 } }) </script>
複製代碼
咱們嘗試運行,好像沒問題,點擊按鈕試試:
子組件接收到父組件屬性後,默認是不容許修改的。怎麼辦?
既然只有父組件能修改,那麼加和減的操做必定是放在父組件:
var app = new Vue({
el:"#app",
data:{
num:0
},
methods:{ // 父組件中定義操做num的方法
increment(){
this.num++;
},
decrement(){
this.num--;
}
}
})
複製代碼
可是,點擊按鈕是在子組件中,那就是說須要子組件來調用父組件的函數,怎麼作?
咱們能夠經過v-on指令將父組件的函數綁定到子組件上:
<div id="app">
<h2>num: {{num}}</h2>
<counter :count="num" @inc="increment" @dec="decrement"></counter>
</div>
複製代碼
在子組件中定義函數,函數的具體實現調用父組件的實現,並在子組件中調用這些函數。當子組件中按鈕被點擊時,調用綁定的函數:
Vue.component("counter", {
template:'\ <div>\ <button @click="plus">加</button> \ <button @click="reduce">減</button> \ </div>',
props:['count'],
methods:{
plus(){
this.$emit("inc");
},
reduce(){
this.$emit("dec");
}
}
})
複製代碼
效果:
如今咱們來實現這樣一個功能:
一個頁面,包含登陸和註冊,點擊不一樣按鈕,實現登陸和註冊頁切換:
爲了讓接下來的功能比較清晰,咱們先新建一個文件夾:src
而後新建一個HTML文件,做爲入口:index.html
而後編寫頁面的基本結構:
<div id="app">
<span>登陸</span>
<span>註冊</span>
<hr/>
<div>
登陸頁/註冊頁
</div>
</div>
<script src="../node_modules/vue/dist/vue.js"></script>
<script type="text/javascript"> var vm = new Vue({ el:"#app" }) </script>
複製代碼
樣式:
接下來咱們來實現登陸組件,之前咱們都是寫在一個文件中,可是爲了複用性,開發中都會把組件放入獨立的JS文件中,咱們新建一個user目錄以及login.js及register.js:
編寫組件,這裏咱們只寫模板,不寫功能。
login.js內容以下:
const loginForm = {
template:'\ <div>\ <h2>登陸頁</h2> \ 用戶名:<input type="text"><br/>\ 密碼:<input type="password"><br/>\ </div>\ '
}
複製代碼
register.js內容:
const registerForm = {
template:'\ <div>\ <h2>註冊頁</h2> \ 用 戶 名:<input type="text"><br/>\ 密  碼:<input type="password"><br/>\ 確認密碼:<input type="password"><br/>\ </div>\ '
}
複製代碼
<div id="app">
<span>登陸</span>
<span>註冊</span>
<hr/>
<div>
<!--<loginForm></loginForm>-->
<!-- 疑問:爲何不採用上面的寫法? 因爲html是大小寫不敏感的,若是採用上面的寫法,則被認爲是<loginform></loginform> 因此,若是是駝峯形式的組件,須要把駝峯轉化爲「-」的形式 -->
<login-form></login-form>
<register-form></register-form>
</div>
</div>
<script src="../node_modules/vue/dist/vue.js"></script>
<script src="user/login.js"></script>
<script src="user/register.js"></script>
<script type="text/javascript"> var vm = new Vue({ el: "#app", components: { loginForm, registerForm } }) </script>
複製代碼
效果:
咱們期待的是,當點擊登陸或註冊按鈕,分別顯示登陸頁或註冊頁,而不是一塊兒顯示。
可是,如何才能動態加載組件,實現組件切換呢?
雖然使用原生的Html5和JS也能實現,可是官方推薦咱們使用vue-router模塊。
使用vue-router和vue能夠很是方便的實現 複雜單頁應用的動態路由功能。
使用npm安裝:npm install vue-router --save
在index.html中引入依賴:
<script src="../node_modules/vue-router/dist/vue-router.js"></script>
複製代碼
新建vue-router對象,而且指定路由規則:
// 建立VueRouter對象
const router = new VueRouter({
routes:[ // 編寫路由規則
{
path:"/login", // 請求路徑,以「/」開頭
component:loginForm // 組件名稱
},
{
path:"/register",
component:registerForm
}
]
})
複製代碼
在父組件中引入router對象:
var vm = new Vue({
el:"#app",
components:{// 引用登陸和註冊組件
loginForm,
registerForm
},
router // 引用上面定義的router對象
})
複製代碼
頁面跳轉控制:
<div id="app">
<!--router-link來指定跳轉的路徑-->
<span><router-link to="/login">登陸</router-link></span>
<span><router-link to="/register">註冊</router-link></span>
<hr/>
<div>
<!--vue-router的錨點-->
<router-view></router-view>
</div>
</div>
複製代碼
<router-view>
來指定一個錨點,當路由的路徑匹配時,vue-router會自動把對應組件放到錨點位置進行渲染<router-link>
指定一個跳轉連接,當點擊時,會觸發vue-router的路由功能,路徑中的hash值會隨之改變效果:
注意:單頁應用中,頁面的切換並非頁面的跳轉。僅僅是地址最後的hash值變化。
事實上,咱們總共就一個HTML:index.html
請訪問: juntech.top