6. Vue.nextTick
- Vue.nextTick 会在dom渲染之后出发,以获取最新dom节点
- Vue 异步队列使用 Promise.then、MutationObserver 和 setImmediate,如果不支持会采用 setTimeout(fn, 0) 代替。
this.$nextTick( () => {
// code
})
使用 Vue.nextTick 异步渲染的好处
- 汇总data的修改,一次性更新视图。
- 减少dom操作次数,提高性能。
7. ref属性
- 在DOM 元素上使用,引用指向 DOM 元素;
- 在子组件上使用,引用就指向组件实例,可调用子组件的data和mothods等。
$refs 在组件渲染之后生效,不是响应式的。应该避免在模板或计算属性中访问。
<!-- dom 元素 -->
<p ref="p">hello</p>
<!-- 子组件 -->
<child-component ref="child"></child-component>
this.$refs.xxx();
8. 动态组件:根据条件加载不同组件模板
<div id="app">
<button @click="currentIndex = 0">
1
</button>
<button @click="currentIndex = 1">
2
</button>
<component :is="currentTabComponent"></component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component('t-one', {
template: `
<div>one</div>
`
})
Vue.component('t-two', {
template: `
<div>two</div>
`
})
const app = new Vue({
el: '#app',
data: {
currentIndex: 0,
status:['t-one','t-two']
},
computed: {
currentTabComponent() {
return this.status[this.currentIndex]
}
}
});
</script>
9. vue组件异步加载
- 只有用该组件到时才会加载。
- 一般用于加载大组件。
// 具体用法
// a: () => import('./components/a.vue')
new Vue({
...rest,
components: {
a: () => import('./components/a.vue')
}
})
10. keep-alive
keep-alive
是 Vue 内置的缓存组件,避免使包含的组件重新渲染。
大致用法
<keep-alive>
<KeepAliveStageA v-if="state === 'A'"/>
<KeepAliveStageB v-if="state === 'B'"/>
</keep-alive>
具体案例
app.vue
<template>
<div>
<button @click="changeState('A')">A</button>
<button @click="changeState('B')">B</button>
<keep-alive>
<KeepAliveStageA v-if="state === 'A'"/>
<KeepAliveStageB v-if="state === 'B'"/>
</keep-alive>
</div>
</template>
<script>
import KeepAliveStageA from './components/KeepAliveStateA'
import KeepAliveStageB from './components/KeepAliveStateB'
export default {
components: {
KeepAliveStageA,
KeepAliveStageB
},
data() {
return {
state: 'A'
}
},
methods: {
changeState(state) {
this.state = state
}
}
}
</script>
子组件A,子组件B同理
<template>
<p>state A</p>
</template>
<script>
export default {
mounted() {
// eslint-disable-next-line
console.log('A mounted')
},
destroyed() {
// eslint-disable-next-line
console.log('A destroyed')
}
}
</script>
11. mixin,混入:抽离组件公共逻辑
不足
- 多个
mixin
可能会造成命名冲突 mixin
和组件出现多对多关系时,复杂度较高
用法
<template>
<div>
{{name}},{{city}}
<button @click="showName">显示姓名</button>
</div>
</template>
<script>
import myMixin from './mixin'
export default {
mixins: [myMixin], // 可以添加多个,会自动合并起来
data() {
return {
name: '你好'
}
},
methods: {
},
mounted() {
// eslint-disable-next-line
console.log('component mounted', this.name)
}
}
</script>
mixin.js
export default {
data() {
return {
city: '北京'
}
},
methods: {
showName() {
// eslint-disable-next-line
console.log(this.name)
}
},
mounted() {
// eslint-disable-next-line
console.log('mixin mounted', this.name)
}
}
12. vuex:实现Vue多个组件响应式共享状态的管理工具。
核心功能
- State :定义全局共享的state变量
第一步:在仓库store中定义需要全局共享的state变量
state: {
age: 25
}
第二步:在对应的组件中获取并显示在页面上
<p>{{$store.state.age}}</p>
- Getters:相当于组件中的computed计算属性。
第一步:在仓库store中定义好getters
getters: {
getAge(state) {
return state.age + 1;
}
}
第二步:在对应的组件中获取并显示在页面上
<p>{{$store.getters.getAge}}</p>
- Mutations:修改state变量
第一步:在仓库store中定义需求调用的mutation方法
mutations: {
incre(state, payload) {
state.age += payload.age;
}
}
第二步:在对应组件中定义触发更改状态的模板和方法
// template
<button @click="add">增加</button>
// script
methods: {
add() {
this.$store.commit('incre', {age: 1});
}
}
- Actions:只有它可以为异步函数,可以整合多个mutation。
第一步:在仓库store中定义需求调用的mutation方法
actions: {
increAsyn({commit}, payload) {
commit('incre', payload);
}
}
第二步:在对应组件中定义触发更改状态的模板和方法
// template
<button @click="addAsyn">异步增加</button>
// script
addAsyn() {
this.$store.dispatch('increAsyn', {age: 1});
}
- Modules
第一步:在仓库store中定义不同的模块以及modules方法
// 创建 moduleA.js
const moduleA = {
state: {
name: 'txm',
age: 25
},
getters: {},
mutations: {},
actions: {}
}
// 创建 moduleB.js
const moduleB = {
state: {
name: 'sxm',
age: 22
},
getters: {},
mutations: {},
actions: {}
}
// 在index.js中要import
modules: {
a: moduleA,
b: moduleB
}
第二步:在对应的组件中获取并显示在页面上
<p>{{$store.state.a.age}}</p>
<p>{{$store.state.b.age}}</p>
辅助函数:设置为组件内的computed、method
- mapState
第一步:在对应的组件中从vuex取出mapState
import {mapState} from 'vuex';
获取仓库store里的状态
computed: {
...mapState([
'age'
])
}
第二步:在对应的组件中获取并显示在页面上
<p>{{age}}</p>
- mapGetters
第一步:在对应的组件中从vuex取出mapGetters
import {mapGetters} from 'vuex';
通过组件中的计算属性进行获取:
computed: {
...mapGetters([
'getAge'
])
}
第二步:在对应的组件中获取并显示在页面上
<p>{{getAge}}</p>
- mapMutations
第一步:在对应的组件中从vuex取出mapMutations
import {mapMutations} from 'vuex';
在组件的methods属性中获取仓库store中的mutations方法,然后在methods里对应的方法中执行也可以携带参数。
methods: {
add() {
// this.$store.commit('incre', {age: 1});
this.incre({age: 1});
},
// 相当于定义了一个 incre 方法
...mapMutations([
'incre'
])
}
- mapActions
第一步:在对应的组件中从vuex取出mapActions
import {mapActions} from 'vuex';
在组件的methods属性中获取仓库store中的actions方法,然后在methods里对应的方法中执行也可以携带参数。
methods: {
addAsyn() {
// this.$store.dispatch('increAsyn', {age: 1});
this.increAsyn({age: 1});
},
// 相当于定义了一个 increAsyn 方法
...mapActions([
'increAsyn'
])
}
13. vue-router
路由模式
- hash 模式:默认配置。
通过window.onhashchange
监听路由变化 - H5 history 模式:不带
#
,更好看(官方说法)。
通过history.pushState
和window.onpopstate
监听路由变化
两者选择
- 两者的url发生变化,会发生页面跳转,但不会刷新页面。
- to B的系统推荐
hash
,简单易用。 - to C的系统可以考虑
H5 history
,seo
更友好,但需要服务端支持。
基本使用、参数、懒加载
<!-- 一般在app.vue中 -->
<!-- 路由链接 -->
<router-link to="/">Home</router-link>
<!-- 路由占位符 -->
<router-view/>
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
// 路由懒加载
// /* webpackChunkName: "about" */ 将懒加载的组件按组,打包在异步块中
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
},
{
path: '/about1',
name: 'About1',
// 路由懒加载
// /* webpackChunkName: "about" */ 将懒加载的组件按组,打包在异步块中
component: () => import(/* webpackChunkName: "about" */ '../views/About1.vue')
},
{
path: '/pay',
name: 'Pay',
// 路由懒加载
// /* webpackChunkName: "pay" */ 将懒加载的组件按组,打包在异步块中
component: () => import(/* webpackChunkName: "pay" */ '../views/Pay.vue')
},
// 携带参数的路由
{
path: '/user/:id',
// 加载页面时,会一同加载
component: User
}
]
- 组件获取路由参数
<!-- 在路由组件中使用参数 -->
<div>User {{ $route.params.id }}</div>
<!-- 在js中使用 -->
this.$route.params.id