### 什么是Vue.js
+ Vue.js 是目前最火的一個(gè)前端框架,React是最流行的一個(gè)前端框架(React除了開發(fā)網(wǎng)站隙袁,還可以開發(fā)手機(jī)App忆肾, Vue語法也是可以用于進(jìn)行手機(jī)App開發(fā)的宴咧,需要借助于Weex)
+ Vue.js 是前端的**主流框架之一**荒椭,和Angular.js、React.js 一起,并成為前端三大主流框架!
+ Vue.js 是一套構(gòu)建用戶界面的框架漩蟆,**只關(guān)注視圖層**,它不僅易于上手妓蛮,還便于與第三方庫或既有項(xiàng)目整合怠李。(Vue有配套的第三方類庫,可以整合起來做大型項(xiàng)目的開發(fā))
+ 前端的主要工作蛤克?主要負(fù)責(zé)MVC中的V這一層捺癞;主要工作就是和界面打交道,來制作前端頁面效果构挤;
## 為什么要學(xué)習(xí)流行框架
+ 企業(yè)為了提高開發(fā)效率:在企業(yè)中髓介,時(shí)間就是效率,效率就是金錢筋现;
? - 企業(yè)中唐础,使用框架,能夠提高開發(fā)的效率矾飞;
+ 提高開發(fā)效率的發(fā)展歷程:原生JS -> Jquery之類的類庫 -> 前端模板引擎 -> Angular.js / Vue.js(能夠幫助我們減少不必要的DOM操作彻犁;提高渲染效率;雙向數(shù)據(jù)綁定的概念【通過框架提供的指令凰慈,我們前端程序員只需要關(guān)心數(shù)據(jù)的業(yè)務(wù)邏輯,不再關(guān)心DOM是如何渲染的了】)
+ 在Vue中驼鹅,一個(gè)核心的概念微谓,就是讓用戶不再操作DOM元素森篷,解放了用戶的雙手,讓程序員可以更多的時(shí)間去關(guān)注業(yè)務(wù)邏輯豺型;
+ 增強(qiáng)自己就業(yè)時(shí)候的競爭力
? - 人無我有仲智,人有我優(yōu)
? - 你平時(shí)不忙的時(shí)候,都在干嘛姻氨?
## 框架和庫的區(qū)別
+ 框架:是一套完整的解決方案钓辆;對項(xiàng)目的侵入性較大,項(xiàng)目如果需要更換框架肴焊,則需要重新架構(gòu)整個(gè)項(xiàng)目前联。
? - node 中的 express;
+ 庫(插件):提供某一個(gè)小功能娶眷,對項(xiàng)目的侵入性較小似嗤,如果某個(gè)庫無法完成某些需求,可以很容易切換到其它庫實(shí)現(xiàn)需求届宠。
? - 1. 從Jquery 切換到 Zepto
? - 2. 從 EJS 切換到 art-template
## Node(后端)中的 MVC 與 前端中的 MVVM 之間的區(qū)別
+ MVC 是后端的分層開發(fā)概念烁落;
+ MVVM是前端視圖層的概念,主要關(guān)注于 視圖層分離豌注,也就是說:MVVM把前端的視圖層伤塌,分為了 三部分 Model, View , VM ViewModel
+ 為什么有了MVC還要有MVVM
## Vue.js 基本代碼 和 MVVM 之間的對應(yīng)關(guān)系
## Vue之 - `基本的代碼結(jié)構(gòu)`和`插值表達(dá)式`、`v-cloak`
## Vue指令之`v-text`和`v-html`
## Vue指令之`v-bind`的三種用法
1. 直接使用指令`v-bind`
2. 使用簡化指令`:`
3. 在綁定的時(shí)候轧铁,拼接綁定內(nèi)容:`:title="btnTitle + ', 這是追加的內(nèi)容'"`
## Vue指令之`v-on`和`跑馬燈效果`
### 跑馬燈效果
1. HTML結(jié)構(gòu):
```
<div id="app">
? ? <p>{{info}}</p>
? ? <input type="button" value="開啟" v-on:click="go">
? ? <input type="button" value="停止" v-on:click="stop">
? </div>
```
2. Vue實(shí)例:
```
// 創(chuàng)建 Vue 實(shí)例每聪,得到 ViewModel
? ? var vm = new Vue({
? ? ? el: '#app',
? ? ? data: {
? ? ? ? info: '猥瑣發(fā)育,別浪~属桦!',
? ? ? ? intervalId: null
? ? ? },
? ? ? methods: {
? ? ? ? go() {
? ? ? ? ? // 如果當(dāng)前有定時(shí)器在運(yùn)行熊痴,則直接return
? ? ? ? ? if (this.intervalId != null) {
? ? ? ? ? ? return;
? ? ? ? ? }
? ? ? ? ? // 開始定時(shí)器
? ? ? ? ? this.intervalId = setInterval(() => {
? ? ? ? ? ? this.info = this.info.substring(1) + this.info.substring(0, 1);
? ? ? ? ? }, 500);
? ? ? ? },
? ? ? ? stop() {
? ? ? ? ? clearInterval(this.intervalId);
? ? ? ? }
? ? ? }
? ? });
```
## Vue指令之`v-on的縮寫`和`事件修飾符`
### 事件修飾符:
+ .stop? ? ? 阻止冒泡
+ .prevent? ? 阻止默認(rèn)事件
+ .capture? ? 添加事件偵聽器時(shí)使用事件捕獲模式
+ .self? ? ? 只當(dāng)事件在該元素本身(比如不是子元素)觸發(fā)時(shí)觸發(fā)回調(diào)
+ .once? ? ? 事件只觸發(fā)一次
## Vue指令之`v-model`和`雙向數(shù)據(jù)綁定`
## 簡易計(jì)算器案例
1. HTML 代碼結(jié)構(gòu)
```
? <div id="app">
? ? <input type="text" v-model="n1">
? ? <select v-model="opt">
? ? ? <option value="0">+</option>
? ? ? <option value="1">-</option>
? ? ? <option value="2">*</option>
? ? ? <option value="3">÷</option>
? ? </select>
? ? <input type="text" v-model="n2">
? ? <input type="button" value="=" v-on:click="getResult">
? ? <input type="text" v-model="result">
? </div>
```
2. Vue實(shí)例代碼:
```
// 創(chuàng)建 Vue 實(shí)例,得到 ViewModel
? ? var vm = new Vue({
? ? ? el: '#app',
? ? ? data: {
? ? ? ? n1: 0,
? ? ? ? n2: 0,
? ? ? ? result: 0,
? ? ? ? opt: '0'
? ? ? },
? ? ? methods: {
? ? ? ? getResult() {
? ? ? ? ? switch (this.opt) {
? ? ? ? ? ? case '0':
? ? ? ? ? ? ? this.result = parseInt(this.n1) + parseInt(this.n2);
? ? ? ? ? ? ? break;
? ? ? ? ? ? case '1':
? ? ? ? ? ? ? this.result = parseInt(this.n1) - parseInt(this.n2);
? ? ? ? ? ? ? break;
? ? ? ? ? ? case '2':
? ? ? ? ? ? ? this.result = parseInt(this.n1) * parseInt(this.n2);
? ? ? ? ? ? ? break;
? ? ? ? ? ? case '3':
? ? ? ? ? ? ? this.result = parseInt(this.n1) / parseInt(this.n2);
? ? ? ? ? ? ? break;
? ? ? ? ? }
? ? ? ? }
? ? ? }
? ? });
```
## 在Vue中使用樣式
### 使用class樣式
1. 數(shù)組
```
<h1 :class="['red', 'thin']">這是一個(gè)邪惡的H1</h1>
```
2. 數(shù)組中使用三元表達(dá)式
```
<h1 :class="['red', 'thin', isactive?'active':'']">這是一個(gè)邪惡的H1</h1>
```
3. 數(shù)組中嵌套對象
```
<h1 :class="['red', 'thin', {'active': isactive}]">這是一個(gè)邪惡的H1</h1>
```
4. 直接使用對象
```
<h1 :class="{red:true, italic:true, active:true, thin:true}">這是一個(gè)邪惡的H1</h1>
```
### 使用內(nèi)聯(lián)樣式
1. 直接在元素上通過 `:style` 的形式聂宾,書寫樣式對象
```
<h1 :style="{color: 'red', 'font-size': '40px'}">這是一個(gè)善良的H1</h1>
```
2. 將樣式對象果善,定義到 `data` 中,并直接引用到 `:style` 中
+ 在data上定義樣式:
```
data: {
? ? ? ? h1StyleObj: { color: 'red', 'font-size': '40px', 'font-weight': '200' }
}
```
+ 在元素中系谐,通過屬性綁定的形式巾陕,將樣式對象應(yīng)用到元素中:
```
<h1 :style="h1StyleObj">這是一個(gè)善良的H1</h1>
```
3. 在 `:style` 中通過數(shù)組,引用多個(gè) `data` 上的樣式對象
+ 在data上定義樣式:
```
data: {
? ? ? ? h1StyleObj: { color: 'red', 'font-size': '40px', 'font-weight': '200' },
? ? ? ? h1StyleObj2: { fontStyle: 'italic' }
}
```
+ 在元素中纪他,通過屬性綁定的形式鄙煤,將樣式對象應(yīng)用到元素中:
```
<h1 :style="[h1StyleObj, h1StyleObj2]">這是一個(gè)善良的H1</h1>
```
## Vue指令之`v-for`和`key`屬性
1. 迭代數(shù)組
```
<ul>
? <li v-for="(item, i) in list">索引:{{i}} --- 姓名:{{item.name}} --- 年齡:{{item.age}}</li>
</ul>
```
2. 迭代對象中的屬性
```
<!-- 循環(huán)遍歷對象身上的屬性 -->
? ? <div v-for="(val, key, i) in userInfo">{{val}} --- {{key}} --- {{i}}</div>
```
3. 迭代數(shù)字
```
<p v-for="i in 10">這是第 {{i}} 個(gè)P標(biāo)簽</p>
```
> 2.2.0+ 的版本里,**當(dāng)在組件中使用** v-for 時(shí)茶袒,key 現(xiàn)在是必須的梯刚。
當(dāng) Vue.js 用 v-for 正在更新已渲染過的元素列表時(shí),它默認(rèn)用 “**就地復(fù)用**” 策略薪寓。如果數(shù)據(jù)項(xiàng)的順序被改變亡资,Vue將**不是移動(dòng) DOM 元素來匹配數(shù)據(jù)項(xiàng)的順序**澜共, 而是**簡單復(fù)用此處每個(gè)元素**,并且確保它在特定索引下顯示已被渲染過的每個(gè)元素锥腻。
為了給 Vue 一個(gè)提示嗦董,**以便它能跟蹤每個(gè)節(jié)點(diǎn)的身份,從而重用和重新排序現(xiàn)有元素**瘦黑,你需要為每項(xiàng)提供一個(gè)唯一 key 屬性京革。
## Vue指令之`v-if`和`v-show`
> 一般來說,v-if 有更高的切換消耗而 v-show 有更高的初始渲染消耗幸斥。因此匹摇,如果需要頻繁切換 v-show 較好,如果在運(yùn)行時(shí)條件不大可能改變 v-if 較好睡毒。
## 品牌管理案例
### 添加新品牌
### 刪除品牌
### 根據(jù)條件篩選品牌
1. 1.x 版本中的filterBy指令来惧,在2.x中已經(jīng)被廢除:
[filterBy - 指令](https://v1-cn.vuejs.org/api/#filterBy)
```
<tr v-for="item in list | filterBy searchName in 'name'">
? <td>{{item.id}}</td>
? <td>{{item.name}}</td>
? <td>{{item.ctime}}</td>
? <td>
? ? <a href="#" @click.prevent="del(item.id)">刪除</a>
? </td>
</tr>
```
2. 在2.x版本中[手動(dòng)實(shí)現(xiàn)篩選的方式](https://cn.vuejs.org/v2/guide/list.html#顯示過濾-排序結(jié)果):
+ 篩選框綁定到 VM 實(shí)例中的 `searchName` 屬性:
```
<hr> 輸入篩選名稱:
<input type="text" v-model="searchName">
```
+ 在使用 `v-for` 指令循環(huán)每一行數(shù)據(jù)的時(shí)候,不再直接 `item in list`演顾,而是 `in` 一個(gè) 過濾的methods 方法供搀,同時(shí),把過濾條件`searchName`傳遞進(jìn)去:
```
<tbody>
? ? ? <tr v-for="item in search(searchName)">
? ? ? ? <td>{{item.id}}</td>
? ? ? ? <td>{{item.name}}</td>
? ? ? ? <td>{{item.ctime}}</td>
? ? ? ? <td>
? ? ? ? ? <a href="#" @click.prevent="del(item.id)">刪除</a>
? ? ? ? </td>
? ? ? </tr>
? ? </tbody>
```
+ `search` 過濾方法中钠至,使用 數(shù)組的 `filter` 方法進(jìn)行過濾:
```
search(name) {
? return this.list.filter(x => {
? ? return x.name.indexOf(name) != -1;
? });
}
```
## Vue調(diào)試工具`vue-devtools`的安裝步驟和使用
[Vue.js devtools - 翻墻安裝方式 - 推薦](https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd?hl=zh-CN)
## 過濾器
概念:Vue.js 允許你自定義過濾器葛虐,**可被用作一些常見的文本格式化**。過濾器可以用在兩個(gè)地方:**mustache 插值和 v-bind 表達(dá)式**棉钧。過濾器應(yīng)該被添加在 JavaScript 表達(dá)式的尾部屿脐,由“管道”符指示;
### 私有過濾器
1. HTML元素:
```
<td>{{item.ctime | dataFormat('yyyy-mm-dd')}}</td>
```
2. 私有 `filters` 定義方式:
```
filters: { // 私有局部過濾器宪卿,只能在 當(dāng)前 VM 對象所控制的 View 區(qū)域進(jìn)行使用
? ? dataFormat(input, pattern = "") { // 在參數(shù)列表中 通過 pattern="" 來指定形參默認(rèn)值的诵,防止報(bào)錯(cuò)
? ? ? var dt = new Date(input);
? ? ? // 獲取年月日
? ? ? var y = dt.getFullYear();
? ? ? var m = (dt.getMonth() + 1).toString().padStart(2, '0');
? ? ? var d = dt.getDate().toString().padStart(2, '0');
? ? ? // 如果 傳遞進(jìn)來的字符串類型,轉(zhuǎn)為小寫之后佑钾,等于 yyyy-mm-dd西疤,那么就返回 年-月-日
? ? ? // 否則,就返回? 年-月-日 時(shí):分:秒
? ? ? if (pattern.toLowerCase() === 'yyyy-mm-dd') {
? ? ? ? return `${y}-${m}-$eci46ys`;
? ? ? } else {
? ? ? ? // 獲取時(shí)分秒
? ? ? ? var hh = dt.getHours().toString().padStart(2, '0');
? ? ? ? var mm = dt.getMinutes().toString().padStart(2, '0');
? ? ? ? var ss = dt.getSeconds().toString().padStart(2, '0');
? ? ? ? return `${y}-${m}-$6swo6og ${hh}:${mm}:${ss}`;
? ? ? }
? ? }
? }
```
> 使用ES6中的字符串新方法 String.prototype.padStart(maxLength, fillString='') 或 String.prototype.padEnd(maxLength, fillString='')來填充字符串休溶;
### 全局過濾器
```
// 定義一個(gè)全局過濾器
Vue.filter('dataFormat', function (input, pattern = '') {
? var dt = new Date(input);
? // 獲取年月日
? var y = dt.getFullYear();
? var m = (dt.getMonth() + 1).toString().padStart(2, '0');
? var d = dt.getDate().toString().padStart(2, '0');
? // 如果 傳遞進(jìn)來的字符串類型代赁,轉(zhuǎn)為小寫之后,等于 yyyy-mm-dd兽掰,那么就返回 年-月-日
? // 否則芭碍,就返回? 年-月-日 時(shí):分:秒
? if (pattern.toLowerCase() === 'yyyy-mm-dd') {
? ? return `${y}-${m}-$6u6uk0a`;
? } else {
? ? // 獲取時(shí)分秒
? ? var hh = dt.getHours().toString().padStart(2, '0');
? ? var mm = dt.getMinutes().toString().padStart(2, '0');
? ? var ss = dt.getSeconds().toString().padStart(2, '0');
? ? return `${y}-${m}-$mayy4ao ${hh}:${mm}:${ss}`;
? }
});
```
> 注意:當(dāng)有局部和全局兩個(gè)名稱相同的過濾器時(shí)候,會(huì)以就近原則進(jìn)行調(diào)用孽尽,即:局部過濾器優(yōu)先于全局過濾器被調(diào)用窖壕!
## 鍵盤修飾符以及自定義鍵盤修飾符
### 1.x中自定義鍵盤修飾符【了解即可】
```
Vue.directive('on').keyCodes.f2 = 113;
```
### [2.x中自定義鍵盤修飾符](https://cn.vuejs.org/v2/guide/events.html#鍵值修飾符)
1. 通過`Vue.config.keyCodes.名稱 = 按鍵值`來自定義案件修飾符的別名:
```
Vue.config.keyCodes.f2 = 113;
```
2. 使用自定義的按鍵修飾符:
```
<input type="text" v-model="name" @keyup.f2="add">
```
## [自定義指令](https://cn.vuejs.org/v2/guide/custom-directive.html)
1. 自定義全局和局部的 自定義指令:
```
? ? // 自定義全局指令 v-focus,為綁定的元素自動(dòng)獲取焦點(diǎn):
? ? Vue.directive('focus', {
? ? ? inserted: function (el) { // inserted 表示被綁定元素插入父節(jié)點(diǎn)時(shí)調(diào)用
? ? ? ? el.focus();
? ? ? }
? ? });
? ? // 自定義局部指令 v-color 和 v-font-weight,為綁定的元素設(shè)置指定的字體顏色 和 字體粗細(xì):
? ? ? directives: {
? ? ? ? color: { // 為元素設(shè)置指定的字體顏色
? ? ? ? ? bind(el, binding) {
? ? ? ? ? ? el.style.color = binding.value;
? ? ? ? ? }
? ? ? ? },
? ? ? ? 'font-weight': function (el, binding2) { // 自定義指令的簡寫形式艇拍,等同于定義了 bind 和 update 兩個(gè)鉤子函數(shù)
? ? ? ? ? el.style.fontWeight = binding2.value;
? ? ? ? }
? ? ? }
```
2. 自定義指令的使用方式:
```
<input type="text" v-model="searchName" v-focus v-color="'red'" v-font-weight="900">
```
## Vue 1.x 中 自定義元素指令【已廢棄,了解即可】
```
Vue.elementDirective('red-color', {
? bind: function () {
? ? this.el.style.color = 'red';
? }
});
```
使用方式:
```
<red-color>1232</red-color>
```
## [vue實(shí)例的生命周期](https://cn.vuejs.org/v2/guide/instance.html#實(shí)例生命周期)
+ 什么是生命周期:從Vue實(shí)例創(chuàng)建狐蜕、運(yùn)行、到銷毀期間卸夕,總是伴隨著各種各樣的事件,這些事件婆瓜,統(tǒng)稱為生命周期快集!
+ [生命周期鉤子](https://cn.vuejs.org/v2/api/#選項(xiàng)-生命周期鉤子):就是生命周期事件的別名而已;
+ 生命周期鉤子 = 生命周期函數(shù) = 生命周期事件
+ 主要的生命周期函數(shù)分類:
- 創(chuàng)建期間的生命周期函數(shù):
? + beforeCreate:實(shí)例剛在內(nèi)存中被創(chuàng)建出來廉白,此時(shí)个初,還沒有初始化好 data 和 methods 屬性
? + created:實(shí)例已經(jīng)在內(nèi)存中創(chuàng)建OK,此時(shí) data 和 methods 已經(jīng)創(chuàng)建OK猴蹂,此時(shí)還沒有開始 編譯模板
? + beforeMount:此時(shí)已經(jīng)完成了模板的編譯院溺,但是還沒有掛載到頁面中
? + mounted:此時(shí),已經(jīng)將編譯好的模板磅轻,掛載到了頁面指定的容器中顯示
- 運(yùn)行期間的生命周期函數(shù):
+ beforeUpdate:狀態(tài)更新之前執(zhí)行此函數(shù)珍逸, 此時(shí) data 中的狀態(tài)值是最新的,但是界面上顯示的 數(shù)據(jù)還是舊的聋溜,因?yàn)榇藭r(shí)還沒有開始重新渲染DOM節(jié)點(diǎn)
+ updated:實(shí)例更新完畢之后調(diào)用此函數(shù)谆膳,此時(shí) data 中的狀態(tài)值 和 界面上顯示的數(shù)據(jù),都已經(jīng)完成了更新撮躁,界面已經(jīng)被重新渲染好了漱病!
- 銷毀期間的生命周期函數(shù):
+ beforeDestroy:實(shí)例銷毀之前調(diào)用。在這一步把曼,實(shí)例仍然完全可用杨帽。
+ destroyed:Vue 實(shí)例銷毀后調(diào)用。調(diào)用后嗤军,Vue 實(shí)例指示的所有東西都會(huì)解綁定注盈,所有的事件監(jiān)聽器會(huì)被移除,所有的子實(shí)例也會(huì)被銷毀型雳。
## [vue-resource 實(shí)現(xiàn) get, post, jsonp請求](https://github.com/pagekit/vue-resource)
除了 vue-resource 之外当凡,還可以使用 `axios` 的第三方包實(shí)現(xiàn)實(shí)現(xiàn)數(shù)據(jù)的請求
1. 之前的學(xué)習(xí)中,如何發(fā)起數(shù)據(jù)請求纠俭?
2. 常見的數(shù)據(jù)請求類型沿量?? get? post jsonp
3. 測試的URL請求資源地址:
+ get請求地址: http://vue.studyit.io/api/getlunbo
+ post請求地址:http://vue.studyit.io/api/post
+ jsonp請求地址:http://vue.studyit.io/api/jsonp
4. JSONP的實(shí)現(xiàn)原理
+ 由于瀏覽器的安全性限制,不允許AJAX訪問 協(xié)議不同冤荆、域名不同朴则、端口號(hào)不同的 數(shù)據(jù)接口,瀏覽器認(rèn)為這種訪問不安全钓简;
+ 可以通過動(dòng)態(tài)創(chuàng)建script標(biāo)簽的形式乌妒,把script標(biāo)簽的src屬性汹想,指向數(shù)據(jù)接口的地址,因?yàn)閟cript標(biāo)簽不存在跨域限制撤蚊,這種數(shù)據(jù)獲取方式古掏,稱作JSONP(注意:根據(jù)JSONP的實(shí)現(xiàn)原理,知曉侦啸,JSONP只支持Get請求)槽唾;
+ 具體實(shí)現(xiàn)過程:
- 先在客戶端定義一個(gè)回調(diào)方法,預(yù)定義對數(shù)據(jù)的操作光涂;
- 再把這個(gè)回調(diào)方法的名稱庞萍,通過URL傳參的形式,提交到服務(wù)器的數(shù)據(jù)接口忘闻;
- 服務(wù)器數(shù)據(jù)接口組織好要發(fā)送給客戶端的數(shù)據(jù)钝计,再拿著客戶端傳遞過來的回調(diào)方法名稱,拼接出一個(gè)調(diào)用這個(gè)方法的字符串齐佳,發(fā)送給客戶端去解析執(zhí)行私恬;
- 客戶端拿到服務(wù)器返回的字符串之后,當(dāng)作Script腳本去解析執(zhí)行重虑,這樣就能夠拿到JSONP的數(shù)據(jù)了践付;
+ 帶大家通過 Node.js ,來手動(dòng)實(shí)現(xiàn)一個(gè)JSONP的請求例子缺厉;
```
? ? const http = require('http');
? ? // 導(dǎo)入解析 URL 地址的核心模塊
? ? const urlModule = require('url');
? ? const server = http.createServer();
? ? // 監(jiān)聽 服務(wù)器的 request 請求事件永高,處理每個(gè)請求
? ? server.on('request', (req, res) => {
? ? ? const url = req.url;
? ? ? // 解析客戶端請求的URL地址
? ? ? var info = urlModule.parse(url, true);
? ? ? // 如果請求的 URL 地址是 /getjsonp ,則表示要獲取JSONP類型的數(shù)據(jù)
? ? ? if (info.pathname === '/getjsonp') {
? ? ? ? // 獲取客戶端指定的回調(diào)函數(shù)的名稱
? ? ? ? var cbName = info.query.callback;
? ? ? ? // 手動(dòng)拼接要返回給客戶端的數(shù)據(jù)對象
? ? ? ? var data = {
? ? ? ? ? name: 'zs',
? ? ? ? ? age: 22,
? ? ? ? ? gender: '男',
? ? ? ? ? hobby: ['吃飯', '睡覺', '運(yùn)動(dòng)']
? ? ? ? }
? ? ? ? // 拼接出一個(gè)方法的調(diào)用提针,在調(diào)用這個(gè)方法的時(shí)候命爬,把要發(fā)送給客戶端的數(shù)據(jù),序列化為字符串辐脖,作為參數(shù)傳遞給這個(gè)調(diào)用的方法:
? ? ? ? var result = `${cbName}(${JSON.stringify(data)})`;
? ? ? ? // 將拼接好的方法的調(diào)用饲宛,返回給客戶端去解析執(zhí)行
? ? ? ? res.end(result);
? ? ? } else {
? ? ? ? res.end('404');
? ? ? }
? ? });
? ? server.listen(3000, () => {
? ? ? console.log('server running at http://127.0.0.1:3000');
? ? });
```
5. vue-resource 的配置步驟:
+ 直接在頁面中,通過`script`標(biāo)簽嗜价,引入 `vue-resource` 的腳本文件艇抠;
+ 注意:引用的先后順序是:先引用 `Vue` 的腳本文件,再引用 `vue-resource` 的腳本文件久锥;
6. 發(fā)送get請求:
```
getInfo() { // get 方式獲取數(shù)據(jù)
? this.$http.get('http://127.0.0.1:8899/api/getlunbo').then(res => {
? ? console.log(res.body);
? })
}
```
7. 發(fā)送post請求:
```
postInfo() {
? var url = 'http://127.0.0.1:8899/api/post';
? // post 方法接收三個(gè)參數(shù):
? // 參數(shù)1: 要請求的URL地址
? // 參數(shù)2: 要發(fā)送的數(shù)據(jù)對象
? // 參數(shù)3: 指定post提交的編碼類型為 application/x-www-form-urlencoded
? this.$http.post(url, { name: 'zs' }, { emulateJSON: true }).then(res => {
? ? console.log(res.body);
? });
}
```
8. 發(fā)送JSONP請求獲取數(shù)據(jù):
```
jsonpInfo() { // JSONP形式從服務(wù)器獲取數(shù)據(jù)
? var url = 'http://127.0.0.1:8899/api/jsonp';
? this.$http.jsonp(url).then(res => {
? ? console.log(res.body);
? });
}
```
## 配置本地?cái)?shù)據(jù)庫和數(shù)據(jù)接口API
1. 先解壓安裝 `PHPStudy`;
2. 解壓安裝 `Navicat` 這個(gè)數(shù)據(jù)庫可視化工具家淤,并激活;
3. 打開 `Navicat` 工具瑟由,新建空白數(shù)據(jù)庫絮重,名為 `dtcmsdb4`;
4. 雙擊新建的數(shù)據(jù)庫,連接上這個(gè)空白數(shù)據(jù)庫,在新建的數(shù)據(jù)庫上`右鍵` -> `運(yùn)行SQL文件`青伤,選擇并執(zhí)行 `dtcmsdb4.sql` 這個(gè)數(shù)據(jù)庫腳本文件督怜;如果執(zhí)行不報(bào)錯(cuò),則數(shù)據(jù)庫導(dǎo)入完成狠角;
5. 進(jìn)入文件夾 `vuecms3_nodejsapi` 內(nèi)部号杠,執(zhí)行 `npm i` 安裝所有的依賴項(xiàng);
6. 先確保本機(jī)安裝了 `nodemon`, 沒有安裝丰歌,則運(yùn)行 `npm i nodemon -g` 進(jìn)行全局安裝究流,安裝完畢后,進(jìn)入到 `vuecms3_nodejsapi`目錄 -> `src`目錄 -> 雙擊運(yùn)行 `start.bat`
7. 如果API啟動(dòng)失敗动遭,請檢查 PHPStudy 是否正常開啟,同時(shí)神得,檢查 `app.js` 中第 `14行` 中數(shù)據(jù)庫連接配置字符串是否正確厘惦;PHPStudy 中默認(rèn)的 用戶名是root,默認(rèn)的密碼也是root
## [Vue中的動(dòng)畫](https://cn.vuejs.org/v2/guide/transitions.html)
為什么要有動(dòng)畫:動(dòng)畫能夠提高用戶的體驗(yàn)哩簿,幫助用戶更好的理解頁面中的功能宵蕉;
### 使用過渡類名
1. HTML結(jié)構(gòu):
```
<div id="app">
? ? <input type="button" value="動(dòng)起來" @click="myAnimate">
? ? <!-- 使用 transition 將需要過渡的元素包裹起來 -->
? ? <transition name="fade">
? ? ? <div v-show="isshow">動(dòng)畫哦</div>
? ? </transition>
? </div>
```
2. VM 實(shí)例:
```
// 創(chuàng)建 Vue 實(shí)例,得到 ViewModel
var vm = new Vue({
? el: '#app',
? data: {
? ? isshow: false
? },
? methods: {
? ? myAnimate() {
? ? ? this.isshow = !this.isshow;
? ? }
? }
});
```
3. 定義兩組類樣式:
```
/* 定義進(jìn)入和離開時(shí)候的過渡狀態(tài) */
? ? .fade-enter-active,
? ? .fade-leave-active {
? ? ? transition: all 0.2s ease;
? ? ? position: absolute;
? ? }
? ? /* 定義進(jìn)入過渡的開始狀態(tài) 和 離開過渡的結(jié)束狀態(tài) */
? ? .fade-enter,
? ? .fade-leave-to {
? ? ? opacity: 0;
? ? ? transform: translateX(100px);
? ? }
```
### [使用第三方 CSS 動(dòng)畫庫](https://cn.vuejs.org/v2/guide/transitions.html#自定義過渡類名)
1. 導(dǎo)入動(dòng)畫類庫:
```
<link rel="stylesheet" type="text/css" href="./lib/animate.css">
```
2. 定義 transition 及屬性:
```
<transition
enter-active-class="fadeInRight"
? ? leave-active-class="fadeOutRight"
? ? :duration="{ enter: 500, leave: 800 }">
? <div class="animated" v-show="isshow">動(dòng)畫哦</div>
</transition>
```
### 使用動(dòng)畫鉤子函數(shù)
1. 定義 transition 組件以及三個(gè)鉤子函數(shù):
```
<div id="app">
? ? <input type="button" value="切換動(dòng)畫" @click="isshow = !isshow">
? ? <transition
? ? @before-enter="beforeEnter"
? ? @enter="enter"
? ? @after-enter="afterEnter">
? ? ? <div v-if="isshow" class="show">OK</div>
? ? </transition>
? </div>
```
2. 定義三個(gè) methods 鉤子方法:
```
methods: {
? ? ? ? beforeEnter(el) { // 動(dòng)畫進(jìn)入之前的回調(diào)
? ? ? ? ? el.style.transform = 'translateX(500px)';
? ? ? ? },
? ? ? ? enter(el, done) { // 動(dòng)畫進(jìn)入完成時(shí)候的回調(diào)
? ? ? ? ? el.offsetWidth;
? ? ? ? ? el.style.transform = 'translateX(0px)';
? ? ? ? ? done();
? ? ? ? },
? ? ? ? afterEnter(el) { // 動(dòng)畫進(jìn)入完成之后的回調(diào)
? ? ? ? ? this.isshow = !this.isshow;
? ? ? ? }
? ? ? }
```
3. 定義動(dòng)畫過渡時(shí)長和樣式:
```
.show{
? ? ? transition: all 0.4s ease;
? ? }
```
### [v-for 的列表過渡](https://cn.vuejs.org/v2/guide/transitions.html#列表的進(jìn)入和離開過渡)
1. 定義過渡樣式:
```
<style>
? ? .list-enter,
? ? .list-leave-to {
? ? ? opacity: 0;
? ? ? transform: translateY(10px);
? ? }
? ? .list-enter-active,
? ? .list-leave-active {
? ? ? transition: all 0.3s ease;
? ? }
</style>
```
2. 定義DOM結(jié)構(gòu)节榜,其中羡玛,需要使用 transition-group 組件把v-for循環(huán)的列表包裹起來:
```
? <div id="app">
? ? <input type="text" v-model="txt" @keyup.enter="add">
? ? <transition-group tag="ul" name="list">
? ? ? <li v-for="(item, i) in list" :key="i">{{item}}</li>
? ? </transition-group>
? </div>
```
3. 定義 VM中的結(jié)構(gòu):
```
? ? // 創(chuàng)建 Vue 實(shí)例,得到 ViewModel
? ? var vm = new Vue({
? ? ? el: '#app',
? ? ? data: {
? ? ? ? txt: '',
? ? ? ? list: [1, 2, 3, 4]
? ? ? },
? ? ? methods: {
? ? ? ? add() {
? ? ? ? ? this.list.push(this.txt);
? ? ? ? ? this.txt = '';
? ? ? ? }
? ? ? }
? ? });
```
### 列表的排序過渡
`<transition-group>` 組件還有一個(gè)特殊之處宗苍。不僅可以進(jìn)入和離開動(dòng)畫稼稿,**還可以改變定位**。要使用這個(gè)新功能只需了解新增的 `v-move` 特性讳窟,**它會(huì)在元素的改變定位的過程中應(yīng)用**让歼。
+ `v-move` 和 `v-leave-active` 結(jié)合使用,能夠讓列表的過渡更加平緩柔和:
```
.v-move{
? transition: all 0.8s ease;
}
.v-leave-active{
? position: absolute;
}
```
## 相關(guān)文章
1. [vue.js 1.x 文檔](https://v1-cn.vuejs.org/)
2. [vue.js 2.x 文檔](https://cn.vuejs.org/)
3. [String.prototype.padStart(maxLength, fillString)](http://www.css88.com/archives/7715)
4. [js 里面的鍵盤事件對應(yīng)的鍵碼](http://www.cnblogs.com/wuhua1/p/6686237.html)
5. [pagekit/vue-resource](https://github.com/pagekit/vue-resource)
6. [navicat如何導(dǎo)入sql文件和導(dǎo)出sql文件](https://jingyan.baidu.com/article/a65957f4976aad24e67f9b9b.html)
7. [貝塞爾在線生成器](http://cubic-bezier.com/#.4,-0.3,1,.33)
## 定義Vue組件
什么是組件: 組件的出現(xiàn)丽啡,就是為了拆分Vue實(shí)例的代碼量的谋右,能夠讓我們以不同的組件,來劃分不同的功能模塊补箍,將來我們需要什么樣的功能改执,就可以去調(diào)用對應(yīng)的組件即可;
組件化和模塊化的不同:
+ 模塊化: 是從代碼邏輯的角度進(jìn)行劃分的坑雅;方便代碼分層開發(fā)辈挂,保證每個(gè)功能模塊的職能單一;
+ 組件化: 是從UI界面的角度進(jìn)行劃分的霞丧;前端的組件化呢岗,方便UI組件的重用;
### 全局組件定義的三種方式
1. 使用 Vue.extend 配合 Vue.component 方法:
```
var login = Vue.extend({
? ? ? template: '<h1>登錄</h1>'
? ? });
? ? Vue.component('login', login);
```
2. 直接使用 Vue.component 方法:
```
Vue.component('register', {
? ? ? template: '<h1>注冊</h1>'
? ? });
```
3. 將模板字符串,定義到script標(biāo)簽種:
```
<script id="tmpl" type="x-template">
? ? ? <div><a href="#">登錄</a> | <a href="#">注冊</a></div>
? ? </script>
```
同時(shí)后豫,需要使用 Vue.component 來定義組件:
```
Vue.component('account', {
? ? ? template: '#tmpl'
? ? });
```
> 注意: 組件中的DOM結(jié)構(gòu)悉尾,有且只能有唯一的根元素(Root Element)來進(jìn)行包裹!
### 組件中展示數(shù)據(jù)和響應(yīng)事件
1. 在組件中挫酿,`data`需要被定義為一個(gè)方法构眯,例如:
```
Vue.component('account', {
? ? ? template: '#tmpl',
? ? ? data() {
? ? ? ? return {
? ? ? ? ? msg: '大家好!'
? ? ? ? }
? ? ? },
? ? ? methods:{
? ? ? ? login(){
? ? ? ? ? alert('點(diǎn)擊了登錄按鈕');
? ? ? ? }
? ? ? }
? ? });
```
2. 在子組件中早龟,如果將模板字符串惫霸,定義到了script標(biāo)簽中,那么葱弟,要訪問子組件身上的`data`屬性中的值壹店,需要使用`this`來訪問;
### 【重點(diǎn)】為什么組件中的data屬性必須定義為一個(gè)方法并返回一個(gè)對象
1. 通過計(jì)數(shù)器案例演示
### 使用`components`屬性定義局部子組件
1. 組件實(shí)例定義方式:
```
<script>
? ? // 創(chuàng)建 Vue 實(shí)例芝加,得到 ViewModel
? ? var vm = new Vue({
? ? ? el: '#app',
? ? ? data: {},
? ? ? methods: {},
? ? ? components: { // 定義子組件
? ? ? ? account: { // account 組件
? ? ? ? ? template: '<div><h1>這是Account組件{{name}}</h1><login></login></div>', // 在這里使用定義的子組件
? ? ? ? ? components: { // 定義子組件的子組件
? ? ? ? ? ? login: { // login 組件
? ? ? ? ? ? ? template: "<h3>這是登錄組件</h3>"
? ? ? ? ? ? }
? ? ? ? ? }
? ? ? ? }
? ? ? }
? ? });
? </script>
```
2. 引用組件:
```
<div id="app">
? ? <account></account>
? </div>
```
## 使用`flag`標(biāo)識(shí)符結(jié)合`v-if`和`v-else`切換組件
1. 頁面結(jié)構(gòu):
```
<div id="app">
? ? <input type="button" value="toggle" @click="flag=!flag">
? ? <my-com1 v-if="flag"></my-com1>
? ? <my-com2 v-else="flag"></my-com2>
? </div>
```
2. Vue實(shí)例定義:
```
<script>
? ? Vue.component('myCom1', {
? ? ? template: '<h3>奔波霸</h3>'
? ? })
? ? Vue.component('myCom2', {
? ? ? template: '<h3>霸波奔</h3>'
? ? })
? ? // 創(chuàng)建 Vue 實(shí)例硅卢,得到 ViewModel
? ? var vm = new Vue({
? ? ? el: '#app',
? ? ? data: {
? ? ? ? flag: true
? ? ? },
? ? ? methods: {}
? ? });
? </script>
```
## 使用`:is`屬性來切換不同的子組件,并添加切換動(dòng)畫
1. 組件實(shí)例定義方式:
```
? // 登錄組件
? ? const login = Vue.extend({
? ? ? template: `<div>
? ? ? ? <h3>登錄組件</h3>
? ? ? </div>`
? ? });
? ? Vue.component('login', login);
? ? // 注冊組件
? ? const register = Vue.extend({
? ? ? template: `<div>
? ? ? ? <h3>注冊組件</h3>
? ? ? </div>`
? ? });
? ? Vue.component('register', register);
? ? // 創(chuàng)建 Vue 實(shí)例,得到 ViewModel
? ? var vm = new Vue({
? ? ? el: '#app',
? ? ? data: { comName: 'login' },
? ? ? methods: {}
? ? });
```
2. 使用`component`標(biāo)簽藏杖,來引用組件将塑,并通過`:is`屬性來指定要加載的組件:
```
? <div id="app">
? ? <a href="#" @click.prevent="comName='login'">登錄</a>
? ? <a href="#" @click.prevent="comName='register'">注冊</a>
? ? <hr>
? ? <transition mode="out-in">
? ? ? <component :is="comName"></component>
? ? </transition>
? </div>
```
3. 添加切換樣式:
```
? <style>
? ? .v-enter,
? ? .v-leave-to {
? ? ? opacity: 0;
? ? ? transform: translateX(30px);
? ? }
? ? .v-enter-active,
? ? .v-leave-active {
? ? ? position: absolute;
? ? ? transition: all 0.3s ease;
? ? }
? ? h3{
? ? ? margin: 0;
? ? }
? </style>
```
## 父組件向子組件傳值
1. 組件實(shí)例定義方式,注意:一定要使用`props`屬性來定義父組件傳遞過來的數(shù)據(jù)
```
<script>
? ? // 創(chuàng)建 Vue 實(shí)例蝌麸,得到 ViewModel
? ? var vm = new Vue({
? ? ? el: '#app',
? ? ? data: {
? ? ? ? msg: '這是父組件中的消息'
? ? ? },
? ? ? components: {
? ? ? ? son: {
? ? ? ? ? template: '<h1>這是子組件 --- {{finfo}}</h1>',
? ? ? ? ? props: ['finfo']
? ? ? ? }
? ? ? }
? ? });
? </script>
```
2. 使用`v-bind`或簡化指令点寥,將數(shù)據(jù)傳遞到子組件中:
```
<div id="app">
? ? <son :finfo="msg"></son>
? </div>
```
## 子組件向父組件傳值
1. 原理:父組件將方法的引用,傳遞到子組件內(nèi)部来吩,子組件在內(nèi)部調(diào)用父組件傳遞過來的方法敢辩,同時(shí)把要發(fā)送給父組件的數(shù)據(jù),在調(diào)用方法的時(shí)候當(dāng)作參數(shù)傳遞進(jìn)去误褪;
2. 父組件將方法的引用傳遞給子組件责鳍,其中,`getMsg`是父組件中`methods`中定義的方法名稱兽间,`func`是子組件調(diào)用傳遞過來方法時(shí)候的方法名稱
```
<son @func="getMsg"></son>
```
3. 子組件內(nèi)部通過`this.$emit('方法名', 要傳遞的數(shù)據(jù))`方式历葛,來調(diào)用父組件中的方法,同時(shí)把數(shù)據(jù)傳遞給父組件使用
```
<div id="app">
? ? <!-- 引用父組件 -->
? ? <son @func="getMsg"></son>
? ? <!-- 組件模板定義 -->
? ? <script type="x-template" id="son">
? ? ? <div>
? ? ? ? <input type="button" value="向父組件傳值" @click="sendMsg" />
? ? ? </div>
? ? </script>
? </div>
? <script>
? ? // 子組件的定義方式
? ? Vue.component('son', {
? ? ? template: '#son', // 組件模板Id
? ? ? methods: {
? ? ? ? sendMsg() { // 按鈕的點(diǎn)擊事件
? ? ? ? ? this.$emit('func', 'OK'); // 調(diào)用父組件傳遞過來的方法嘀略,同時(shí)把數(shù)據(jù)傳遞出去
? ? ? ? }
? ? ? }
? ? });
? ? // 創(chuàng)建 Vue 實(shí)例恤溶,得到 ViewModel
? ? var vm = new Vue({
? ? ? el: '#app',
? ? ? data: {},
? ? ? methods: {
? ? ? ? getMsg(val){ // 子組件中,通過 this.$emit() 實(shí)際調(diào)用的方法帜羊,在此進(jìn)行定義
? ? ? ? ? alert(val);
? ? ? ? }
? ? ? }
? ? });
? </script>
```
## 評(píng)論列表案例
目標(biāo):主要練習(xí)父子組件之間傳值
## 使用 `this.$refs` 來獲取元素和組件
```
? <div id="app">
? ? <div>
? ? ? <input type="button" value="獲取元素內(nèi)容" @click="getElement" />
? ? ? <!-- 使用 ref 獲取元素 -->
? ? ? <h1 ref="myh1">這是一個(gè)大大的H1</h1>
? ? ? <hr>
? ? ? <!-- 使用 ref 獲取子組件 -->
? ? ? <my-com ref="mycom"></my-com>
? ? </div>
? </div>
? <script>
? ? Vue.component('my-com', {
? ? ? template: '<h5>這是一個(gè)子組件</h5>',
? ? ? data() {
? ? ? ? return {
? ? ? ? ? name: '子組件'
? ? ? ? }
? ? ? }
? ? });
? ? // 創(chuàng)建 Vue 實(shí)例咒程,得到 ViewModel
? ? var vm = new Vue({
? ? ? el: '#app',
? ? ? data: {},
? ? ? methods: {
? ? ? ? getElement() {
? ? ? ? ? // 通過 this.$refs 來獲取元素
? ? ? ? ? console.log(this.$refs.myh1.innerText);
? ? ? ? ? // 通過 this.$refs 來獲取組件
? ? ? ? ? console.log(this.$refs.mycom.name);
? ? ? ? }
? ? ? }
? ? });
? </script>
```
## 什么是路由
1. 對于普通的網(wǎng)站,所有的超鏈接都是URL地址讼育,所有的URL地址都對應(yīng)服務(wù)器上對應(yīng)的資源帐姻;
2. 對于單頁面應(yīng)用程序來說稠集,主要通過URL中的hash(#號(hào))來實(shí)現(xiàn)不同頁面之間的切換,同時(shí)饥瓷,hash有一個(gè)特點(diǎn):HTTP請求中不會(huì)包含hash相關(guān)的內(nèi)容剥纷;所以,單頁面程序中的頁面跳轉(zhuǎn)主要用hash實(shí)現(xiàn)呢铆;
3. 在單頁面應(yīng)用程序中晦鞋,這種通過hash改變來切換頁面的方式,稱作前端路由(區(qū)別于后端路由)棺克;
## 在 vue 中使用 vue-router
1. 導(dǎo)入 vue-router 組件類庫:
```
<!-- 1. 導(dǎo)入 vue-router 組件類庫 -->
? <script src="./lib/vue-router-2.7.0.js"></script>
```
2. 使用 router-link 組件來導(dǎo)航
```
<!-- 2. 使用 router-link 組件來導(dǎo)航 -->
<router-link to="/login">登錄</router-link>
<router-link to="/register">注冊</router-link>
```
3. 使用 router-view 組件來顯示匹配到的組件
```
<!-- 3. 使用 router-view 組件來顯示匹配到的組件 -->
<router-view></router-view>
```
4. 創(chuàng)建使用`Vue.extend`創(chuàng)建組件
```
? ? // 4.1 使用 Vue.extend 來創(chuàng)建登錄組件
? ? var login = Vue.extend({
? ? ? template: '<h1>登錄組件</h1>'
? ? });
? ? // 4.2 使用 Vue.extend 來創(chuàng)建注冊組件
? ? var register = Vue.extend({
? ? ? template: '<h1>注冊組件</h1>'
? ? });
```
5. 創(chuàng)建一個(gè)路由 router 實(shí)例悠垛,通過 routers 屬性來定義路由匹配規(guī)則
```
// 5. 創(chuàng)建一個(gè)路由 router 實(shí)例,通過 routers 屬性來定義路由匹配規(guī)則
? ? var router = new VueRouter({
? ? ? routes: [
? ? ? ? { path: '/login', component: login },
? ? ? ? { path: '/register', component: register }
? ? ? ]
? ? });
```
6. 使用 router 屬性來使用路由規(guī)則
```
// 6. 創(chuàng)建 Vue 實(shí)例娜谊,得到 ViewModel
? ? var vm = new Vue({
? ? ? el: '#app',
? ? ? router: router // 使用 router 屬性來使用路由規(guī)則
? ? });
```
## 設(shè)置路由高亮
## 設(shè)置路由切換動(dòng)效
## 在路由規(guī)則中定義參數(shù)
1. 在規(guī)則中定義參數(shù):
```
{ path: '/register/:id', component: register }
```
2. 通過 `this.$route.params`來獲取路由中的參數(shù):
```
var register = Vue.extend({
? ? ? template: '<h1>注冊組件 --- {{this.$route.params.id}}</h1>'
? ? });
```
## 使用 `children` 屬性實(shí)現(xiàn)路由嵌套
```
? <div id="app">
? ? <router-link to="/account">Account</router-link>
? ? <router-view></router-view>
? </div>
? <script>
? ? // 父路由中的組件
? ? const account = Vue.extend({
? ? ? template: `<div>
? ? ? ? 這是account組件
? ? ? ? <router-link to="/account/login">login</router-link> |
? ? ? ? <router-link to="/account/register">register</router-link>
? ? ? ? <router-view></router-view>
? ? ? </div>`
? ? });
? ? // 子路由中的 login 組件
? ? const login = Vue.extend({
? ? ? template: '<div>登錄組件</div>'
? ? });
? ? // 子路由中的 register 組件
? ? const register = Vue.extend({
? ? ? template: '<div>注冊組件</div>'
? ? });
? ? // 路由實(shí)例
? ? var router = new VueRouter({
? ? ? routes: [
? ? ? ? { path: '/', redirect: '/account/login' }, // 使用 redirect 實(shí)現(xiàn)路由重定向
? ? ? ? {
? ? ? ? ? path: '/account',
? ? ? ? ? component: account,
? ? ? ? ? children: [ // 通過 children 數(shù)組屬性确买,來實(shí)現(xiàn)路由的嵌套
? ? ? ? ? ? { path: 'login', component: login }, // 注意,子路由的開頭位置纱皆,不要加 / 路徑符
? ? ? ? ? ? { path: 'register', component: register }
? ? ? ? ? ]
? ? ? ? }
? ? ? ]
? ? });
? ? // 創(chuàng)建 Vue 實(shí)例拇惋,得到 ViewModel
? ? var vm = new Vue({
? ? ? el: '#app',
? ? ? data: {},
? ? ? methods: {},
? ? ? components: {
? ? ? ? account
? ? ? },
? ? ? router: router
? ? });
? </script>
```
## 命名視圖實(shí)現(xiàn)經(jīng)典布局
1. 標(biāo)簽代碼結(jié)構(gòu):
```
<div id="app">
? ? <router-view></router-view>
? ? <div class="content">
? ? ? <router-view name="a"></router-view>
? ? ? <router-view name="b"></router-view>
? ? </div>
? </div>
```
2. JS代碼:
```
<script>
? ? var header = Vue.component('header', {
? ? ? template: '<div class="header">header</div>'
? ? });
? ? var sidebar = Vue.component('sidebar', {
? ? ? template: '<div class="sidebar">sidebar</div>'
? ? });
? ? var mainbox = Vue.component('mainbox', {
? ? ? template: '<div class="mainbox">mainbox</div>'
? ? });
? ? // 創(chuàng)建路由對象
? ? var router = new VueRouter({
? ? ? routes: [
? ? ? ? {
? ? ? ? ? path: '/', components: {
? ? ? ? ? ? default: header,
? ? ? ? ? ? a: sidebar,
? ? ? ? ? ? b: mainbox
? ? ? ? ? }
? ? ? ? }
? ? ? ]
? ? });
? ? // 創(chuàng)建 Vue 實(shí)例,得到 ViewModel
? ? var vm = new Vue({
? ? ? el: '#app',
? ? ? data: {},
? ? ? methods: {},
? ? ? router
? ? });
? </script>
```
3. CSS 樣式:
```
? <style>
? ? .header {
? ? ? border: 1px solid red;
? ? }
? ? .content{
? ? ? display: flex;
? ? }
? ? .sidebar {
? ? ? flex: 2;
? ? ? border: 1px solid green;
? ? ? height: 500px;
? ? }
? ? .mainbox{
? ? ? flex: 8;
? ? ? border: 1px solid blue;
? ? ? height: 500px;
? ? }
? </style>
```
## `watch`屬性的使用
考慮一個(gè)問題:想要實(shí)現(xiàn) `名` 和 `姓` 兩個(gè)文本框的內(nèi)容改變抹剩,則全名的文本框中的值也跟著改變;(用以前的知識(shí)如何實(shí)現(xiàn)蓉坎?澳眷??)
1. 監(jiān)聽`data`中屬性的改變:
```
<div id="app">
? ? <input type="text" v-model="firstName"> +
? ? <input type="text" v-model="lastName"> =
? ? <span>{{fullName}}</span>
? </div>
? <script>
? ? // 創(chuàng)建 Vue 實(shí)例蛉艾,得到 ViewModel
? ? var vm = new Vue({
? ? ? el: '#app',
? ? ? data: {
? ? ? ? firstName: 'jack',
? ? ? ? lastName: 'chen',
? ? ? ? fullName: 'jack - chen'
? ? ? },
? ? ? methods: {},
? ? ? watch: {
? ? ? ? 'firstName': function (newVal, oldVal) { // 第一個(gè)參數(shù)是新數(shù)據(jù)钳踊,第二個(gè)參數(shù)是舊數(shù)據(jù)
? ? ? ? ? this.fullName = newVal + ' - ' + this.lastName;
? ? ? ? },
? ? ? ? 'lastName': function (newVal, oldVal) {
? ? ? ? ? this.fullName = this.firstName + ' - ' + newVal;
? ? ? ? }
? ? ? }
? ? });
? </script>
```
2. 監(jiān)聽路由對象的改變:
```
<div id="app">
? ? <router-link to="/login">登錄</router-link>
? ? <router-link to="/register">注冊</router-link>
? ? <router-view></router-view>
? </div>
? <script>
? ? var login = Vue.extend({
? ? ? template: '<h1>登錄組件</h1>'
? ? });
? ? var register = Vue.extend({
? ? ? template: '<h1>注冊組件</h1>'
? ? });
? ? var router = new VueRouter({
? ? ? routes: [
? ? ? ? { path: "/login", component: login },
? ? ? ? { path: "/register", component: register }
? ? ? ]
? ? });
? ? // 創(chuàng)建 Vue 實(shí)例,得到 ViewModel
? ? var vm = new Vue({
? ? ? el: '#app',
? ? ? data: {},
? ? ? methods: {},
? ? ? router: router,
? ? ? watch: {
? ? ? ? '$route': function (newVal, oldVal) {
? ? ? ? ? if (newVal.path === '/login') {
? ? ? ? ? ? console.log('這是登錄組件');
? ? ? ? ? }
? ? ? ? }
? ? ? }
? ? });
? </script>
```
## `computed`計(jì)算屬性的使用
1. 默認(rèn)只有`getter`的計(jì)算屬性:
```
<div id="app">
? ? <input type="text" v-model="firstName"> +
? ? <input type="text" v-model="lastName"> =
? ? <span>{{fullName}}</span>
? </div>
? <script>
? ? // 創(chuàng)建 Vue 實(shí)例勿侯,得到 ViewModel
? ? var vm = new Vue({
? ? ? el: '#app',
? ? ? data: {
? ? ? ? firstName: 'jack',
? ? ? ? lastName: 'chen'
? ? ? },
? ? ? methods: {},
? ? ? computed: { // 計(jì)算屬性拓瞪; 特點(diǎn):當(dāng)計(jì)算屬性中所以來的任何一個(gè) data 屬性改變之后,都會(huì)重新觸發(fā) 本計(jì)算屬性 的重新計(jì)算助琐,從而更新 fullName 的值
? ? ? ? fullName() {
? ? ? ? ? return this.firstName + ' - ' + this.lastName;
? ? ? ? }
? ? ? }
? ? });
? </script>
```
2. 定義有`getter`和`setter`的計(jì)算屬性:
```
<div id="app">
? ? <input type="text" v-model="firstName">
? ? <input type="text" v-model="lastName">
? ? <!-- 點(diǎn)擊按鈕重新為 計(jì)算屬性 fullName 賦值 -->
? ? <input type="button" value="修改fullName" @click="changeName">
? ? <span>{{fullName}}</span>
? </div>
? <script>
? ? // 創(chuàng)建 Vue 實(shí)例祭埂,得到 ViewModel
? ? var vm = new Vue({
? ? ? el: '#app',
? ? ? data: {
? ? ? ? firstName: 'jack',
? ? ? ? lastName: 'chen'
? ? ? },
? ? ? methods: {
? ? ? ? changeName() {
? ? ? ? ? this.fullName = 'TOM - chen2';
? ? ? ? }
? ? ? },
? ? ? computed: {
? ? ? ? fullName: {
? ? ? ? ? get: function () {
? ? ? ? ? ? return this.firstName + ' - ' + this.lastName;
? ? ? ? ? },
? ? ? ? ? set: function (newVal) {
? ? ? ? ? ? var parts = newVal.split(' - ');
? ? ? ? ? ? this.firstName = parts[0];
? ? ? ? ? ? this.lastName = parts[1];
? ? ? ? ? }
? ? ? ? }
? ? ? }
? ? });
? </script>
```
## `watch`、`computed`和`methods`之間的對比
1. `computed`屬性的結(jié)果會(huì)被緩存兵钮,除非依賴的響應(yīng)式屬性變化才會(huì)重新計(jì)算蛆橡。主要當(dāng)作屬性來使用;
2. `methods`方法表示一個(gè)具體的操作掘譬,主要書寫業(yè)務(wù)邏輯泰演;
3. `watch`一個(gè)對象,鍵是需要觀察的表達(dá)式葱轩,值是對應(yīng)回調(diào)函數(shù)睦焕。主要用來監(jiān)聽某些特定數(shù)據(jù)的變化藐握,從而進(jìn)行某些具體的業(yè)務(wù)邏輯操作;可以看作是`computed`和`methods`的結(jié)合體垃喊;
## `nrm`的安裝使用
作用:提供了一些最常用的NPM包鏡像地址猾普,能夠讓我們快速的切換安裝包時(shí)候的服務(wù)器地址;
什么是鏡像:原來包剛一開始是只存在于國外的NPM服務(wù)器缔御,但是由于網(wǎng)絡(luò)原因抬闷,經(jīng)常訪問不到,這時(shí)候耕突,我們可以在國內(nèi)笤成,創(chuàng)建一個(gè)和官網(wǎng)完全一樣的NPM服務(wù)器,只不過眷茁,數(shù)據(jù)都是從人家那里拿過來的炕泳,除此之外,使用方式完全一樣上祈;
1. 運(yùn)行`npm i nrm -g`全局安裝`nrm`包培遵;
2. 使用`nrm ls`查看當(dāng)前所有可用的鏡像源地址以及當(dāng)前所使用的鏡像源地址;
3. 使用`nrm use npm`或`nrm use taobao`切換不同的鏡像源地址登刺;
## 相關(guān)文件
1. [URL中的hash(井號(hào))](http://www.cnblogs.com/joyho/articles/4430148.html)
Data多實(shí)例共享問題:
app.vue文件我們可以分成三部分解讀籽腕,
<template></template>標(biāo)簽包裹的內(nèi)容:這是模板的HTMLDom結(jié)構(gòu),里邊引入了一張圖片和<router-view></router-view>標(biāo)簽纸俭,<router-view>標(biāo)簽說明使用了路由機(jī)制皇耗。我們會(huì)在以后專門拿出一篇文章講Vue-router。
<script></script>標(biāo)簽包括的js內(nèi)容:你可以在這里些一些頁面的動(dòng)態(tài)效果和Vue的邏輯代碼揍很。
<style></style>標(biāo)簽包裹的css內(nèi)容:這里就是你平時(shí)寫的CSS樣式郎楼,對頁面樣子進(jìn)行裝飾用的,需要特別說明的是你可以用<style scoped></style>來聲明這些css樣式只在本模板中起作用窒悔。