前言:css
1、優勢:html
輕量級、高效率、上手快、簡單易學、文檔全面而簡潔前端
2、功能:vue
一、模板渲染jquery
二、模塊化webpack
三、擴展功能:路由、Ajaxgit
3、課程包含:es6
一、Vue實例github
二、Vue組件web
三、Vue指令
四、內置組件
五、實例方法
六、實例選項
七、實例屬性
八、模板渲染
九、條件渲染
十、組件交互
十一、標籤屬性
十二、事件綁定
1三、計算屬性
1四、屬性監聽
1五、表單
1六、動畫
1七、vue-cli項目搭建
1八、Vue-router理由:實現單頁面切換
1九、vuex
4、vue.js簡介
一、輕量級的前端界面框架
二、2016.10發佈最新2.0版本,更強大,更快速
三、主要包括:
a) 數據渲染/數據同步
b) 組件化/模塊化
c) 其餘功能:路由、ajax、數據流
5、Vue.js學習資源
6、Vue.js的特色
一、雙向數據綁定
二、組件化/模塊化
三、單文件組件 - js、css、html存在於一個.vue文件內
經過什麼實現呢?
a) webpack+vue-loader
b) Browserify+vueify
單文件組件的優勢:
a) 能夠在一個文件裏編輯html、css和js
b) <style scoped></style>樣式上的scoped屬性規定了該樣式的做用域,防止污染到其餘組件
c) 能夠定義語言,如:<template lang=」jade」></template> 預加載器
<style lang=」less」></style> 預處理器
d) 可使用webpack打包工具,利用它的功能
7、Vue.js的實例對象
一、概念:當項目引入vue.js後,在全局裏會有個js的vue的類,經過vue類來實例化的對象就是vue實例對象。經過關鍵字new Vue()實例。
二、選項
(1)el - 決定該vue實例裝載到頁面的什麼位置
(2)模板template - 裝載的東西,是指包含指令或html的一個片斷
如:template: ‘<div><other-component></div>’
(3)數據data - data中的數據會被代理到實例對象裏
如:data: {
fruit: ‘apple’
}
能夠經過vm.fruit訪問代理到的內容
也能夠將data中的數據渲染到template中,如:
template: ‘<div>{{ fruit }}</div>’
(4)組件component - 引入其餘子組件
如:component: {App}
三、實際項目中如何使用組件和組件間如何引入
(1)一般一個項目裏,咱們能夠在main.js或入口的js中首先實例化一個根組件,把這個根組件掛載到某個容器中,而後引入第一個子組件App,固然App中也會有其餘的組件,好比header、sidebar、footer等,咱們的每一個頁面也是以一樣的方式引入到App這樣的組件裏,而後一層層樹狀結構,造成一個組件樹。
四、生命週期
(1)Vue的一個組件或者vue的一個實例化對象在不一樣的階段,vue.js提供了不一樣的鉤子,咱們經過這些鉤子在特定的階段執行特定的操做。
(2)鉤子函數包括:
a) beforeCreate -- 實例剛剛建立的時候
b) Created -- 初始化完成這樣的一個事件
c) beforeMount -- 渲染的時候
d) Mounted -- 渲染完畢
e) beforeDestory & destoryed -- 調用摧毀方法
8、Vue.js的組件
一、如何實現vue.js的根組件及組件之間的相互關係?
(1)經過vue的腳手架工具生成項目
(2)在main.js中經過es6語法引入vue的一個庫並賦予Vue這個變量:
import Vue from ‘vue’;
‘vue’ -- vue庫或模塊
Vue -- 變量
(3)實例化根組件並進行數據渲染
先關注main.js和index.html:
在main.js中 import Vue from 'vue' (ES6知識點:P272 import導入模塊) /* eslint-disable no-new */ new Vue({ el: '#app', template: '<p>hello world {{ word }}</p>', data: { word: 'hello world' } })
(4)Vue是自底向上增量開發
(5)組件註冊與引入 -- 實現組件樹
經過Vue.component(‘組件名’, {組件對象,含有參數template})方法註冊全局組件,此處的組件對象至關於new Vue方法,涉及到一個「語法糖」功能。
a) 註冊全局組件
js:
Vue.component('my-header', {
template: '<p>this is my header</p>'
})
html:
<div id="app">
<my-header></my-header>
</div>
b) 註冊局部組件、子孫組件構成組件樹
js: // 孫組件
var myHeaderChild = { template: '<p>this is my header child</p>' } // 子組件
var myHeader = { template: '<p><my-header-child></my-header-child>this is my header</p>', components: { 'my-header-child': myHeaderChild } } new Vue({ el: '#app', data: { word: 'hello world' }, components: { 'my-header': myHeader } }) html: <div id="app"> <my-header></my-header> </div>
局部組件my-header只能在#app中使用。
PS: 實際項目中在components文件夾中存放組件,跟它同級的App.vue引入不一樣的component,在導出pages的時候使用components來引入其它component就很是清晰.
c) 避免data引用賦值
若是直接給組件的data賦一些值,這樣作若是有多個組件用到這個data,其中一個經過事件改變data後,另外一些組件中的data也會發生改變,採用return方法返回所須要的數據可避免這種狀況。
var myHeader = {
template: '<p><my-header-child></my-header-child>this is my header</p>', components: { 'my-header-child': myHeaderChild }, data () { (ES6知識點:P90方法簡寫) return { f1: 0, f2: 2 } } }
9、Vue的基本概念
一、全局api -- vue的實例對象提供的全局方法
(1)Vue.extend(options) -- 用於擴展vue的構造器
(2)Vue.set(object, key, value) -- 是給全局vue設置屬性的一個方法
(3)Vue.component(id, [definition]) -- 添加全局組件
(4)Vue.use(plugin) -- 經過它來註冊相似vue router、vuex之類的插件
二、實例選項
(1)Data--與數據相關:
a) data
b) computed -- 計算屬性值
c) props
d) methods
e) watch
(2)與DOM相關的:
a) el
b) template
c) render -- 方法
(3)Lifecycle Hooks -- 生命週期的鉤子
(4)Assets
a) directives -- 輸入指令
b) filters -- 過濾器
c) components
(5)Misc -- 合集的一些選項
a) extends
b) functional
三、實例屬性/方法 -- 以$開頭,直接從實例對象調用
root.$data/ root.$on var root = new Vue({ el: '#app', data: { word: 'hello world' }, components: { 'my-header': myHeader } })
// 屬性&方法
console.log(root.$data) root.$on('emit', function () { alert(1) })
四、指令 -- 寫在模板裏,經過模板與組件的數據進行交互的方法,有時這個指令還包含參數,如v-on:事件
(1)v-html -- 將數據渲染到元素內部
與v-text的區別:前者渲染出的是DOM元素,後者渲染成字符串文本
{{msg}} 與v-text相似,雙花括號裏能夠是一元js表達式
<template>
<div>
<p v-text="hello"></p>
<p v-html="hello"></p>
{{ hello }}
{{ status ? 'success' : 'fail' }}
</div>
</template>
<script>
export default {
data () {
return {
hello: '<span>world</span>',
status: true
}
}
}
</script>
(2)v-on:事件 縮寫@:事件
有時會與修飾器「.」結合 構成v-on:參數.修飾器
var myHeader = { template: '<p v-html="" v-on:click="" v-on:keydown.enter=""><my-header-child></my-header-child>this is my header</p>', components: { 'my-header-child': myHeaderChild }, data () { return { f1: 0, f2: 2 } } }
經常使用的修飾器有:
a) .stop 阻止冒泡
b) .prevent
c) .capture
d) .self
e) .{keyCode | keyAlias} -- 如:.enter
f) .native
(3)v-if
(4)v-for -- (詳細介紹參見第三章第二項)
五、內置組件 -- 不是本身註冊的,而是vue自帶的組件
(1)<component></component> 它身上包含:is方法,經過此方法將變量傳進去來指定這個組件是個什麼樣的組件。
(2)<router-view></router-view> 是路由提供的內置組件
(3)<keep-alive></keep-alive> 能夠經過它來將上面的router組件進行緩存,即在進行切換的時候,router-view裏的內容只要被訪問過的就會被緩存起來。
var myHeader = { template: '<p v-html="" v-on:click="" v-on:keydown.enter=""> <component :is=""></component> this is my header</p> <keep-alive><router-view></router-view></keep-alive>', components: { 'my-header-child': myHeaderChild }, data () { return { f1: 0, f2: 2 } } }
(4)<transition></transition> 動畫組件
第三章
1、基本結構
一、在index.html中寫下div,並賦予id
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>vue2.0</title> </head> <body> <div id="app"></div> </body> </html>
二、在main.js中經過import引入vue模塊(每一個項目必引)和相應的組件模塊如App.vue
import Vue from 'vue' import App from './App' /* eslint-disable no-new */ new Vue({ el: '#app', render: h => h(App) (ES6知識點:P69 箭頭函數) })
三、在App.vue中定義template、script、style三部分,在script中使用export導出要顯示的頁面
<template> <div> {{ hello }} </div> </template> <script> export default { data () { return { hello: 'world' } } } </script> <style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>
2、列表渲染v-for 數組、對象、子組件
一、v-for指令實現列表循環 -- 數組形式
<template> <div> <ul> <li v-for="item in lists">{{item.name}}的價格是{{item.price}}元</li> 或採用v-text指令: <li v-for="item in lists" v-text="item.name + '---' + item.price"></li> </ul> </div> </template> <script> export default { data () { return { lists: [ { name: 'apple', price: 34 }, { name: 'banana', price: 56 } ] } } } </script>
須要注意的是,v-for指令應加在要循環的那一項上面,而不是它的父級。
此外,也能夠聲明每一項的index
<li v-for="(item, index) in lists" :class="{odd: index % 2}">{{ index }}-{{ item.name }}的價格是{{ item.price }}元</li>
注:此處的:class的值若是是對象,必定別忘記寫花括號。
二、v-for指令實現列表循環 -- 對象形式
<template> <div> <ul> <!-- <li v-for="value in listObj">{{ value }}</li> --> 或: <li v-for="(value, key) in listObj">{{ key + value}}</li> </ul> </div> </template> <script> export default { data () { return { listObj: { name: 'apple', price: 34, weight: '100g' } } } } </script>
注:這裏的v-for指令中必須用key、value in obj,與數組的item(不是定死的)和index in arr相對應。
三、組件之間的相互引用及列表循環之子組件間的渲染
(1)組件間的相互引用
第一步:在script中的export前先把組件引進來
<script> import componentA from './components/a' export default {} </script>
注:此處的componentA表明這個a.vue,在其餘組件中直接用<componentA></componentA>
第二步:註冊 -- 經過components選項註冊到當前組件裏
export default { components: {componentA}, (ES6知識點:P90屬性簡寫) data () { return { } } }
第三步:使用、渲染 -- 將組件componentA的template渲染到當前的組件的template中
<template> <div> <component-a></component-a> </div> </template>
(2)列表循環之子組件間的渲染
只須要在template中的componetA組件上添加v-for指令便可:
<componentA v-for="(value, key) in listObj" :key="key"></componentA>
組件渲染的意義:
能夠動態的將父組件的數據傳給子組件componentA,如上例中經過綁定屬性key,而後子組件a.vue中能夠拿到傳過來的值進行使用。
3、列表數據的同步更新方法
一、methods
<template>
<div>
<ul>
<li v-for="item in list">{{ item.name }} -- {{item.price}}</li>
</ul>
<button @click="addItem">addItem</button>
</div>
</template>
<script>
export default {
data () {
return {
list: [
{
name: 'apple',
price: 34
},
{
name: 'banana',
price: 56
}
]
}
},
methods: {
addItem () {
this.list.push({name: 'pineapple', price: 78})
}
}
}
</script>
PS:此處的邏輯是點擊按鈕,向列表中添加一項。
數組中並非全部的方法都能觸發列表的更新,下面的這些方法能夠觸發:
push() 在後面添加一項
pop() 從後面刪除一項
shift() 在前面添加一項
unshift() 從前面刪除一項
splice() 刪除或替換一項
sort() 排序
reverse() 反轉
這些方法或情形不會觸發列表更新:
filter() 過濾
concat() 拼接數組
slice() 切割數組
兩種情形:
(1)直接爲其中某一項賦值,如vm.items[indexOfItem] = newValue
因此下例這種狀況不生效:
methods: {
addItem () {
this.list[1] = {
name: 'pineapple',
price: 78
}
}
}
若是硬要改變第1項實現列表數據更新,就要藉助Vue.set()方法:
methods: {
addItem () {
Vue.set(this.list, 1, {
name: 'pineapple',
price: 78
})}
}
其中第一個參數是數組自己,第二個是要被改變的那項的index,第三項是改變成什麼。
PS:但在使用Vue的set方法前,須要在該組件中引入Vue組件,不然會報錯
<script>
import Vue from 'Vue'
export ...
</script>
(2)改變數組的長度,如vm.items.length = newLength
4、vue標籤屬性和條件渲染
一、經過v-bind:參數名 = 「數據」 進行動態綁定標籤屬性,當數據被修改後,該屬性對應的數據在頁面也會同步更新。
<template>
<div>
<a :href="link" :title="hello">to baidu</a>
<componentA :dataA = "dataA"></componentA>
</div>
</template>
<script>
export default {
data () {
return {
hello: 'world',
link: 'http://www.baidu.com',
dataA: 112
}
}
}
</script>
PS:1)使用v-bind綁定的是個變量,不使用v-bind綁定的屬性就只是個字符串。
如:
<a class="link-href" :class="classStr">to baidu</a>
這裏的兩個class不會衝突。
:class延伸:class屬性的幾種添加方式
a) 字符串形式:如上例
b) 對象形式:若是class綁定的是一個對象,就能夠根據對象的值進行判斷是否展現該對象的屬性做爲class。如:
<a class="link-href" :class="classObj">點我啊</a>
data () {
return {
classObj: {
'red-font': true,
'blue-font': false
}
}
}
c) 數組形式:
<a class="link-href" :class="classArr">再點我啊</a>
data () {
return {
classArr: ['red-font', 'blue-font']
}
}
PS:以上三種形式均可以直接寫到行間。
d) 數組、對象混用
<a class="link-href" :class="[classA, {'red-font': hasError}]">第三次點擊</a>
data () {
return {
classA: 'blue-font',
hasError: true
}
}
也能夠經過:style內聯樣式將樣式展現到便籤上:
<a :style="styleCss">測試內聯樣式</a>
data () {
return {
styleCss: {
color: 'red',
'font-size': '30px'
}
}
}
這時,能夠在js中如methods中對this.styleCss進行操做來改變a標籤的樣式。
2) 若是v-bind屬性綁定到子組件標籤componentA上,那麼在子組件內部a.vue中也可使用該屬性。
二、條件渲染之v-if、v-show
<template>
<p v-if="isPartA">partA</p>
<p v-show="!isPartA">partB</p>
<button @click="toggle">toggle</button>
</template>
<script>
export default {
data () {
return {
isPartA: false
}
},
methods: {
toggle () {
this.isPartA = !this.isPartA
}
}
}
</script>
PS:v-if和v-show的區別:
v-if在DOM元素中不存在,使用v-show時元素存在,只是加了個display=」none」
兩者均可以配合v-else指令使用:
<p v-if="isPartA">partA</p>
<p v-else>no data</p>
5、事件綁定
一、基本/內置的事件綁定經過v-on:參數或縮寫@:綁定,有時後會用到修飾符「.」
二、自定義事件綁定
流程描述:在子組件中經過點擊觸發了本身的方法,這個方法$emit發出一個自定義事件(可帶參數),父組件監聽這個自定義事件,並觸發父組件本身的一個方法,這個方法就是要處理的結果,方法中傳遞參數,可訪問到子組件中$emit發出的那個參數。
父組件App.vue中:
<template>
<comA @my-event="onComaMyEvent"></comA>
</template>
<script>
import comA from './components/a'
export default {
components: {comA},
data () {
return {
}
},
methods: {
onComaMyEvent (paramFromA) {
console.log('onComaMyEvent' + paramFromA)
}
}
}
</script>
子組件a.vue中:
<template>
<button @click="emitMyEvent">emit</button></template>
<script>
export default {
data () {
return {
hello: 'I am a component A!'
}
},
methods: {
emitMyEvent () {
this.$emit('my-event', this.hello)
}
}
}
</script>
三、表單事件綁定 -- 雙向數據綁定(v-model)
(1)普通的input框
<template>
<input type="text" v-model="myValue">
<p>{{ myValue }}</p>
</template>
<script>
export default {
data () {
return {
myValue: ''
}
}
}
</script>
(2)複選框
<template>
<input v-model="myBox" type="checkbox" value="apple">
<input v-model="myBox" type="checkbox" value="banana">
<input v-model="myBox" type="checkbox" value="pineapple">
<p>{{ myBox }}</p>
</template>
<script>
export default {
data () {
return {
myBox: []
}
}
}
</script>
(3)單選框
<template>
<input v-model="myRadio" type="radio" value="apple">
<input v-model="myRadio" type="radio" value="banana">
<input v-model="myRadio" type="radio" value="pineapple">
<p>{{ myRadio }}</p>
</template>
<script>
export default {
data () {
return {
myRadio: ''
}
}
}
</script>
四、下拉框
<template>
<select name="" id="" v-model="selection">
<option value="apple">apple</option>
<option value="banana">banana</option>
<option value="pineapple">pineapple</option>
</select>
<p>{{ selection }}</p>
</template>
<script>
export default {
data () {
return {
selection: null
}
}
}
</script>
PS:上述的option能夠經過v-for循環渲染
select標籤及指令不變,只在option上v-for循環便可:
<option v-for="item in selectObj" :value="item.id">{{ item.text}}</option>
<script>
export default {
data () {
return {
selection: null,
selectObj: [
{id: 0, text: 'apple'},
{id: 1, text: 'pineapple'},
{id: 2, text: 'banana'}
]
}
}
}
</script>
另外,也能夠把select抽成組件如vSelect,上面也能夠綁定自定義事件,並經過操做自定義事件和$emit來實現父子組件之間的通訊。
五、v-model.lazy 懶加載
當輸入框輸完失去焦點後才進行雙向數據綁定。
六、v-model.number轉換數據類型 由string轉爲number
注意:字母和數字組合爲NaN,數據類型也是number
七、v-model.trim 裁剪空格,只是裁兩端空格
6、計算屬性computed和數據監聽watch
一、計算屬性computed是個vue選項,經過computed、經過一個方法來return一個值,這個值可使用data裏面的數據,經過this來引用。會被緩存。
<template>
<input type="text" v-model="myValue">
<p>{{ myValueWithoutNum }}</p>
</template>
<script>
export default {
data () {
return {
myValue: ''
}
},
computed: {
myValueWithoutNum () {
return this.myValue.replace(/\d/g, '')
}
}
}
</script>
PS:也能夠在methods經過方法myValueWithoutNum()來實現該功能。
兩者的區別:
計算屬性的更新只會根據另一個值如myValue進行更新,假如myValue再也不更新,那麼myValueWithNum也再也不更新。
而當咱們調用方法裏的myValueWithNum()時,不管什麼時候調用,都會從新獲取該myValue。
二、數據監聽watch
<template>
<ul>
<li v-for="item in myList">{{ item.text }}</li>
</ul>
<button @click="changeList">change</button></template>
<script>
import Vue from 'vue'
export default {
data () {
return {
myList: [
{text: 'apple'},
{text: 'banana'}
]
}
},
methods: {
changeList () {
Vue.set(this.myList, 1, {
text: 'pineapple'
})
},
tellUser () {
alert('will change!')
}
},
watch: {
myList () {
this.tellUser()
}
}
}
</script>
適用場景:對列表進行更改,能夠在watch裏進行監聽,只要更改就調用methods的某個方法。
第四章 深刻vue組件
I. 組件
1、組件基礎
一、組件名、屬性在template中最好把駝峯格式轉成中線格式。
二、能夠經過:is=」」方法在template中使用組件。
2、組件之間的通訊 -- 主要有三種:屬性、emit、slot插槽
父向子傳 用props,即標籤屬性
子向父傳 用emit,即經過去觸發一個事件,這個事件只有emit觸發和on監聽兩種方法
(1)父傳子之靜態屬性傳遞
父組件App.vue中:
<template>
<div>
<comp-a number-to-do = 78></comp-a>
</div>
</template>
<script>
import compA from './components/a'
export default {
components: {
compA
},
data () {
return {}
}
}
</script>
子組件a.vue中:
<template>
<div>
{{ hello }}
{{ numberToDo }}
</div>
</template>
<script>
export default {
props: ['number-to-do'],
data () {
return {
hello: 'I am a component A!'
}
}
}
</script>
PS:a) 注意以上三處加粗的代碼的名字轉換。
b) 在子組件中經過props接收父組件傳過來的數據,就至關於在本身的data中添加了該數據,在data中就沒必要從新定義。
c) props除了能夠接收數組外,還能夠接收對象,對象裏能夠定義接收的數據類型。
父組件中:
<comp-a number-to-do = 78></comp-a>
子組件中:
props: {
'number-to-do': [Number, String]
},
PS:父組件中的78無論加不加引號,都是String類型,若是子組件中props未指定該類型,就會報錯,指定了就不會。
(2)父傳子之動態屬性傳遞
父組件App.vue中:
<template>
<div>
<input type="text" v-model="myVal">
<comp-a :my-value="myVal"></comp-a>
</div>
</template>
<script>
import compA from './components/a'
export default {
components: {
compA
},
data () {
return {
myVal: ''
}
}
}
</script>
子組件a.vue中:
<template>
<div>
{{ hello }}
{{ myValue }}
</div>
</template>
<script>
export default {
props: {
'my-value': [Number, String]
},
data () {
return {
hello: 'I am a component A!'
}
}
}
</script>
PS:注意屬性如:my-value、事件如@my-event只能用中劃線,不能用駝峯方式。
(3)父傳子之插槽
若是父組件想向子組件插入一個模板標籤元素,要藉助<slot>標籤。
父組件App.vue中:
<template>
<div>
<comp-a :my-value="myVal">
<p>123</p>
</comp-a>
</div>
</template>
子組件a.vue中:
<template>
<div>
{{ hello }}
{{ myValue }}
<slot></slot>
</div>
</template>
PS:上例中就把父組件放到子組件標籤中的p標籤插到了子組件的slot位置。
1)插槽的便捷之處:
a) 經常使用場景:
好比子組件<comp-a>是個dialog,標籤裏能夠插入任何元素<p>、<span>之類的,這樣就能夠實現彈框內容不一樣了。
b) 好比子組件<comp-a>中沒有內容,能夠在插槽<slot>標籤中寫內容,就會被顯示,若子組件有內容,就只展現子組件的內容,而不展現插槽的。
2)關於具名slot -- 能夠知道不一樣部分的插入
父組件中:
<comp-a :my-value="myVal">
<p>123</p>
<p slot="header">xxx header</p>
<p slot="footer">yyy footer</p>
</comp-a>
子組件中:
<slot></slot>
<slot name="header">no header</slot>
balabala
<slot name="footer">no footer</slot>
(4)子傳父 使用emit和v-on:,參照第三章P16第五事件綁定。
3、動態組件
一、經過:is="變量如:currentView",將某個組件渲染到某個位置,咱們就能夠經過currentView來載入不一樣的組件到那個位置。
二、經常使用場景:
好比tab切換,tab切換下面會展示不一樣的小組件,這個小組件由一個組件切換成另外一個組件,因此咱們只要在切換的方法中更新currentView就會將組件同步更新到相應的位置。
三、動態組件有些相似路由,換句話說<router-view>就至關於一個動態組件。
跟路由類似,動態組件也支持<keep-alive>內置標籤,能夠緩存組件,提升組件的加載速度。
<template>
<keep-alive>
<p :is = "currentView"></p>
</keep-alive>
</template>
<script>
import comA from './components/a'
export default {
components: {comA},
data () {
return {
currentView: 'com-a'
}
}
}
</script>
PS:加粗的com-a就是子組件變量,該子組件必定要先import再註冊,不然就會報錯。
4、總結
II. Vue.js的高級功能
1、過渡/動畫
一、css實現過渡
css階段類名:
經過<transition>標籤與v-show或v-if指令以及style樣式配合,樣式中通常都是opacity/transform樣式:
(1)淡入淡出
<template>
<button @click="show = !show">toggle</button>
<div>
<transition name="fade">
<p v-show="show">this is toggle show</p>
</transition>
</div>
</template>
<script>
export default {
data () {
return {
show: true
}
}
}
</script>
<style>
.fade-enter,
.fade-leave-active {
opacity: 0;
}
.fade-enter-active,
.fade-leave-active {
transition: all .5s ease-out;
}
</style>
PS:style中的.fade-和<transition>標籤的name是對應的。
(2)自定義動畫,如位移
<template>
<button @click="show = !show">toggle</button>
<div>
<transition name="my-trans">
<p v-show="show">this is toggle show</p>
</transition>
</div>
</template>
<script>
同上
</script>
<style>
.my-trans-enter-active,
.my-trans-leave-active {
transition: all 1s ease-out;
}
.my-trans-enter {
transform: translateY(-500px);
opacity: 0;
}
.my-trans-leave-active {
transform: translateY(500px);
opacity: 0;
}
</style>
(3)接受的過渡狀態、多元素過渡
a) 方式一
<template>
<button @click="toggleCom">toggle</button>
<transition name="fade" mode="out-in">
<div :is="currentView"></div>
</transition>
</template>
<script>
import comA from './components/a'
import comB from './components/b'
export default {
components: {comA, comB},
data () {
return {
currentView: 'com-b'
}
},
methods: {
toggleCom () {
if (this.currentView === 'com-a') {
this.currentView = 'com-b'
} else {
this.currentView = 'com-a'
}
}
}
}
</script>
<style>
.fade-enter,
.fade-leave-active {
opacity: 0;
}
.fade-enter-active,
.fade-leave-active {
transition: all .5s ease-out;
}
</style>
PS:a) style中的.fade-和<transition>標籤的name是對應的。
b) 與直接用css過渡不一樣之處在於,標籤上不用加v-show/v-if指令。
c) <transition>標籤默認的mode爲in-out即新的先進來舊的再出去,這樣體驗很很差,因此修改成out-in即舊的先出新的再進。
b) 方式二
<template>
<button @click="show = !show">toggle</button>
<transition name="fade" mode="out-in">
<p v-if="show">I am show</p>
<div v-else>I am not show</div>
</transition>
</template>
<script>
import comA from './components/a'
import comB from './components/b'
export default {
components: {comA, comB},
data () {
return {
currentView: 'com-b',
show: true
}
}
}
</script>
<style>
.fade-enter,
.fade-leave-active {
opacity: 0;
}
.fade-enter-active,
.fade-leave-active {
transition: all .5s ease-out;
}
</style>
PS:在vue中若是<transition>中的兩個元素是相同標籤如都是<p>,則不會執行該動畫,須要添加key區分兩個標籤,動畫才能正常執行。
<transition name="fade" mode="out-in">
<p v-if="show" key="0">I am show</p>
<p v-else key="1">not in show</p>
</transition>
二、JS過渡
— 一樣也分爲一些過渡階段,與css過渡不一樣的是,js經過v-on來監聽這些事件鉤子。
<template>
<transition
@before-enter="beforeEnter"
@enter="enter"
@leave="leave"
:css="false">
<p class="animate-p" v-show="show">I am show</p>
</transition>
<br><br><br><br><br>
<button @click="show = !show">toggle</button>
</template>
<script>
import $ from 'jquery'
export default {
data () {
return {
show: true
}
},
methods: {
beforeEnter (el) {
$(el).css({
left: '-500px',
opacity: 1
})
},
enter (el, done) {
$(el).stop().animate({
left: 0,
opacity: 1
}, {
duration: 1500,
complete: done
})
},
leave (el, done) {
$(el).stop().animate({
left: '500px',
opacity: 0
}, {
duration: 1500,
complete: done
})
}
}
}
</script>
<style>
.animate-p {
position: absolute;
left: 0;
top: 0;
}
</style>
注意:(1)<transition>標籤不須要name,但須要綁定屬性:css=」false」,避免該標籤去檢查css中指定的選項。
(2)每一個方法其實都要操做傳過來的參數el,這個el是<transition>體內的DOM元素。
(3)其中的兩個方法enter、leave除了參數el外,還有個done(必須調用),是在兩個動做執行完了執行。
(4)用js操做時可能須要用到jquery等公用庫,最好把它在index.html中引入,由於那兒的代碼不會通過打包和處理資源,只會做爲一個入口的頁面往裏加東西。
PS:如何在項目中引入jquery?
在當前項目的目錄下(就是package.json),運行命令 cnpm install jquery --save-dev 這樣就將jquery安裝到了這個項目中。而後修改webpack.base.conf.js(在build文件下)兩個地方:
小注:上面的--save是爲了更新package.json,使得別人在用的時候也是更新後的。
a) 加入
var webpack=require('webpack');
b) 在module.exports的裏面加入
plugins: [
new webpack.optimize.CommonsChunkPlugin('common.js'),
new webpack.ProvidePlugin({
jQuery: "jquery",
$: "jquery"
})
]
c) 最後在main.js中加入import $ from 'jquery',完成jquery的引入
2、自定義指令
經過選項directives定義如v-color指令,在directives指令選項中定義color函數,傳el和binding兩個參數,el就表明v-color指令所在的元素,binding是個對象,指它綁定的一些變量或計算表達式等,binding.value指的是指令接收到值。
一、局部指令 -- 把該指令定義到普通組件的directives裏
<template>
<p v-color="'red'">這是一個段落</p>
<p v-custom="'40px'">第二段</p>
</template>
<script>
export default {
directives: {
color (el, binding) {
el.style.color = binding.value
},
custom: {
bind (el, binding) {
},
inserted (el, binding) {
el.style.fontSize = binding.value
}
}
}
}
</script>
二、全局指令 -- 把該指令定義到main.js的根組件的directives裏,定義方法同上
PS:如上例中,color指令方法爲合寫,custom指令方法爲分寫,詳細介紹參見下面:
三、自定義指令適用場景
實現該元素一插入到頁面就獲取焦點:
<template>
<input type="text" v-focus>
</template>
<script>
export default {
directives: {
focus: {
inserted (el, binding) {
el.focus()
}
}
}
}
</script>
3、插件 -- 功能完整的一套組件,獨立於vue而存在的
一、例如vue-router,如何安裝並引用呢?
第一步,在當前項目的目錄下(就是package.json),運行命令cnpm install vue-router --save
第二步,若是全局使用,就在main.js中import VueRouter from ‘vue-router’,等同於var VueRouter = require(‘vue-router’)
第三步,註冊使用該插件Vue.use(VueRouter)
第四步,實例化該插件let router = new VueRouter()
第五步,正式使用,在根組件中直接使用上面定義的router
如下爲入口文件main.js:
import Vue from 'vue'
import App from './App'
import VueRouter from 'vue-router'
// 註冊
Vue.use(VueRouter)
// 實例化
let router = new VueRouter()
/* eslint-disable no-new */
new Vue({
router, // 正式使用
el: '#app',
render: h => h(App)
})
二、例如vue-resource,它的安裝同vue-router,在main.js中引入時直接註冊便可,不須要實例化,這樣在每一個子組件的方法中均可以直接採用this.$http.get()方法。
更多插件詳見https://github.com/vuejs
4、單文件組件和vue-cli
一、單文件組件概念:vue自己是經過vue-cli工具搭建成的,單文件組件是.vue文件,它把template、script和css都集中到一個文件裏,實現組件及組件樹。全部的組件都是個.vue文件,最終在main.js中將根組件App.vue拼裝到頁面裏。
單文件組件的實現得益於vue-loader,配合webpack,通過必定的處理,最終把template和css插到組件裏。
關於css:
在style標籤上添加scoped,就限制該css爲當前組件的樣式,若是不加scoped,樣式就會泄漏到全局,致使全部引入該組件的父組件也會接收到這樣的樣式。
二、vue-cli
(1)用於初始化vue項目,是vue官方提供的一個腳手架工具。
(2)使用vue-cli的優點:
a) 它是一套成熟的vue項目架構設計,會隨着版本的更迭而更新(現爲2.0)
b) 提供了一套本地的測試服務器
c) 提供了一套本身的打包上線的方案webpack
(3)vue-cli對系統的要求 -- 它是命令行的一個工具
a) 系統必須裝NodeJs(>=4.0)
b) git 下載代碼
c) 一個能使用Node的命令行終端
(4)使用流程(使用NodeJs的包管理工具):
a) 全局安裝vue-cli npm install vue-cli -g
b) 初始化項目 vue init webpack my-project 規定了使用webpack打包方式
c) 安裝項目依賴 npm install
d)在localhost啓動測試服務器 npm run dev
或:生成上線目錄(部署) npm run build
(5)缺乏第五章項目安裝等筆記
5、ES6語法
一、import、export
(1)語法格式
import 變量名 from ‘’
export default {}
export後面必須跟default,只有這樣才能夠直接import一個default的內容做爲一個變量來引入當前文件。也能夠引入或導出一個變量import/export {變量名},但必須帶花括號。
二、對象縮寫
如componets: {hello}
三、區分var和let、const (ES6知識點)
用var在代碼塊中定義變量,在外面也能取到該變量,用let可避免這種泄露。
const用來聲明常量,也能夠避免泄露。
四、函數簡寫
如data () {}
6、vue-router
一、概念:根據不一樣的地址發到不一樣的頁面
二、單頁面應用:不用頻繁地去請求服務器,咱們只是經過ajax在切換的時候請求新數據,就實現了不須要刷新整個頁面的功能
三、什麼是前端路由?
舉例說明,當咱們請求foo頁面,展現其中一個頁面,請求bar時展現另外一個頁面。
前端路由在由一個頁面請求另外一個頁面時,公共的框架、css、js、環境之類的再也不請求,只請求頁面的不一樣之處。
四、設置路由
(1)安裝路由 cnpm install vue-router --save
(2)在入口文件main.js中引入vue-router
import Vue from 'vue'
import App from './App'
import VueRouter from 'vue-router'
// 註冊
Vue.use(VueRouter)
// 實例化
let router = new VueRouter()
/* eslint-disable no-new */
new Vue({
router, // 正式使用
el: '#app',
render: h => h(App)
})
(3)使用vue-router有三個關鍵點:
a) 一份map 規定什麼樣的地址訪問什麼樣的頁面或組件,在它上上級routes並列要加哈西mode: ‘history’ — 路由map
b) router-view 規定什麼樣的位置或什麼樣的區域顯示不一樣的頁面 — 路由視圖
c) router-link 在頁面上如何跳轉到下個頁面 — 路由導航
如何使用?
第一步,提早寫好兩個組件apple.vue和banana.vue,並在main.js中引入組件:
import Apple from ‘./components/apple’
import Banana from ‘./components/banana’
第二步,在上述實例化中經過routes選項進行配置(映射關係):
let router = new VueRouter({
mode: ‘history’,
routes: [
{
path: ‘/apple’,
component: Apple
},
{
path: ‘/banana,
component: Banana
}
]
})
第三步,規定在路由裏設定的組件在哪顯示 —— 在App.vue的template中
<template>
<router-view></router-view>
</template>
第四步,訪問地址分別爲localhost:8080/#/apple和localhost:8080/#/banana,第二步中使用Mode哈西,地址中就不須要寫#了。
另外一種方式,可使用<router-link>組件,並綁定:to屬性
<template>
<router-view></router-view>
<router-link :to=」{path: ‘apple’}」>toApple</router-link>
<router-link :to=」{path: ‘banana’}」>banana</router-link>
</template>
這個組件會默認渲染成一個a標籤,to表明它的href
五、路由參數
一、咱們原來的地址會加上?type=1&mode=2之類的參數,vue-router要在映射表中加入參數:
let router = new VueRouter({
mode: ‘history’,
routes: [
{
path: ‘/apple/:color/detail/:type’,
component: Apple
},
{
path: ‘/banana,
component: Banana
}
]
})
PS:上面的path中只有帶引號的纔是能被下面的$router.params獲取的參數。
二、使用時,在地址中直接經過’/參數值’添加:
localhost:8080/apple/red/detail/3
三、在組件如apple.vue內部如何獲取剛設定的這個參數?
設完參數之後,路由會往每一個組件的全局的router對象裏插入當前頁面的params,咱們在每一個子組件裏就能夠經過this.$route這樣的全局對象來獲取當前路由的參數,獲取到的是一個參數對象,如{color:’red’, type: 3},或者在template用花括號直接訪問如{{$route.params.color}}。
apple.vue中:
<template>
<p>{{ $route.params.color }}</p>
<button @click=」getParam」>getParam</button>
</template>
<script>
export default {
methods: {
getParam () {
console.log(this.$route.params)
}
}
}
</script>
PS:若是在映射表的path中設置了參數,但訪問路徑中不寫這個參數,就找不到這個路由即訪問不到相應的頁面。
六、路由嵌套vue-touter
在映射表中接着寫children,這個children對應的值也是個數組,一樣也包含path和component兩個屬性,該子組件經過<router-view>插入到父組件即apple.vue中,渲染出的頁面一樣會顯示在apple.vue頁面。
main.js中路由映射表:
先引入RedApple組件:
import RedApple from ‘./components/redapple’
let router = new VueRouter({
mode: ‘history’,
routes: [
{
path: ‘/apple’,
component: Apple,
children: [
path: ‘red’,
component: RedApple
]
},
{
path: ‘/banana,
component: Banana
}
]
})
該RedApple的父組件apple.vue中:
<template>
{{hello}}
<router-view></router-view>
</template>
export def...
訪問地址:
localhost:8080/apple/red
PS:一樣咱們在App.vue中也能夠經過<router-link :to=」{path:’apple/red’}」></router-link>實現相同的路由嵌套。
七、命名的路由視圖、路由重定向
(1)在router-link的to屬性的值有如下幾種:
a) <router-link :to=」’apple’」></router-link>
b) <router-link :to=」{path: ‘apple/red’}」></router-link>
c) <router-link :to=」{path: ‘apple’, param: {color: ‘yellow’}}」></router-link>
d) 具名的路由 <router-link :to=」{name: ‘applePage’}」></router-link>
e) 因爲router-link默認生成a標籤,要生成其餘標籤如在ul中生成li,則需加個屬性tag=」li」
f) router-link標籤被點中以後會自動添加一個class=」router-link-active」
PS:在組件template中的router-link這樣的導航叫作聲明式的導航。
(2)咱們也能夠在main.js裏採用router.push()方法進行編程式導航,其中push的內容和router-link的to所能指定的格式相同。
怎麼使用呢?
好比router.beforEach()方法指每次操做時都爲它設定一些操做,此時咱們能夠進行一些異步操做,好比檢查用戶信息,若是是未登陸狀態,能夠在回調裏使用router.push()把頁面導航到登陸頁。
router.beforEach(router.push(‘login’)或router.push({path: ‘login’})或router.push({name: ‘loginPage’}))
(3)命名的路由視圖(第五章4-8 26分鐘處)
給App.vue中的多個router-view標籤命不一樣的名字,在main.js的映射表的component中給不一樣的視圖指定不一樣的組件。
App.vue中:
<router-view name="bananaA"></router-view>
<router-view name="bananaB"></router-view>
main.js中:
routes: [
{
path: '/banana',
components: {
bananaA: Banana,
bananaB: RedBanana
}
}
]
(4)路由重定向
在映射表中加一項,採用redirect屬性將地址重定向到其餘頁面:
main.js中:
routes: [
{
path: ‘/’,
redirect: ‘/banana’
},
{
path: '/banana',
components: {
bananaA: Banana,
bananaB: RedBanana
}
}
]
八、使用過渡製做路由跳轉動畫
在App.vue中:
<transition name="fade">
<keep-alive>
<router-view></router-view>
</keep-alive>
</transition>
九、總結
(1)路由map 路由視圖 路由導航
(2)路由參數 嵌套路由
(3)命名路由和路由視圖
(4)重定向
7、vuex — 狀態管理插件(原理)
一、原理:有個統一的數據中心store,它用來維護狀態數據,每一個組件進行更新的時候就通知數據中心,數據中心再將共享的狀態觸發每一個調用這個組件的更新。
二、flux模型 用來實現vuex的流程
vue的組件經過Actions這樣一個動做來操做Mutations,Mutations控制數據中心的狀態state,狀態更改後再反映到頁面組件的一個渲染render,下圖中綠框虛線標的部分是vuex作的事情。
這個模型的設計含有不少規則,好比:
(1)Actions去執行異步的操做,好比去後臺調用API(Backend API)
(2)Mutations是同步地去更改State數據的一種方法,它能夠和Devtools交互
這套模型了保證數據的單項流動:
Vue Components經過Dispatch這樣的動做去觸發Actions,Actions經過Commit去觸發Mutations,Mutations直接操做數據。
PS:只適用於複雜項目,也能夠本身建造store,而後對外提供些事件接口及更新視圖的方法。
三、vuex狀態管理(實例)
(1)安裝vuex cnpm install vuex --save
而後重啓服務器cnpm run dev
(2)使用:
第一步,在main.js中引入插件vuex
import Vuex from 'vuex'
第二步,註冊使用
Vue.use(Vuex)
第三步,實例化
let store = new Vuex.Store({
state: {
totalPrice: 0
},
mutations: {
increment (state, price) {
state.totalPrice += price
},
decrement (state, price) {
state.totalPrice -= price
}
}
})
第四步,在根實例中引入store
new Vue({
store
})
第五步,在App.vue中展現totalPrice
<template>
{{ totalPrice }}
</template>
PS:此處的totalPrice爲屬性或方法,因此須要在script中定義
<script>
import Apple from ‘./components/apple’
export default {
components: {
Apple
},
computed: {
totalPrice () {
return this.$store.state.totalPrice
// PS:此處的totalPrice是剛纔在main.js的store實例的state中定義的,和本頁面的不同
}
}
}
</script>
第六步,在子組件apple.vue中添加按鈕並對totalPrice進行操做
<template>
<button @click=」add」>add 5<button>
<button @click=」minus」>minus 5</button>
</template>
<script>
export default {
data () {
price: 5
},
methods: {
add () {
this.$store.commit(‘increment’, this.price)
},
minus () {
this.$store.commit(‘decrement’, this.price)
}
}
}
</script>
PS:子組件中用$store.commit方法感受和子組件向父組件傳遞事件相似用$emit方法,可一併記憶理解。
其中第三步和第六步可改成:
第三步,實例化
let store = new Vuex.Store({
state: {
totalPrice: 0
},
mutations: {
increment (state, price) {
state.totalPrice += price
},
decrement (state, price) {
state.totalPrice -= price
}
},
actions: {
increase (context, price) {
context.commit(‘increment’, price)
},
decrease (context, price) {
context.commit(‘decrement’, price)
}
}
})
第六步,在子組件apple.vue中添加按鈕並對totalPrice進行操做
<template>
<button @click=」add」>add 5<button>
<button @click=」minus」>minus 5</button>
</template>
<script>
export default {
data () {
price: 5
},
methods: {
add () {
this.$store.dispatch(‘increase’, this.price)
},
minus () {
this.$store.dispatch(‘decrease’, this.price)
}
}
}
</script>
PS:actions只能去調用mutations,不能直接修改state;
第一個參數context指當前的store;
在子組件中就再也不commit mutations了,而是dispatch actions;
第二種方式把actions做爲中介達到執行increment的目的。
PS:actions和mutations的區別:
actions裏能夠進行異步操做,而後再去觸發mutations;而mutations裏必須是同步操做數據(即依次向下執行操做)。因此按照以前的圖形,跟後端的api接口都必須放在actions裏。
舉例說明:
actions: {
increase (context, id) {
api(id, function(price){
context.commit(‘increment’, price)
})
}
}
四、vuex除了state、mutations和actions這三個關鍵的數據流環節之外,還提供了getters用來獲取狀態集state裏的數據。
所以main.js的store實例可改成:
let store = new Vuex.Store({
state: {
totalPrice: 0
},
getters: {
getTotal (state) {
return state.totalPrice
}
},
mutations: {
increment (state, price) {
state.totalPrice += price
},
decrement (state, price) {
state.totalPrice -= price
}
},
actions: {
increase (context, price) {
context.commit(‘increment’, price)
},
decrease (context, price) {
context.commit(‘decrement’, price)
}
}
})
相應地,App.vue中的計算屬性computed裏可改成:
computed: {
totalPrice () {
return this.$store.getters.getTotal
}
}
五、modules
能夠把狀態集分紅不一樣的模型,每個module都維護一套本身的state、mutations、actions和getters,這些狀態集module最後合成一個總的對外store接口,咱們能夠根據不一樣的參數取不一樣模型裏的狀態。
const moduleA = {
state: {...},
mutations: {...},
actions: {...},
getters: {...}
}
const moduleB = {
state: {...},
mutations: {...},
actions: {...},
getters: {...}
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
store.state.a // -> moduleA’s state
store.state.b // -> moduleB’s state
補充:vuex模塊化在實際項目中的應用 *****
一、 實際項目結構
二、 根據以上結構:
(1) 數據中心爲store文件夾,包括公用的actions.js和getters.js以及index.js、mutations.js,公用的actions.js和getters.js對mutations的動做進行映射
(2) 數據放在modules的對應模塊裏如cart.js和products.js,每一個數據模型裏(即js裏)也包含actions和mutations
(3) 最終的輸出是在store>index.js裏,將vuex.store進行實例化並將全部的actions、getters、modules等輸出出來。
三、 簡單案例:
Store中只包括modules文件夾和index.js
四、 詳細步驟:
(1) 安裝vuex
npm install vuex --save
(2) 在store>index.js中引入vuex,並使用Vuex.use方法,故還需引入vue
index.js:
import Vuex from ‘vuex’
import Vue from ‘vue’
Vue.use(Vuex)
引入對應的數據模型,並導出實例化的vuex.store:
import OrderList from ‘./modules/orderList’
export default new Vuex.Store({
modules: {
OrderList
}
})
(3) 在入口文件main.js中引入store,並配置到全局
main.js:
(4) 使用router配置orderlist的訪問地址http://localhost:8080/orderList/
router>index.js:
並渲染到父組件中,此處爲app.vue:
(5) 在每一個數據模型中進行設置
PS:
1) state中存放數據
2) 因爲頁面沒法直接調用state中的數據,因此採用getters調用state的值
3) actions中進行異步操做
此處經過es6的解構賦值,把參數能夠寫成{commit, state},commit用來調用mutations,state獲取狀態集裏的數據
4) mutations同步地對狀態state進行更改
此處有兩個參數state和另外一個參數,該參數是咱們要賦值的state中的某個數據,是在actions或頁面要傳進去的
嚴格來說,只容許mutations對state進行更改,不容許actions
(6) 在相應的頁面組件中調用store的方法,採用this.$store
1) 動態獲取頁面初始化數據tableData
2) mounted時主動調用actions,對orderList進行賦值
此時狀態集中的orderList被更新,固然上面computed中依賴於orderList的tableDate也相應更新,template中的渲染層也會相應更新
(7) 另外一個功能:參數更改,頁面同步刷新
1) 在orderList.js的mutations中增長方法updateParams
2) 在orderList.vue中調用mutations的方法
(8) 採用types方式,把各模塊方法或變量都放在同一個js中定義
在modules同級創建types文件夾並新建相應的js
types>orderList.js:
modules>orderList.js:
1) 引入全部相關的types:
2) 使用該變量