Vue基礎

MVC和MVVM的關系圖解

### 什么是Vue.js

+ Vue.js 是目前最火的一個前端框架,React是最流行的一個前端框架(React除了開發網站,還可以開發手機App, Vue語法也是可以用于進行手機App開發的,需要借助于Weex)

+ Vue.js 是前端的**主流框架之一**,和Angular.js、React.js 一起,并成為前端三大主流框架!

+ Vue.js 是一套構建用戶界面的框架,**只關注視圖層**,它不僅易于上手,還便于與第三方庫或既有項目整合。(Vue有配套的第三方類庫,可以整合起來做大型項目的開發)

+ 前端的主要工作?主要負責MVC中的V這一層;主要工作就是和界面打交道,來制作前端頁面效果;

## 為什么要學習流行框架

+ 企業為了提高開發效率:在企業中,時間就是效率,效率就是金錢;

? - 企業中,使用框架,能夠提高開發的效率;

+ 提高開發效率的發展歷程:原生JS -> Jquery之類的類庫 -> 前端模板引擎 -> Angular.js / Vue.js(能夠幫助我們減少不必要的DOM操作;提高渲染效率;雙向數據綁定的概念【通過框架提供的指令,我們前端程序員只需要關心數據的業務邏輯,不再關心DOM是如何渲染的了】)

+ 在Vue中,一個核心的概念,就是讓用戶不再操作DOM元素,解放了用戶的雙手,讓程序員可以更多的時間去關注業務邏輯;

+ 增強自己就業時候的競爭力

? - 人無我有,人有我優

? - 你平時不忙的時候,都在干嘛?

## 框架和庫的區別

+ 框架:是一套完整的解決方案;對項目的侵入性較大,項目如果需要更換框架,則需要重新架構整個項目。

? - node 中的 express;

+ 庫(插件):提供某一個小功能,對項目的侵入性較小,如果某個庫無法完成某些需求,可以很容易切換到其它庫實現需求。

? - 1. 從Jquery 切換到 Zepto

? - 2. 從 EJS 切換到 art-template

## Node(后端)中的 MVC 與 前端中的 MVVM 之間的區別

+ MVC 是后端的分層開發概念;

+ MVVM是前端視圖層的概念,主要關注于 視圖層分離,也就是說:MVVM把前端的視圖層,分為了 三部分 Model, View , VM ViewModel

+ 為什么有了MVC還要有MVVM

## Vue.js 基本代碼 和 MVVM 之間的對應關系

## Vue之 - `基本的代碼結構`和`插值表達式`、`v-cloak`

## Vue指令之`v-text`和`v-html`

## Vue指令之`v-bind`的三種用法

1. 直接使用指令`v-bind`

2. 使用簡化指令`:`

3. 在綁定的時候,拼接綁定內容:`:title="btnTitle + ', 這是追加的內容'"`

## Vue指令之`v-on`和`跑馬燈效果`

### 跑馬燈效果

1. HTML結構:

```

<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實例:

```

// 創建 Vue 實例,得到 ViewModel

? ? var vm = new Vue({

? ? ? el: '#app',

? ? ? data: {

? ? ? ? info: '猥瑣發育,別浪~!',

? ? ? ? intervalId: null

? ? ? },

? ? ? methods: {

? ? ? ? go() {

? ? ? ? ? // 如果當前有定時器在運行,則直接return

? ? ? ? ? if (this.intervalId != null) {

? ? ? ? ? ? return;

? ? ? ? ? }

? ? ? ? ? // 開始定時器

? ? ? ? ? this.intervalId = setInterval(() => {

? ? ? ? ? ? this.info = this.info.substring(1) + this.info.substring(0, 1);

? ? ? ? ? }, 500);

? ? ? ? },

? ? ? ? stop() {

? ? ? ? ? clearInterval(this.intervalId);

? ? ? ? }

? ? ? }

? ? });

```

## Vue指令之`v-on的縮寫`和`事件修飾符`

### 事件修飾符:

+ .stop? ? ? 阻止冒泡

+ .prevent? ? 阻止默認事件

+ .capture? ? 添加事件偵聽器時使用事件捕獲模式

+ .self? ? ? 只當事件在該元素本身(比如不是子元素)觸發時觸發回調

+ .once? ? ? 事件只觸發一次

## Vue指令之`v-model`和`雙向數據綁定`

## 簡易計算器案例

1. HTML 代碼結構

```

? <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實例代碼:

```

// 創建 Vue 實例,得到 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. 數組

```

<h1 :class="['red', 'thin']">這是一個邪惡的H1</h1>

```

2. 數組中使用三元表達式

```

<h1 :class="['red', 'thin', isactive?'active':'']">這是一個邪惡的H1</h1>

