Vue基礎(chǔ)

MVC和MVVM的關(guān)系圖解

### 什么是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í)例生命周期)


lifecycle

+ 什么是生命周期:從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樣式只在本模板中起作用窒悔。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末呜袁,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子简珠,更是在濱河造成了極大的恐慌阶界,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件聋庵,死亡現(xiàn)場離奇詭異荐操,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)珍策,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門托启,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人攘宙,你說我怎么就攤上這事屯耸」涨ǎ” “怎么了?”我有些...
    開封第一講書人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵疗绣,是天一觀的道長线召。 經(jīng)常有香客問我,道長多矮,這世上最難降的妖魔是什么缓淹? 我笑而不...
    開封第一講書人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮塔逃,結(jié)果婚禮上讯壶,老公的妹妹穿的比我還像新娘。我一直安慰自己湾盗,他們只是感情好伏蚊,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著格粪,像睡著了一般躏吊。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上帐萎,一...
    開封第一講書人閱讀 52,156評(píng)論 1 308
  • 那天比伏,我揣著相機(jī)與錄音,去河邊找鬼疆导。 笑死凳怨,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的是鬼。 我是一名探鬼主播,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼紫新,長吁一口氣:“原來是場噩夢啊……” “哼均蜜!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起芒率,我...
    開封第一講書人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬榮一對情侶失蹤囤耳,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后偶芍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體充择,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年匪蟀,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了椎麦。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡材彪,死狀恐怖观挎,靈堂內(nèi)的尸體忽然破棺而出琴儿,到底是詐尸還是另有隱情,我是刑警寧澤嘁捷,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響喷兼,放射性物質(zhì)發(fā)生泄漏棵介。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一缓升、第九天 我趴在偏房一處隱蔽的房頂上張望鼓鲁。 院中可真熱鬧,春花似錦仔沿、人聲如沸坐桩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽绵跷。三九已至,卻和暖如春成福,著一層夾襖步出監(jiān)牢的瞬間碾局,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來泰國打工奴艾, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留净当,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓蕴潦,卻偏偏與公主長得像像啼,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子潭苞,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容