VUE基礎
- Vue基礎
-
- 資料綁定
- 過濾器
- 指令
- 計算屬性
-
- 計算屬性的getter、setter方法
- 計算屬性擴充
- 計算屬性緩存
- v-bind
-
- 綁定class
-
- 使用對象文法綁定class:
- 使用數組文法綁定class
- 綁定内聯樣式
-
- 使用數組文法綁定多個樣式
- 内置指令
-
- v-cloak
- v-pre
- v-once
- v-if、v-else-if、v-else
- v-for
-
- v-for疊代整數
- 更新數組觸發資料改變的方法
- v-on
- v-model
- 元件
-
- 挂載元件
- 通過props傳遞資料:
- 子元件向父元件傳值
- 使用v-model和$emit傳值
- 中央事件總線
-
- 父(\$parent)鍊傳遞資料
- 子元件索引
- slot插槽
- 具名slot
- 使用component标簽挂載模闆
- $nextTick
- 自定義指令
- 虛拟dom
- vue-router
-
- 安裝vue-router
- 配置vue-router
- 配置跳轉
-
- 方式一,router-link
- 方式二,api跳轉
- router鈎子函數
-
- beforeEach
- afterEach
- vuex
-
- 安裝vuex
- 配置vuex
- 使用vuex,建立資料
-
- 擷取vuex中的資料
- 使用mutations修改states的資料
- commit接收對象
- getters
- 異步操作資料使用actions
- modules狀态區分
- 中央事件總線vue-bus
Vue基礎
資料綁定
通過{{}}可以與vue中data中的資料綁定。如果不想使用{{}}可以使用
v-pre
取消{{}}資料綁定。
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
<id id="app">
<span >{{ a }}</span>
<span v-pre>{{a}}</span>
</id>
<script src="./js/vue.min.js"></script>
<script>
let vue = new Vue({
el: "#app",
data: {
a: '<a href="www.baidu.com" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" >百度</a>'
},
created() {
console.log(this);
console.log(this.a);
console.log(this.$el);
// vue資料執行個體建立完成,資料生成
},
mounted() {
console.log(this);
console.log(this.$el);
// 挂載el,與dom關聯
}
})
</script>
</body>
</html>
使用v-html輸出html内容。
<id id="app">
<span >{{ a }}</span>
<span v-pre>{{a}}</span>
<span v-html='a'></span>
</id>
<script src="./js/vue.min.js"></script>
<script>
let vue = new Vue({
el: "#app",
data: {
a: '<a href="www.baidu.com" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" >百度</a>'
}
})
</script>
過濾器
filters屬性加上|操作符實作過濾:
<id id="app">
<!-- name 即為要過濾的資料 | 表示要使用過濾 formartName表示使用的哪個過濾器 -->
{{ name | formartName}}
</id>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: "#app",
data: {
name: 'zs'
},
// 在filters中使用過濾器方法
filters: {
formartName(value) { // value就是需要過濾的資料
return "@_" + value + "[email protected]";
}
}
})
</script>
可以指定使用多個過濾器,也可以給過濾器傳遞參數:
<id id="app">
可以使用多個過濾器,并且還能給過濾器傳遞參數
{{ name | formartName | formartName1('*')}}
</id>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: "#app",
data: {
name: 'zs'
},
filters: {
formartName(value) { // value就是需要過濾的資料
return "@_" + value + "[email protected]";
},
formartName1(value, param) {
return value + '->' + param;
}
}
})
</script>
指令
使用
v-show
,如果為false時,隻是設定了對應的元素的
display
屬性為none:
<id id="app">
<p v-show="isShow">v-show的使用</p>
</id>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
isShow: true
}
})
</script>
v-bind
作資料綁定,可以為元素動态綁定一個屬性。
<id id="app">
為p标簽綁定了一個name屬性,name屬性的值就是data資料中text對應的值
<p v-bind:name='text' v-show="isShow">v-show的使用</p>
</id>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
isShow: true,
text: '_text'
}
})
</script>
v-on
指令,可以用來監聽事件,其後接一個methods中定義的方法或者一個表達式。
<id id="app">
<p v-bind:name='text' v-show="isShow" v-on:click="isShow = false">v-show的使用</p>
</id>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
isShow: true,
text: '_text'
}
})
</script>
計算屬性
computed
時計算屬性,計算屬性也是一個屬性,類似于data中的資料,計算屬性是一個函數,計算屬性的值是函數的傳回值。
<id id="app">
{{ fullName }}
</id>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
firstName: 'Jhon',
lastName: 'Cena'
},
computed: {
fullName() {
return this.firstName + " " + this.lastName;
}
}
})
</script>
計算屬性的getter、setter方法
計算屬性有getter和setter方法,分别用于讀取和設定計算屬性的值。
<id id="app">
{{ fullName }}
</id>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
firstName: 'Jhon',
lastName: 'Cena'
},
computed: {
fullName: {
get() {
return this.firstName + " " + this.lastName;
},
set(value) {
let vs = value.split(' ');
this.firstName = "*" + vs[0];
this.lastName = vs[1];
}
}
}
})
app.fullName = 'zhang san';
</script>
計算屬性是依賴其他屬性的,隻要其他屬性發生改變,計算屬性就會跟着發生變化。setter屬性可以接收一個參數,這個參數接收了并不是一定能改變計算屬性的值,而是根據參數,去改變對應的計算屬性依賴的值,依賴的值改變,getter方法會傳回對應格式的資料。
計算屬性擴充
計算屬性可以依賴其他計算屬性,計算屬性也可以依賴其他執行個體資料,這裡示範計算屬性依賴其他執行個體資料。
<div id="app1">
{{ msg }}
</div>
<div id="app2">
{{message}}
</div>
<script src="./js/vue.min.js"></script>
<script>
let app1 = new Vue({
el: '#app1',
data: {
msg: 'message'
}
});
let app2 = new Vue({
el: '#app2',
computed: {
message() {
return app1.msg.split('').reverse().join('');
}
}
})
app1.msg = 'hello world!';
</script>
計算屬性緩存
計算屬性(computed)類似于方法(methods),但是方法每次調用都會被執行,而計算屬性則不同,隻有在計算屬性所依賴的資料發生改變時才會執行。
<div id="app1">
計算屬性是一個屬性,可以直接使用,methods是方法,需要調用
{{ cTime }},<br/> {{ mTime() }}
</div>
<script src="./js/vue.min.js"></script>
<script>
let app1 = new Vue({
el: '#app1',
data: {
data: new Date()
},
computed: {
cTime() {
return this.data + " --- ";
}
},
methods: {
mTime() {
return new Date();
}
}
});
v-bind
綁定class
使用對象文法綁定class:
<div id="app">
<span :class="{ 'red': isRed, 'error': isError}">這段話的顔色</span>
</div>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
isRed: true,
isError: true,
active: 'active',
primary: 'primary'
}
})
</script>
<span :class="{ ‘red’: isRed, ‘error’: isError}">這段話的顔色</span>
,這裡為class綁定一個對象,對象的屬性名将作為class屬性的值,當且僅當對象屬性的值為true時,才會被應用。
使用數組文法綁定class
使用數組文法,可以嵌套對象文法。
<div id="app">
<span :class="[{ 'red': isRed, 'error': isError}, active, primary]">這段話的顔色</span>
</div>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
isRed: true,
isError: true,
active: 'active',
primary: 'primary'
}
})
</script>
要綁定多個class屬性需要使用對象文法或者數組文法,如果都不使用,而是直接使用資料,最多隻能有一個資料。
錯誤寫法:
正确寫法(隻能有一個):
綁定内聯樣式
對象文法,與綁定class不同的是,對象屬性作為内聯樣式屬性,資料的值作為樣式的值,而不是根據true和false來确定應用誰
<div id="app">
<span :style="{'color': red, 'fontSize': fontSize + 'px'}">這段話的顔色</span>
</div>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
red: 'red',
fontSize: 20
}
})
</script>
使用數組文法綁定多個樣式
<div id="app">
<span :style="[color, font]">這段話的顔色</span>
</div>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
color: {
color: 'red',
background: 'green'
},
font: {
fontSize: 20 + 'px'
}
}
})
</script>
内置指令
v-cloak
v-cloak
的作用:如果網速較慢等情況下,資料加載較慢,{{data}}可能會直接顯示在頁面上,而v-cloak的作用就是阻止這種情況的發生。使用v-cloak時需要配合下面css樣式:
[v-cloak] {
display: none;
}
<div id="app">
<span v-cloak>{{ msg }}</span>
</div>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
msg: 'message'
}
})
</script>
v-pre
v-pre
的作用:{{data}}是取資料,而有時候我們需要原樣輸出,即{{}}不具備任何功能,這是就可以使用v-pre
<div id="app">
<span v-pre>{{ msg }}</span>
</div>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
msg: 'message'
}
})
</script>
v-once
使用v-once,資料隻被渲染一次,之後資料發生變化使用了v-once的資料也不會被渲染
<div id="app" @click="changeMsg">
<span>{{ msg }}</span><br/>
<span v-once>{{ msg }}</span>
</div>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
msg: 'message'
},
methods: {
changeMsg() {
this.msg = this.msg.split('').reverse().join('');
}
}
})
v-if、v-else-if、v-else
v-if和
v-show
的差別是,v-if不會加載html标簽,v-show時設定css樣式dispaly為none,
v-show
多用于頻繁操作的場景。
<div id="app">
<span v-if='status == 1'>1</span>
<span v-else-if='status == 2'>2</span>
<span v-else-if='status == 3'>3</span>
<span v-else>4</span>
</div>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
status: 3
}
})
</script>
可以使用
<template>
标簽作為v-if的載體,
<template>
最終不會被加載到html中。
注:使用v-if時vue會盡可能的複用元件,比如下面代碼,點選切換的時候,vue做的其實就是把相同标簽的不同的地方更換了,即把手機号換成了郵箱,name屬性的phone換成了email:
<div id="app">
<template v-if='status === 1'>
<label>手機号:</label>
<input type="text" name="phone">
</template>
<template v-if='status === 2'>
<label>郵箱:</label>
<input type="text" name="emial">
</template>
<button @click='change'>切換</button>
</div>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
status: 1
},
methods: {
change() {
this.status = this.status === 1 ? 2 : 1;
}
}
})
</script>
如果不需要元件被複用,可以元件添加一個key屬性,屬性的值必須是唯一的。
v-for
v-for用來周遊數組或者對象屬性,也可以結合template标簽使用。
周遊數組時,有兩個參數可選,第一個是每一項的資料,第二個是索引。周遊對象時,第一個參數是對象的屬性名,第二個參數是對象屬性值,第三個參數是索引:
<div id="app">
<ul>
<li v-for="(a, index) of arr"> {{ a }} -- {{ index }}</li>
</ul>
<template v-for="(key, value, index) of person">
{{ index }} : {{ key }} -> {{ value }}<br>
</template>
</div>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
arr: [1, 3, 5, 7],
person: {
name: 'zs',
age: 18,
address: 'China'
}
}
})
v-for疊代整數
<div id="app">
<span v-for="(item, index) of integer">{{index}} : {{item}} /</span>
</div>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
integer: 10
}
})
</script>
更新數組觸發資料改變的方法
-
push():向原數組末尾增加一個元素
示例:
<div id="app" >
{{arr}}
<button @click="change">change</button>
</div>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
arr: [1,2,3,4,5]
},
methods: {
change() {
this.arr.push(6);
}
}
})
-
pop():從數組末尾删除一個元素
示例:
<div id="app" >
{{arr}}
<button @click="change">change</button>
</div>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
arr: [1,2,3,4,5]
},
methods: {
change() {
this.arr.pop();
}
}
})
</script>
- shift():從數組開頭删除一個元素
<div id="app" >
{{arr}}
<button @click="change">change</button>
</div>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
arr: [1,2,3,4,5]
},
methods: {
change() {
this.arr.shift();
}
}
})
</script>
- unshift():向數組開始位置添加一個元素
<div id="app" >
{{arr}}
<button @click="change">change</button>
</div>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
arr: [1,2,3,4,5]
},
methods: {
change() {
this.arr.unshift(1);
}
}
})
</script>
-
splice():改變數組長度
示例:
<div id="app" >
{{arr}}
<button @click="change">change</button>
</div>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
arr: [1,2,3,4,5]
},
methods: {
change() {
this.arr.splice(2);
}
}
})
</script>
- sort():數組排序
<div id="app" >
{{arr}}
<button @click="change">change</button>
</div>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
arr: [7,2,1,4,5]
},
methods: {
change() {
this.arr.sort((a, b) => {
// a-b就相當于a要大于b,升序排序
return a - b;
})
}
}
})
</script>
-
reverse() :反轉數組
示例:
<div id="app" >
{{arr}}
<button @click="change">change</button>
</div>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
arr: [7,2,1,4,5]
},
methods: {
change() {
this.arr.reverse();
}
}
})
</script>
-
filter():數組過濾,不改變原數組,傳回一個新的數組
示例:
<div id="app" >
{{arr}}
<button @click="change">change</button>
</div>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
arr: [7,2,1,4,5]
},
methods: {
change() {
console.log(this.arr);
// 不改變原數組,産生一個新的數組
this.arr = this.arr.filter(function(data) {
return data > 2;
});
}
}
})
</script>
-
concat():連接配接數組,把一個數組追加大目前數組後,不改變原有數組,産生新的數組
示例:
<div id="app" >
{{arr}}
<button @click="change">change</button>
</div>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
arr: [7,2,1,4,5]
},
methods: {
change() {
let arr2 = ['a', 'b', 'c'];
this.arr = this.arr.concat(arr2);
}
}
})
</script>
-
slice():根據下腳标查找元素,不改變原有數組,産生一個新數組并傳回
示例:
<div id="app" >
{{arr}}
<button @click="change">change</button>
</div>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
arr: [7,2,1,4,5]
},
methods: {
change() {
let arr2 = [2,4];
// 查找數組中索引大于等于2的所有元素,組成一個新數組并傳回
// this.arr = this.arr.slice(2);
// 查找下腳标大于等于0小于1的元素,組成一個新數組并傳回
this.arr = this.arr.slice(0,1);
}
}
})
</script>
v-on
監聽事件:
<div id="app" >
{{count}}
<button @click="count++">change</button>
</div>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
count: 0
}
})
</script>
綁定使用方法:
<div id="app" >
{{count}}
可以傳參,也可以傳入目前事件$event
<button @click="change('abc',$event)">change</button>
</div>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
count: 0
},
methods: {
change(param) {
// 可以通過event去通路事件
console.log(param, event);
}
}
})
</script>
事件修飾符.stop,.prevent,.capture,.self,.once
-
.stop 阻止事件冒泡
示例:點選button按鈕,如果事件冒泡的話,也會觸發div的單擊事件,但是在button上使用.stop就會阻止事件冒泡
<div id="app" >
{{count}}
<div @click="count++">
<button @click.stop=''>change</button>
</div>
</div>
-
.prevent 阻止事件的預設行為
示例:
<div id="app" >
{{count}}
<div @click="count++">
<a href="www.baidu.com" @click.prevent=''>change</a>
</div>
</div>
-
.capture 事件捕獲模式
下面代碼先執行1後執行2,如果不适應.capture的話是先執行2後執行1
<div id="app" >
<div @click.capture="change(1)">
<button @click.capture='change(2)'>change</button>
</div>
</div>
- .self 元素本身觸發事件時才執行
<div id="app" >
{{count}}
<div @click.self="count++">
<!--點選button不會觸發div的單擊事件-->
<button @click.prevent=''>change</button>
</div>
</div>
v-model
使用v-model實作表單資料綁定,v-model可以用@input來實作。
<div id="app" >
{{msg}}
<input v-model="msg" placeholder="請輸入...">
<input @input="input" placeholder="請輸入..." :value="msg">
</div>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
msg: ''
},
methods: {
input(e) {
this.msg = e.target.value;
}
}
})
</script>
元件
元件注冊
<div id="app" >
<!-- 使用全局注冊的元件 -->
<my-component></my-component>
<!-- 使用局部注冊的元件 -->
<child></child>
</div>
<script src="./js/vue.min.js"></script>
<script>
// 注冊全局元件
Vue.component('my-component', {
template: '<div>xxx</div>'
});
let app = new Vue({
el: '#app',
// 注冊局部元件
components: {
'child': {
template: '<div>child</div>'
}
}
})
</script>
挂載元件
在類似于table這樣的标簽中,隻能使用td,tr等,不能使用自定義元件的時候,需要把元件挂載到某個節點上。
<div id="app" >
<table>
<!-- 通過is屬性挂載元件 -->
<tbody is='child'></tbody>
</table>
</div>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
// 注冊局部元件
components: {
'child': {
template: '<th>child</th>'
}
}
})
</script>
通過props傳遞資料:
<div id="app" >
<table>
<!-- 通過is屬性挂載元件 -->
<tbody is='child' message='傳遞資料的方式'></tbody>
</table>
</div>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
// 注冊局部元件
components: {
'child': {
props: ['message'],
template: '<th>{{message}}</th>'
}
}
})
</script>
子元件向父元件傳值
<div id="app" >
{{ msg }}
<!-- 通過子元件定義的事件來接收子元件傳遞的值 -->
<child @data='changeData' message='h'></child>
</div>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
msg: 'o'
},
methods: {
changeData(data) {
// data就是 子元件 傳遞過來的資料
this.msg = data;
}
},
// 注冊局部元件
components: {
'child': {
props: ['message'],
template: '<div>{{message}}' +
'<button @click="change">傳遞資料</button></div>',
methods: {
change() {
// 子元件通過$emit傳值,第一個參數是自定義事件名稱,第二個參數是傳的值
this.$emit('data','abc')
}
}
}
}
})
</script>
使用v-model和$emit傳值
<div id="app" >
{{msg}}
<child v-model='msg'></child>
</div>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
msg: '0'
},
methods: {
changeMsg(data) {
this.msg = data;
}
},
components: {
child: {
template: '<button @click="sendMsg">傳遞資料</button>',
methods: {
sendMsg() {
this.$emit('input', 'abc');
}
}
}
}
})
</script>
上面這個對應的自定義事件寫法:
<div id="app" >
{{msg}}
<child @input='changeMsg'></child>
</div>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
msg: '0'
},
methods: {
changeMsg(data) {
this.msg = data;
}
},
components: {
child: {
template: '<button @click="sendMsg">傳遞資料</button>',
methods: {
sendMsg() {
this.$emit('input', 'abc');
}
}
}
}
})
</script>
中央事件總線
<div id="app" >
{{msg}}
<child></child>
</div>
<script src="./js/vue.min.js"></script>
<script>
// 建立一個空執行個體vue,隻用于傳遞資料
var bus = new Vue();
let app = new Vue({
el: '#app',
data: {
msg: '0'
},
mounted() {
let _this = this;
// 通過這個空執行個體vue監聽這個事件,并接收資料
bus.$on('input', (data) => {
_this.msg = data;
})
},
components: {
child: {
template: '<button @click="sendMsg">傳遞資料</button>',
methods: {
sendMsg() {
// 通過空執行個體vue注冊一個事件,并傳遞資料
bus.$emit('input', 'abc');
}
}
}
}
})
</script>
父($parent)鍊傳遞資料
多個父元件隻需要多次.$parent就可以了。但是這種子元件直接修改父元件的方式不推薦使用。(緊耦合)
<div id="app" >
{{msg}}
<child></child>
</div>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
msg: '0'
},
components: {
child: {
template: '<button @click="sendMsg">傳遞資料</button>',
methods: {
sendMsg() {
// 直接修改父元件的資料
this.$parent.msg = 'hahaha';
}
}
}
}
})
</script>
子元件索引
<div id="app" >
{{msg}}
<!-- ref 為元件取一個别名 -->
<child ref='childA'></child>
</div>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
msg: '0'
},
mounted() {
// 通過$refs.别名 去通路子元件的資料
this.msg = this.$refs.childA.msg;
},
components: {
child: {
template: '<button @click="sendMsg">傳遞資料</button>',
data() {
return {
msg: '12345'
}
},
methods: {
sendMsg() {
// 直接修改父元件的資料
this.$parent.msg = 'hahaha';
}
}
}
}
})
</script>
slot插槽
<div id="app" >
<child>
<!-- 向插槽内添加資料 -->
<p>{{msg}}</p>
</child>
</div>
<script src="./js/vue.min.js"></script>
<script>
let vue = new Vue({
el: '#app',
data: {
msg: '12345'
},
components: {
child: {
// slot作為插槽,在使用目前元件時,如果在标簽内寫入了内容,就替換插槽内的内容
template: "<div>子元件的内容:<slot>插槽</slot></div>"
}
}
});
</script>
具名slot
用于向指定的插槽内添加資料:
<div id="app" >
<child>
<!-- 向插槽内添加資料 -->
<p>
<!-- 向name為n2的插槽内添加資料 -->
<div slot='n2'>{{msg}}</div>
</p>
</child>
</div>
<script src="./js/vue.min.js"></script>
<script>
let vue = new Vue({
el: '#app',
data: {
msg: '12345'
},
components: {
child: {
// slot作為插槽,在使用目前元件時,如果在标簽内寫入了内容,就替換插槽内的内容
template: "<div>子元件的内容:<slot name='n1'>插槽</slot><slot name='n2'>2</slot></div>"
}
}
});
</script>
使用component标簽挂載模闆
is指定要挂載的是哪個模闆,可以動态指定
:is
<div id="app" >
<component is='child'></component>
</div>
<script src="./js/vue.min.js"></script>
<script>
let vue = new Vue({
el: '#app',
data: {
msg: '12345',
},
components: {
child: {
name: 'child',
template: "<div>123</div>"
}
}
});
</script>
$nextTick
下面代碼執行會報錯:
<div id="app" >
<div id="content" v-if='isShow'>hello world!</div>
<button @click='isShow = false'>隐藏</button>
<button @click='getText'>顯示并擷取内容</button>
</div>
<script src="./js/vue.min.js"></script>
<script>
let vue = new Vue({
el: '#app',
data: {
isShow: true
},
methods: {
getText() {
this.isShow = true;
// this.isShow = true 此時并沒有去更新dom,而是開啟一個隊列,在隊列中處理資料(去重,得到最終改變),
// 不是資料改變一次,頁面就渲染一次,隻有所有資料最終固定後渲染資料,改變dom,是以此時去擷取一個不存在的元素報錯
// 在下一次事件循環tick完成更新
let msg = document.getElementById("content").innerText;
console.log(msg);
}
}
});
</script>
修改後,使用$netTick
<div id="app" >
<div id="content" v-if='isShow'>hello world!</div>
<button @click='isShow = false'>隐藏</button>
<button @click='getText'>顯示并擷取内容</button>
</div>
<script src="./js/vue.min.js"></script>
<script>
let vue = new Vue({
el: '#app',
data: {
isShow: true
},
methods: {
getText() {
this.isShow = true;
// this.isShow = true 此時并沒有去更新dom,而是開啟一個隊列,在隊列中處理資料(去重,得到最終改變),
// 不是資料改變一次,頁面就渲染一次,隻有所有資料最終固定後渲染資料,改變dom,是以此時去擷取一個不存在的元素報錯
// 在下一次事件循環tick完成更新
// $nextTick可以知道什麼時候dom更新完成
this.$nextTick(() => {
let msg = document.getElementById("content").innerText;
console.log(msg);
});
}
}
});
</script>
自定義指令
注冊指令的兩種方式
一、全局注冊
Vue.directive('指令名', {
// 指令選項
})
二、局部注冊
new Vue({
el: '#app',
directivies: {
'指令名': {
// 指令選項
}
}
})
使用 v-指令名 即可。
全局方式:
<div id="app" >
<input v-focus>
</div>
<script src="./js/vue.min.js"></script>
<script>
Vue.directive ('focus', {
inserted(el) {
el.focus();
}
})
</script>
局部方式:
<div id="app" >
<input v-focus>
</div>
<script src="./js/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
directives: {
focus: {
inserted: function(el) {
el.focus();
}
}
}
})
</script>
虛拟dom
<div id="app" >
<anchor :level='2' title="特性">特性</anchor>
</div>
<script src="./js/vue.min.js"></script>
<script>
Vue.component('anchor', {
props: {
level: {
type: Number,
required: true
},
title: String,
default: ''
},
render: function(createElement) {
return createElement(
'h' + this.level,
[
createElement(
'a',
{
domProps: {
href: '#' + this.title
}
},
this.$slots.default
)
]
)
}
})
let app = new Vue({
el: '#app'
})
</script>
vue-router
安裝vue-router
npm install vue-router --save
配置vue-router
import Vue from 'vue'
import App from './App.vue'
// 導入vue-router
import VueRouter from 'vue-router'
// 導入vue元件
import Index from './views/Index'
import About from './views/About'
// 配置路由群組件映射
const Routers = [
{
path: '/index',
component: Index
},
{
path: '/about',
component: About
},
{
path: '*',
redirect: '/index'
}
]
// 配置路由
const RouterConfig = {
mode: 'history',
routes: Routers
}
// 建立vue-router執行個體
const router = new VueRouter(RouterConfig)
Vue.use(VueRouter)
Vue.config.productionTip = false
new Vue({
el: '#app',
router: router,
render: h => h(App)
}).$mount('#app')
配置跳轉
方式一,router-link
<router-view></router-view>
标簽内顯示元件内容,
router-link
标簽類似a标簽,tag标簽使用與指定router-link使用哪個标簽實作。
<template>
<div id="app">
hello
<router-view></router-view>
<router-link to='/index'>首頁</router-link>
<router-link to='/about' tag='span'>關于</router-link>
</div>
</template>
<script>
export default {
}
</script>
<style scoped>
#app {
color: red;
}
</style>
router-link
的其他屬性:
replace :不會留下曆史記錄,回退不能回到上個頁面
<router-link replace to='/about' >關于</router-link>
active-class:目前router-link被選中時的類名,比如下面這個關于被選中時的class屬性為about
<router-link to='/about' tag='span' replace active-class='about'>關于</router-link>
方式二,api跳轉
this.$router.push(’/about’)
<template>
<div id="app">
hello
<router-view></router-view>
<router-link to='/index'>首頁</router-link>
<router-link to='/about' tag='span' replace active-class='about'>關于</router-link>
<button @click="handleRouter">API跳轉</button>
</div>
</template>
<script>
export default {
methods: {
handleRouter () {
// 通過api的方式跳轉
this.$router.push('/about')
}
}
}
</script>
<style scoped>
#app {
color: red;
}
</style>
$router的其他方法:
replace: 方法類似于router-link中的replace屬性,this.$router.replace('/index')
go:類似于window.history.go(),表示向前或向後後退多少步。例如this.$router.go(-1)後退1頁,this.$router.go(2)前進2頁
router鈎子函數
beforeEach
進入路由前beforeEach函數:
// 配置路由群組件映射
const Routers = [
{
path: '/index',
meta: {
title: '首頁'
},
component: Index
},
{
path: '/about',
meta: {
title: '關于'
},
component: About
},
{
path: '*',
redirect: '/index'
}
]
// 配置路由
const RouterConfig = {
mode: 'history',
routes: Routers
}
// 建立vue-router執行個體
const router = new VueRouter(RouterConfig)
// 進入路由前
router.beforeEach((to, from, next) => {
window.document.title = to.meta.title
})
meta字段可以自定義資訊。
三個參數:
to:要跳轉到的路由
from: 從哪個路由跳轉的
next:函數,調用這個函數才進入下一個鈎子,否則路由不跳轉
afterEach
每一個路由中的設定
比如進入每個頁面後,滾動條都在起始位置:
router.afterEach((to, from, next) => {
window.scrollTo(0,0)
})
或者判斷是否登入:
router.afterEach((to, from, next) => {
if ('登入') {
next(); // 允許路由跳轉
} else {
next('login'); // 否則跳轉到登入頁面
}
})
next()
函數,不接受參數,路由跳轉,設定為false,路由取消跳轉,參數為具體路由,跳轉到指定路由。
vuex
安裝vuex
npm install vuex --save
配置vuex
在main.js中配置
import Vuex from 'vuex'
Vue.use(Vuex)
// 配置vuex
const store = new Vuex.Store({
})
new Vue({
el: '#app',
router: router,
store: store, // 配置vuex
render: h => h(App)
}).$mount('#app')
使用vuex,建立資料
資料儲存在state字段:
const store = new Vuex.Store({
state: {
count: 0
}
})
擷取vuex中的資料
通過$store.state.xxx通路資料
<template>
<div>
首頁 {{ $store.state.count }}
<button @click="handleCount">加一</button>
</div>
</template>
<script>
export default {
methods: {
handleCount () {
this.$store.state.count++
}
}
}
</script>
這樣通路每次都會調用
$store.state.xxx
,可以把這個作為計算屬性
<template>
<div>
首頁 {{ count }}
<button @click="handleCount">加一</button>
</div>
</template>
<script>
export default {
computed: {
count () {
return this.$store.state.count
}
},
methods: {
handleCount () {
this.$store.state.count++
}
}
}
</script>
使用mutations修改states的資料
state中的資料不建議直接修改,而是通過mutations屬性定義方法來修改
// 配置vuex
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
},
decrease (state, n = 1) {
state.count -= n
}
}
})
在元件中掉喲mutations中的方法來改變資料,調用mutations中的資料要使用commit來調用:
<template>
<div>
首頁 {{ count }}
<button @click="handleCountA">加</button>
<button @click="handleCountD">減</button>
</div>
</template>
<script>
export default {
computed: {
count () {
return this.$store.state.count
}
},
methods: {
handleCountA () {
this.$store.commit('increment')
},
handleCountD () {
this.$store.commit('decrease', 2)
}
}
}
</script>
commit接收對象
main.js中定義方法:
mutations: {
increment (state) {
state.count++
},
decrease (state, n = 1) {
state.count -= n
},
// param作為一個對象
change (state, param) {
state.count += (param.count1 - param.count2)
}
}
在元件中調用,type就是要調用的方法名,其他的就是具體的參數:
changeCount () {
this.$store.commit({
type: 'change',
count1: 1,
count2: 5
})
}
在mutations中不要做異步操作,commit後資料不能及時跟新。
getters
getters類似于計算屬性
需求:對一個數組進行過濾,去大于10的數
state: {
count: 11,
list: [1, 3, 5, 7, 10, 11, 13, 15]
},
getters: {
listFilter: state => state.list.filter(data => data > 10),
// getters中的資料也可以通路其他getters中的資料
equalseCount: (state, getters) => getters.listFilter.filter(data => data === state.count)
},
通路getter資料:
getter中的資料 {{ $store.getters.listFilter }} -> {{ $store.getters.equalseCount}}
異步操作資料使用actions
定義actions
mutations: {
increment (state) {
state.count++
},
decrease (state, n = 1) {
state.count -= n
},
change (state, param) {
state.count += (param.count1 - param.count2)
}
},
actions: {
increment (context, param) {
context.commit('change', param)
}
}
調用actions要使用dispatch方法
actions () {
this.$store.dispatch({ // 使用dispath方法調用action中的方法
type: 'increment',
count1: 1,
count2: 5
})
}
異步案例:
actions:
actions: {
asyncIncrement (context) {
return new Promise(resolve => {
setTimeout(() => {
context.commit('increment')
resolve('success')
}, 2000)
})
}
}
在元件中調用:
async () {
this.$store.dispatch('asyncIncrement').then(data => console.log(data))
}
資料改變用mutations,存在業務邏輯用actions
modules狀态區分
如果所有的狀态寫在一起不容易區分,這時可以用modules來做區分:
const moduleA = {
state: {
count: 10
}
}
const moduleB = {
state: {
count: 20
},
getters: {
sumCount (state, getters, rootState) {
return state.count + rootState.b.count + rootState.count
}
}
}
// 配置vuex
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
},
state: {
count: 11,
list: [1, 3, 5, 7, 10, 11, 13, 15]
},
}
擷取,要注意的是 子產品内部的 action、mutation、和 getter 注冊在全局命名空間,不能使用子產品名.getters等方式去調用
<template>
<div>介紹 {{ $store.state.count }}
moduleB中的Count {{ $store.state.b.count }}
moduleB中的sumCount {{ $store.getters.sumCount }}
</div>
</template>
<script>
export default {
}
</script>
中央事件總線vue-bus
建立一個vue-bus.js檔案:
const install = function (Vue) {
const Bus = new Vue({
methods: {
emit(event, ...args) {
this.$emit(event, args)
},
on(event, callback) {
this.$on(event, callback);
},
off(event, callback) {
this.off(event, callback)
}
}
})
Vue.prototype.$bus = Bus
}
export default install
在main.js中引入并使用:
import VueBus from './vue-bus'
Vue.use(VueBus)
在元件中使用-發送資料:
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<button @click="handleNum">click</button>
<HelloWorld/>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'app',
components: {
HelloWorld
},
methods: {
handleNum() {
this.$bus.emit('add', 10);
}
}
}
</script>
<style>
</style>
擷取資料:
<template>
<div class="hello">
<h1>{{ number }} </h1>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data() {
return {
number: 0
}
},
methods: {
handle(num) {
let data = parseInt(num)
this.number += data
}
},
created() {
this.$bus.on('add', this.handle)
},
beforeDestroy() {
this.$bus.off('add', data => console.log(data))
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>