```

3. 數組中嵌套對象

```

<h1 :class="['red', 'thin', {'active': isactive}]">這是一個邪惡的H1</h1>

```

4. 直接使用對象

```

<h1 :class="{red:true, italic:true, active:true, thin:true}">這是一個邪惡的H1</h1>

```

### 使用內聯樣式

1. 直接在元素上通過 `:style` 的形式,書寫樣式對象

```

<h1 :style="{color: 'red', 'font-size': '40px'}">這是一個善良的H1</h1>

```

2. 將樣式對象,定義到 `data` 中,并直接引用到 `:style` 中

+ 在data上定義樣式:

```

data: {

? ? ? ? h1StyleObj: { color: 'red', 'font-size': '40px', 'font-weight': '200' }

}

```

+ 在元素中,通過屬性綁定的形式,將樣式對象應用到元素中:

```

<h1 :style="h1StyleObj">這是一個善良的H1</h1>

```

3. 在 `:style` 中通過數組,引用多個 `data` 上的樣式對象

+ 在data上定義樣式:

```

data: {

? ? ? ? h1StyleObj: { color: 'red', 'font-size': '40px', 'font-weight': '200' },

? ? ? ? h1StyleObj2: { fontStyle: 'italic' }

}

```

+ 在元素中,通過屬性綁定的形式,將樣式對象應用到元素中:

```

<h1 :style="[h1StyleObj, h1StyleObj2]">這是一個善良的H1</h1>

```

## Vue指令之`v-for`和`key`屬性

1. 迭代數組

```

<ul>

? <li v-for="(item, i) in list">索引:{{i}} --- 姓名:{{item.name}} --- 年齡:{{item.age}}</li>

</ul>

```

2. 迭代對象中的屬性

```

<!-- 循環遍歷對象身上的屬性 -->

? ? <div v-for="(val, key, i) in userInfo">{{val}} --- {{key}} --- {{i}}</div>

```

3. 迭代數字

```

<p v-for="i in 10">這是第 {{i}} 個P標簽</p>

```

> 2.2.0+ 的版本里,**當在組件中使用** v-for 時,key 現在是必須的。

當 Vue.js 用 v-for 正在更新已渲染過的元素列表時,它默認用 “**就地復用**” 策略。如果數據項的順序被改變,Vue將**不是移動 DOM 元素來匹配數據項的順序**, 而是**簡單復用此處每個元素**,并且確保它在特定索引下顯示已被渲染過的每個元素。

為了給 Vue 一個提示,**以便它能跟蹤每個節點的身份,從而重用和重新排序現有元素**,你需要為每項提供一個唯一 key 屬性。

## Vue指令之`v-if`和`v-show`

> 一般來說,v-if 有更高的切換消耗而 v-show 有更高的初始渲染消耗。因此,如果需要頻繁切換 v-show 較好,如果在運行時條件不大可能改變 v-if 較好。



## 品牌管理案例

### 添加新品牌

### 刪除品牌

### 根據條件篩選品牌

1. 1.x 版本中的filterBy指令,在2.x中已經被廢除:

[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版本中[手動實現篩選的方式](https://cn.vuejs.org/v2/guide/list.html#顯示過濾-排序結果):

+ 篩選框綁定到 VM 實例中的 `searchName` 屬性:

```

<hr> 輸入篩選名稱:

<input type="text" v-model="searchName">

```

+ 在使用 `v-for` 指令循環每一行數據的時候,不再直接 `item in list`,而是 `in` 一個 過濾的methods 方法,同時,把過濾條件`searchName`傳遞進去:

```

<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` 過濾方法中,使用 數組的 `filter` 方法進行過濾:

```

search(name) {

? return this.list.filter(x => {

? ? return x.name.indexOf(name) != -1;

? });

}

```

## Vue調試工具`vue-devtools`的安裝步驟和使用

[Vue.js devtools - 翻墻安裝方式 - 推薦](https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd?hl=zh-CN)

## 過濾器

概念:Vue.js 允許你自定義過濾器,**可被用作一些常見的文本格式化**。過濾器可以用在兩個地方:**mustache 插值和 v-bind 表達式**。過濾器應該被添加在 JavaScript 表達式的尾部,由“管道”符指示;

### 私有過濾器

1. HTML元素:

```

<td>{{item.ctime | dataFormat('yyyy-mm-dd')}}</td>

```

2. 私有 `filters` 定義方式:

```

filters: { // 私有局部過濾器,只能在 當前 VM 對象所控制的 View 區域進行使用

? ? dataFormat(input, pattern = "") { // 在參數列表中 通過 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');

? ? ? // 如果 傳遞進來的字符串類型,轉為小寫之后,等于 yyyy-mm-dd,那么就返回 年-月-日

? ? ? // 否則,就返回? 年-月-日 時:分:秒

? ? ? if (pattern.toLowerCase() === 'yyyy-mm-dd') {

? ? ? ? return `${y}-${m}-$xweae33`;

? ? ? } else {

? ? ? ? // 獲取時分秒

? ? ? ? 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}-$xbaxuqg ${hh}:${mm}:${ss}`;

? ? ? }

? ? }

? }

```

> 使用ES6中的字符串新方法 String.prototype.padStart(maxLength, fillString='') 或 String.prototype.padEnd(maxLength, fillString='')來填充字符串;

### 全局過濾器

```

// 定義一個全局過濾器

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');

? // 如果 傳遞進來的字符串類型,轉為小寫之后,等于 yyyy-mm-dd,那么就返回 年-月-日

? // 否則,就返回? 年-月-日 時:分:秒

? if (pattern.toLowerCase() === 'yyyy-mm-dd') {

? ? return `${y}-${m}-$s4c14ha`;

? } else {

? ? // 獲取時分秒

? ? 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}-$lsns6gc ${hh}:${mm}:${ss}`;

? }

});

```

> 注意:當有局部和全局兩個名稱相同的過濾器時候,會以就近原則進行調用,即:局部過濾器優先于全局過濾器被調用!

## 鍵盤修飾符以及自定義鍵盤修飾符

### 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,為綁定的元素自動獲取焦點:

? ? Vue.directive('focus', {

? ? ? inserted: function (el) { // inserted 表示被綁定元素插入父節點時調用

? ? ? ? el.focus();

? ? ? }

? ? });

? ? // 自定義局部指令 v-color 和 v-font-weight,為綁定的元素設置指定的字體顏色 和 字體粗細:

? ? ? directives: {

? ? ? ? color: { // 為元素設置指定的字體顏色

? ? ? ? ? bind(el, binding) {

? ? ? ? ? ? el.style.color = binding.value;

? ? ? ? ? }

? ? ? ? },

? ? ? ? 'font-weight': function (el, binding2) { // 自定義指令的簡寫形式,等同于定義了 bind 和 update 兩個鉤子函數

? ? ? ? ? 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實例的生命周期](https://cn.vuejs.org/v2/guide/instance.html#實例生命周期)


lifecycle

+ 什么是生命周期:從Vue實例創建、運行、到銷毀期間,總是伴隨著各種各樣的事件,這些事件,統稱為生命周期!

+ [生命周期鉤子](https://cn.vuejs.org/v2/api/#選項-生命周期鉤子):就是生命周期事件的別名而已;

+ 生命周期鉤子 = 生命周期函數 = 生命周期事件

+ 主要的生命周期函數分類:

- 創建期間的生命周期函數:

? + beforeCreate:實例剛在內存中被創建出來,此時,還沒有初始化好 data 和 methods 屬性

? + created:實例已經在內存中創建OK,此時 data 和 methods 已經創建OK,此時還沒有開始 編譯模板

? + beforeMount:此時已經完成了模板的編譯,但是還沒有掛載到頁面中

? + mounted:此時,已經將編譯好的模板,掛載到了頁面指定的容器中顯示

- 運行期間的生命周期函數:

+ beforeUpdate:狀態更新之前執行此函數, 此時 data 中的狀態值是最新的,但是界面上顯示的 數據還是舊的,因為此時還沒有開始重新渲染DOM節點

+ updated:實例更新完畢之后調用此函數,此時 data 中的狀態值 和 界面上顯示的數據,都已經完成了更新,界面已經被重新渲染好了!

- 銷毀期間的生命周期函數:

+ beforeDestroy:實例銷毀之前調用。在這一步,實例仍然完全可用。

+ destroyed:Vue 實例銷毀后調用。調用后,Vue 實例指示的所有東西都會解綁定,所有的事件監聽器會被移除,所有的子實例也會被銷毀。

## [vue-resource 實現 get, post, jsonp請求](https://github.com/pagekit/vue-resource)

除了 vue-resource 之外,還可以使用 `axios` 的第三方包實現實現數據的請求

1. 之前的學習中,如何發起數據請求?

2. 常見的數據請求類型?? 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的實現原理

+ 由于瀏覽器的安全性限制,不允許AJAX訪問 協議不同、域名不同、端口號不同的 數據接口,瀏覽器認為這種訪問不安全;

+ 可以通過動態創建script標簽的形式,把script標簽的src屬性,指向數據接口的地址,因為script標簽不存在跨域限制,這種數據獲取方式,稱作JSONP(注意:根據JSONP的實現原理,知曉,JSONP只支持Get請求);

+ 具體實現過程:

- 先在客戶端定義一個回調方法,預定義對數據的操作;

- 再把這個回調方法的名稱,通過URL傳參的形式,提交到服務器的數據接口;

- 服務器數據接口組織好要發送給客戶端的數據,再拿著客戶端傳遞過來的回調方法名稱,拼接出一個調用這個方法的字符串,發送給客戶端去解析執行;

- 客戶端拿到服務器返回的字符串之后,當作Script腳本去解析執行,這樣就能夠拿到JSONP的數據了;

+ 帶大家通過 Node.js ,來手動實現一個JSONP的請求例子;

```

? ? const http = require('http');

? ? // 導入解析 URL 地址的核心模塊

? ? const urlModule = require('url');

? ? const server = http.createServer();

? ? // 監聽 服務器的 request 請求事件,處理每個請求

? ? server.on('request', (req, res) => {

? ? ? const url = req.url;

? ? ? // 解析客戶端請求的URL地址

? ? ? var info = urlModule.parse(url, true);

? ? ? // 如果請求的 URL 地址是 /getjsonp ,則表示要獲取JSONP類型的數據

? ? ? if (info.pathname === '/getjsonp') {

? ? ? ? // 獲取客戶端指定的回調函數的名稱

? ? ? ? var cbName = info.query.callback;

? ? ? ? // 手動拼接要返回給客戶端的數據對象

? ? ? ? var data = {

? ? ? ? ? name: 'zs',

? ? ? ? ? age: 22,

? ? ? ? ? gender: '男',

? ? ? ? ? hobby: ['吃飯', '睡覺', '運動']

? ? ? ? }

? ? ? ? // 拼接出一個方法的調用,在調用這個方法的時候,把要發送給客戶端的數據,序列化為字符串,作為參數傳遞給這個調用的方法:

? ? ? ? var result = `${cbName}(${JSON.stringify(data)})`;

? ? ? ? // 將拼接好的方法的調用,返回給客戶端去解析執行

? ? ? ? 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`標簽,引入 `vue-resource` 的腳本文件;

+ 注意:引用的先后順序是:先引用 `Vue` 的腳本文件,再引用 `vue-resource` 的腳本文件;

6. 發送get請求:

```

getInfo() { // get 方式獲取數據

? this.$http.get('http://127.0.0.1:8899/api/getlunbo').then(res => {

? ? console.log(res.body);

? })

}

```

7. 發送post請求:

```

postInfo() {

? var url = 'http://127.0.0.1:8899/api/post';

? // post 方法接收三個參數:

? // 參數1: 要請求的URL地址

? // 參數2: 要發送的數據對象

? // 參數3: 指定post提交的編碼類型為 application/x-www-form-urlencoded

? this.$http.post(url, { name: 'zs' }, { emulateJSON: true }).then(res => {

? ? console.log(res.body);

? });

}

```

8. 發送JSONP請求獲取數據:

```

jsonpInfo() { // JSONP形式從服務器獲取數據

? var url = 'http://127.0.0.1:8899/api/jsonp';

? this.$http.jsonp(url).then(res => {

? ? console.log(res.body);

? });

}

```

## 配置本地數據庫和數據接口API

1. 先解壓安裝 `PHPStudy`;

2. 解壓安裝 `Navicat` 這個數據庫可視化工具,并激活;

3. 打開 `Navicat` 工具,新建空白數據庫,名為 `dtcmsdb4`;

4. 雙擊新建的數據庫,連接上這個空白數據庫,在新建的數據庫上`右鍵` -> `運行SQL文件`,選擇并執行 `dtcmsdb4.sql` 這個數據庫腳本文件;如果執行不報錯,則數據庫導入完成;

5. 進入文件夾 `vuecms3_nodejsapi` 內部,執行 `npm i` 安裝所有的依賴項;

6. 先確保本機安裝了 `nodemon`, 沒有安裝,則運行 `npm i nodemon -g` 進行全局安裝,安裝完畢后,進入到 `vuecms3_nodejsapi`目錄 -> `src`目錄 -> 雙擊運行 `start.bat`

7. 如果API啟動失敗,請檢查 PHPStudy 是否正常開啟,同時,檢查 `app.js` 中第 `14行` 中數據庫連接配置字符串是否正確;PHPStudy 中默認的 用戶名是root,默認的密碼也是root


## [Vue中的動畫](https://cn.vuejs.org/v2/guide/transitions.html)

為什么要有動畫:動畫能夠提高用戶的體驗,幫助用戶更好的理解頁面中的功能;

### 使用過渡類名

1. HTML結構:

```

<div id="app">

? ? <input type="button" value="動起來" @click="myAnimate">

? ? <!-- 使用 transition 將需要過渡的元素包裹起來 -->

? ? <transition name="fade">

? ? ? <div v-show="isshow">動畫哦</div>

? ? </transition>

? </div>

```

2. VM 實例:

```

// 創建 Vue 實例,得到 ViewModel

var vm = new Vue({

? el: '#app',

? data: {

? ? isshow: false

? },

? methods: {

? ? myAnimate() {

? ? ? this.isshow = !this.isshow;

? ? }

? }

});

```

3. 定義兩組類樣式:

```

/* 定義進入和離開時候的過渡狀態 */

? ? .fade-enter-active,

? ? .fade-leave-active {

? ? ? transition: all 0.2s ease;

? ? ? position: absolute;

? ? }

? ? /* 定義進入過渡的開始狀態 和 離開過渡的結束狀態 */

? ? .fade-enter,

? ? .fade-leave-to {

? ? ? opacity: 0;

? ? ? transform: translateX(100px);

? ? }

```

### [使用第三方 CSS 動畫庫](https://cn.vuejs.org/v2/guide/transitions.html#自定義過渡類名)

1. 導入動畫類庫:

```

<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">動畫哦</div>

</transition>

```

### 使用動畫鉤子函數

1. 定義 transition 組件以及三個鉤子函數:

```

<div id="app">

? ? <input type="button" value="切換動畫" @click="isshow = !isshow">

? ? <transition

? ? @before-enter="beforeEnter"

? ? @enter="enter"

? ? @after-enter="afterEnter">

? ? ? <div v-if="isshow" class="show">OK</div>

? ? </transition>

? </div>

```

2. 定義三個 methods 鉤子方法:

```

methods: {

? ? ? ? beforeEnter(el) { // 動畫進入之前的回調

? ? ? ? ? el.style.transform = 'translateX(500px)';

? ? ? ? },

? ? ? ? enter(el, done) { // 動畫進入完成時候的回調

? ? ? ? ? el.offsetWidth;

? ? ? ? ? el.style.transform = 'translateX(0px)';

? ? ? ? ? done();

? ? ? ? },

? ? ? ? afterEnter(el) { // 動畫進入完成之后的回調

? ? ? ? ? this.isshow = !this.isshow;

? ? ? ? }

? ? ? }

```

3. 定義動畫過渡時長和樣式:

```

.show{

? ? ? transition: all 0.4s ease;

? ? }

```

### [v-for 的列表過渡](https://cn.vuejs.org/v2/guide/transitions.html#列表的進入和離開過渡)

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結構,其中,需要使用 transition-group 組件把v-for循環的列表包裹起來:

```

? <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中的結構:

```

? ? // 創建 Vue 實例,得到 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>` 組件還有一個特殊之處。不僅可以進入和離開動畫,**還可以改變定位**。要使用這個新功能只需了解新增的 `v-move` 特性,**它會在元素的改變定位的過程中應用**。

+ `v-move` 和 `v-leave-active` 結合使用,能夠讓列表的過渡更加平緩柔和:

```

.v-move{

? transition: all 0.8s ease;

}

.v-leave-active{

? position: absolute;

}

```

## 相關文章

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 里面的鍵盤事件對應的鍵碼](http://www.cnblogs.com/wuhua1/p/6686237.html)

5. [pagekit/vue-resource](https://github.com/pagekit/vue-resource)

6. [navicat如何導入sql文件和導出sql文件](https://jingyan.baidu.com/article/a65957f4976aad24e67f9b9b.html)

7. [貝塞爾在線生成器](http://cubic-bezier.com/#.4,-0.3,1,.33)


## 定義Vue組件

什么是組件: 組件的出現,就是為了拆分Vue實例的代碼量的,能夠讓我們以不同的組件,來劃分不同的功能模塊,將來我們需要什么樣的功能,就可以去調用對應的組件即可;

組件化和模塊化的不同:

+ 模塊化: 是從代碼邏輯的角度進行劃分的;方便代碼分層開發,保證每個功能模塊的職能單一;

+ 組件化: 是從UI界面的角度進行劃分的;前端的組件化,方便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標簽種:

```

<script id="tmpl" type="x-template">

? ? ? <div><a href="#">登錄</a> | <a href="#">注冊</a></div>

? ? </script>

```

同時,需要使用 Vue.component 來定義組件:

```

Vue.component('account', {

? ? ? template: '#tmpl'

? ? });

```

> 注意: 組件中的DOM結構,有且只能有唯一的根元素(Root Element)來進行包裹!

### 組件中展示數據和響應事件

1. 在組件中,`data`需要被定義為一個方法,例如:

```

Vue.component('account', {

? ? ? template: '#tmpl',

? ? ? data() {

? ? ? ? return {

? ? ? ? ? msg: '大家好!'

? ? ? ? }

? ? ? },

? ? ? methods:{

? ? ? ? login(){

? ? ? ? ? alert('點擊了登錄按鈕');

? ? ? ? }

? ? ? }

? ? });

```

2. 在子組件中,如果將模板字符串,定義到了script標簽中,那么,要訪問子組件身上的`data`屬性中的值,需要使用`this`來訪問;

### 【重點】為什么組件中的data屬性必須定義為一個方法并返回一個對象

1. 通過計數器案例演示

### 使用`components`屬性定義局部子組件

1. 組件實例定義方式:

```

<script>

? ? // 創建 Vue 實例,得到 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`標識符結合`v-if`和`v-else`切換組件

1. 頁面結構:

```

<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實例定義:

```

<script>

? ? Vue.component('myCom1', {

? ? ? template: '<h3>奔波霸</h3>'

? ? })

? ? Vue.component('myCom2', {

? ? ? template: '<h3>霸波奔</h3>'

? ? })

? ? // 創建 Vue 實例,得到 ViewModel

? ? var vm = new Vue({

? ? ? el: '#app',

? ? ? data: {

? ? ? ? flag: true

? ? ? },

? ? ? methods: {}

? ? });

? </script>

```

## 使用`:is`屬性來切換不同的子組件,并添加切換動畫

1. 組件實例定義方式:

```

? // 登錄組件

? ? 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);

? ? // 創建 Vue 實例,得到 ViewModel

? ? var vm = new Vue({

? ? ? el: '#app',

? ? ? data: { comName: 'login' },

? ? ? methods: {}

? ? });

```

2. 使用`component`標簽,來引用組件,并通過`: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. 組件實例定義方式,注意:一定要使用`props`屬性來定義父組件傳遞過來的數據

```

<script>

? ? // 創建 Vue 實例,得到 ViewModel

? ? var vm = new Vue({

? ? ? el: '#app',

? ? ? data: {

? ? ? ? msg: '這是父組件中的消息'

? ? ? },

? ? ? components: {

? ? ? ? son: {

? ? ? ? ? template: '<h1>這是子組件 --- {{finfo}}</h1>',

? ? ? ? ? props: ['finfo']

? ? ? ? }

? ? ? }

? ? });

? </script>

```

2. 使用`v-bind`或簡化指令,將數據傳遞到子組件中:

```

<div id="app">

? ? <son :finfo="msg"></son>

? </div>

```

## 子組件向父組件傳值

1. 原理:父組件將方法的引用,傳遞到子組件內部,子組件在內部調用父組件傳遞過來的方法,同時把要發送給父組件的數據,在調用方法的時候當作參數傳遞進去;

2. 父組件將方法的引用傳遞給子組件,其中,`getMsg`是父組件中`methods`中定義的方法名稱,`func`是子組件調用傳遞過來方法時候的方法名稱

```

<son @func="getMsg"></son>

```

3. 子組件內部通過`this.$emit('方法名', 要傳遞的數據)`方式,來調用父組件中的方法,同時把數據傳遞給父組件使用

```

<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() { // 按鈕的點擊事件

? ? ? ? ? this.$emit('func', 'OK'); // 調用父組件傳遞過來的方法,同時把數據傳遞出去

? ? ? ? }

? ? ? }

? ? });

? ? // 創建 Vue 實例,得到 ViewModel

? ? var vm = new Vue({

? ? ? el: '#app',

? ? ? data: {},

? ? ? methods: {

? ? ? ? getMsg(val){ // 子組件中,通過 this.$emit() 實際調用的方法,在此進行定義

? ? ? ? ? alert(val);

? ? ? ? }

? ? ? }

? ? });

? </script>

```

## 評論列表案例

目標:主要練習父子組件之間傳值

## 使用 `this.$refs` 來獲取元素和組件

```

? <div id="app">

? ? <div>

? ? ? <input type="button" value="獲取元素內容" @click="getElement" />

? ? ? <!-- 使用 ref 獲取元素 -->

? ? ? <h1 ref="myh1">這是一個大大的H1</h1>

? ? ? <hr>

? ? ? <!-- 使用 ref 獲取子組件 -->

? ? ? <my-com ref="mycom"></my-com>

? ? </div>

? </div>

? <script>

? ? Vue.component('my-com', {

? ? ? template: '<h5>這是一個子組件</h5>',

? ? ? data() {

? ? ? ? return {

? ? ? ? ? name: '子組件'

? ? ? ? }

? ? ? }

? ? });

? ? // 創建 Vue 實例,得到 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. 對于普通的網站,所有的超鏈接都是URL地址,所有的URL地址都對應服務器上對應的資源;

2. 對于單頁面應用程序來說,主要通過URL中的hash(#號)來實現不同頁面之間的切換,同時,hash有一個特點:HTTP請求中不會包含hash相關的內容;所以,單頁面程序中的頁面跳轉主要用hash實現;

3. 在單頁面應用程序中,這種通過hash改變來切換頁面的方式,稱作前端路由(區別于后端路由);

## 在 vue 中使用 vue-router

1. 導入 vue-router 組件類庫:

```

<!-- 1. 導入 vue-router 組件類庫 -->

? <script src="./lib/vue-router-2.7.0.js"></script>

```

2. 使用 router-link 組件來導航

```

<!-- 2. 使用 router-link 組件來導航 -->

<router-link to="/login">登錄</router-link>

<router-link to="/register">注冊</router-link>

```

3. 使用 router-view 組件來顯示匹配到的組件

```

<!-- 3. 使用 router-view 組件來顯示匹配到的組件 -->

<router-view></router-view>

```

4. 創建使用`Vue.extend`創建組件

```

? ? // 4.1 使用 Vue.extend 來創建登錄組件

? ? var login = Vue.extend({

? ? ? template: '<h1>登錄組件</h1>'

? ? });

? ? // 4.2 使用 Vue.extend 來創建注冊組件

? ? var register = Vue.extend({

? ? ? template: '<h1>注冊組件</h1>'

? ? });

```

5. 創建一個路由 router 實例,通過 routers 屬性來定義路由匹配規則

```

// 5. 創建一個路由 router 實例,通過 routers 屬性來定義路由匹配規則

? ? var router = new VueRouter({

? ? ? routes: [

? ? ? ? { path: '/login', component: login },

? ? ? ? { path: '/register', component: register }

? ? ? ]

? ? });

```

6. 使用 router 屬性來使用路由規則

```

// 6. 創建 Vue 實例,得到 ViewModel

? ? var vm = new Vue({

? ? ? el: '#app',

? ? ? router: router // 使用 router 屬性來使用路由規則

? ? });

```

## 設置路由高亮

## 設置路由切換動效

## 在路由規則中定義參數

1. 在規則中定義參數:

```

{ path: '/register/:id', component: register }

```

2. 通過 `this.$route.params`來獲取路由中的參數:

```

var register = Vue.extend({

? ? ? template: '<h1>注冊組件 --- {{this.$route.params.id}}</h1>'

? ? });

```

## 使用 `children` 屬性實現路由嵌套

```

? <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>'

? ? });

? ? // 路由實例

? ? var router = new VueRouter({

? ? ? routes: [

? ? ? ? { path: '/', redirect: '/account/login' }, // 使用 redirect 實現路由重定向

? ? ? ? {

? ? ? ? ? path: '/account',

? ? ? ? ? component: account,

? ? ? ? ? children: [ // 通過 children 數組屬性,來實現路由的嵌套

? ? ? ? ? ? { path: 'login', component: login }, // 注意,子路由的開頭位置,不要加 / 路徑符

? ? ? ? ? ? { path: 'register', component: register }

? ? ? ? ? ]

? ? ? ? }

? ? ? ]

? ? });

? ? // 創建 Vue 實例,得到 ViewModel

? ? var vm = new Vue({

? ? ? el: '#app',

? ? ? data: {},

? ? ? methods: {},

? ? ? components: {

? ? ? ? account

? ? ? },

? ? ? router: router

? ? });

? </script>

```

## 命名視圖實現經典布局

1. 標簽代碼結構:

```

<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>'

? ? });

? ? // 創建路由對象

? ? var router = new VueRouter({

? ? ? routes: [

? ? ? ? {

? ? ? ? ? path: '/', components: {

? ? ? ? ? ? default: header,

? ? ? ? ? ? a: sidebar,

? ? ? ? ? ? b: mainbox

? ? ? ? ? }

? ? ? ? }

? ? ? ]

? ? });

? ? // 創建 Vue 實例,得到 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`屬性的使用

考慮一個問題:想要實現 `名` 和 `姓` 兩個文本框的內容改變,則全名的文本框中的值也跟著改變;(用以前的知識如何實現???)

1. 監聽`data`中屬性的改變:

```

<div id="app">

? ? <input type="text" v-model="firstName"> +

? ? <input type="text" v-model="lastName"> =

? ? <span>{{fullName}}</span>

? </div>

? <script>

? ? // 創建 Vue 實例,得到 ViewModel

? ? var vm = new Vue({

? ? ? el: '#app',

? ? ? data: {

? ? ? ? firstName: 'jack',

? ? ? ? lastName: 'chen',

? ? ? ? fullName: 'jack - chen'

? ? ? },

? ? ? methods: {},

? ? ? watch: {

? ? ? ? 'firstName': function (newVal, oldVal) { // 第一個參數是新數據,第二個參數是舊數據

? ? ? ? ? this.fullName = newVal + ' - ' + this.lastName;

? ? ? ? },

? ? ? ? 'lastName': function (newVal, oldVal) {

? ? ? ? ? this.fullName = this.firstName + ' - ' + newVal;

? ? ? ? }

? ? ? }

? ? });

? </script>

```

2. 監聽路由對象的改變:

```

<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 }

? ? ? ]

? ? });

? ? // 創建 Vue 實例,得到 ViewModel

? ? var vm = new Vue({

? ? ? el: '#app',

? ? ? data: {},

? ? ? methods: {},

? ? ? router: router,

? ? ? watch: {

? ? ? ? '$route': function (newVal, oldVal) {

? ? ? ? ? if (newVal.path === '/login') {

? ? ? ? ? ? console.log('這是登錄組件');

? ? ? ? ? }

? ? ? ? }

? ? ? }

? ? });

? </script>

```

## `computed`計算屬性的使用

1. 默認只有`getter`的計算屬性:

```

<div id="app">

? ? <input type="text" v-model="firstName"> +

? ? <input type="text" v-model="lastName"> =

? ? <span>{{fullName}}</span>

? </div>

? <script>

? ? // 創建 Vue 實例,得到 ViewModel

? ? var vm = new Vue({

? ? ? el: '#app',

? ? ? data: {

? ? ? ? firstName: 'jack',

? ? ? ? lastName: 'chen'

? ? ? },

? ? ? methods: {},

? ? ? computed: { // 計算屬性; 特點:當計算屬性中所以來的任何一個 data 屬性改變之后,都會重新觸發 本計算屬性 的重新計算,從而更新 fullName 的值

? ? ? ? fullName() {

? ? ? ? ? return this.firstName + ' - ' + this.lastName;

? ? ? ? }

? ? ? }

? ? });

? </script>

```

2. 定義有`getter`和`setter`的計算屬性:

```

<div id="app">

? ? <input type="text" v-model="firstName">

? ? <input type="text" v-model="lastName">

? ? <!-- 點擊按鈕重新為 計算屬性 fullName 賦值 -->

? ? <input type="button" value="修改fullName" @click="changeName">

? ? <span>{{fullName}}</span>

? </div>

? <script>

? ? // 創建 Vue 實例,得到 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`屬性的結果會被緩存,除非依賴的響應式屬性變化才會重新計算。主要當作屬性來使用;

2. `methods`方法表示一個具體的操作,主要書寫業務邏輯;

3. `watch`一個對象,鍵是需要觀察的表達式,值是對應回調函數。主要用來監聽某些特定數據的變化,從而進行某些具體的業務邏輯操作;可以看作是`computed`和`methods`的結合體;

## `nrm`的安裝使用

作用:提供了一些最常用的NPM包鏡像地址,能夠讓我們快速的切換安裝包時候的服務器地址;

什么是鏡像:原來包剛一開始是只存在于國外的NPM服務器,但是由于網絡原因,經常訪問不到,這時候,我們可以在國內,創建一個和官網完全一樣的NPM服務器,只不過,數據都是從人家那里拿過來的,除此之外,使用方式完全一樣;

1. 運行`npm i nrm -g`全局安裝`nrm`包;

2. 使用`nrm ls`查看當前所有可用的鏡像源地址以及當前所使用的鏡像源地址;

3. 使用`nrm use npm`或`nrm use taobao`切換不同的鏡像源地址;

## 相關文件

1. [URL中的hash(井號)](http://www.cnblogs.com/joyho/articles/4430148.html)




Data多實例共享問題:

app.vue文件我們可以分成三部分解讀,

<template></template>標簽包裹的內容:這是模板的HTMLDom結構,里邊引入了一張圖片和<router-view></router-view>標簽,<router-view>標簽說明使用了路由機制。我們會在以后專門拿出一篇文章講Vue-router。

<script></script>標簽包括的js內容:你可以在這里些一些頁面的動態效果和Vue的邏輯代碼。

<style></style>標簽包裹的css內容:這里就是你平時寫的CSS樣式,對頁面樣子進行裝飾用的,需要特別說明的是你可以用<style scoped></style>來聲明這些css樣式只在本模板中起作用。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,527評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,687評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,640評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,957評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,682評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,011評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,009評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,183評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,714評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,435評論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,665評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,148評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,838評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,251評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,588評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,379評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,627評論 2 380

推薦閱讀更多精彩內容