前端:Vue学习-4
1. 组件缓存 keep-alive
keep-alive是vue的内置组件,当它包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。keep-alive是一个抽象组件:它自身不会渲染成一个dom元素,也不会出现在父组件当中。
keep-alive的优点是,在组件切换过程中,把切换出去的组件保留在内存中,防止重复渲染dom,减少加载时间及性能消耗,提高用户体验。
keep-alive三个属性:include被缓存的组件、exclude不被缓存的组件、max最多可以缓存的组件实例。
<template>
<div id="app">
<keep-alive :include="p">
<router-view></router-view>
</keep-alive>
</div>
</template>
<script>
export default {
name: 'App',
data(){
return{
p:['Home']
}
},
components: {
}
}
</script>
<script>
export default {
name:'Home',
created(){
console.log('组件被加载');
},
mounted(){
console.log('组件dom渲染完了');
},
destoryed(){
console.log('组件被销毁');
},
activated(){
console.log('组件被激活时触发!');
},
deactivated(){
console.log('组件失活时被触发!');
}
}
</script>
运行结果:
不过上述这个运行结果中keep-alive起是起作用了,但是存在一个问题就是回到列表组件时,重新刷新了以下当前页面,不知道什么原因?。。。
组件被缓存后,created、mounted、destoryed函数就不会被触发。所以提供了activated和deactivated,activated表示组件被激活时触发,而deactivated是组件失活时触发。
2. 状态管理工具 - Vuex
vue2 vue-router3 vuex3
vue3 vue-router4 vuex4
vuex是一个vue的状态管理工具,状态就是数据,可以管理vue通用的数据(多组件共享的数据)。
安装命令为:
npm install vuex@3
项目下创建目录store,并在该目录下创建文件index.js
,index.js里的代码如下:
import Vue from "vue"
import Vuex from "vuex"
Vue.use(Vuex);
// 插件安装
const vuex = new Vuex.Store();
// 创建仓库
export default vuex
// 导出
在mian.js中导入即可。
import store from '@/store/index'
new Vue({
render: h => h(App),
store
}).$mount('#app')
2.1 vuex 提供数据&使用数据 - mapState
提供数据在Vuex.Store对象添加state属性即可。
const store = new Vuex.Store({
state:{
count:101
}
});
使用数据$store.state.xxx
<p>{{$store.state.count}}</p>
或
created(){
console.log(this.$store.state.count);
}
mapState
另外可以通过辅助函数来使用数据。mapState,可以帮助我们把store中的数据自动映射到组件的计算属性上。
import {mapState} from 'vuex'
computed:{
...mapState(['count'])
}
// 计算属性
<p>{{count}}</p>
// 页面上进行渲染
2.2 mutations 修改数据 - mapMutations
vuex遵循单向数据流,组件中不能直接修改仓库的数据。
this.$store.state.count = 102
// 错误代码
上述代码vue并不会报错,可以在vuex配置中添加strict:true严格模式,这样就可以看到报错信息了。
const store = new Vuex.Store({
strict:true
});
因为不能直接修改store中的数据,那么也就是说需要在store中定义修改数据的方法,然后在组件中调用这个方法即可,直接在store对象上添加属性mutations对象,在这个下面定义方法即可。
const store = new Vuex.Store({
state:{
count:101
},
strict:true,
mutations:{
setCount(state){
state.count = 102
}
}
});
组件中调用使用 $store.commit(‘方法名’)
<button @click="$store.commit('setCount')">修改</button>
运行结果:
mutations传参,在mutations下定义方法,第一参数为:state,第二个参数就是我们需要传递的参数。调用方法时,使用 $store.commit(‘xxx’,参数)
setCount(state,n){
state.count += n
}
<button @click="$store.commit('setCount',2)">修改</button>
mutations下定义的方法有且只能有一个,如果需要传递多个,那么参数类型可以为对象或者数组。
mapMutations
把位于mutations中的方法提取出来,映射到组件methods中。
import {mapMutations} from 'vuex'
methods:{
...mapMutations(['setCount'])
},
<button @click="setCount(2)">修改</button>
2.3 actions - 异步操作 - mapActions
mutations必须是同步,修改state中的数据必须调用经过mutations,因此如果有异步操作需要修改state中值,那么需要在actions中调用mutations下的方法。调用actions下的方法使用 $store.dispatch(‘方法名’,参数)
const store = new Vuex.Store({
state:{
count:101
},
strict:true,
mutations:{
setCount(state,n){
state.count += n
}
},
actions:{
setAsycCount(context,n){
setTimeout(()=>{
context.commit('setCount',n);
},1000);
}
}
});
<button @click="$store.dispatch('setAsycCount',4)">1秒后修改数据</button>
运行结果:
mapActions
同mapState、mapMutations类似,直接在methods中添加对应映射即可。
import {mapActions} from 'vuex'
methods:{
...mapActions(['setAsycCount'])
},
<button @click="setAsycCount(4)">1秒后修改数据</button>
2.4 getters - 计算属性 - mapGetters
getters类似于计算属性,getters函数的第一个参数是state;函数必须有返回值。
const store = new Vuex.Store({
state:{
list:[1,2,3,4,5,6,7,8,9,10]
},
getters:{
filterList(state){
return state.list.filter(x => x > 5)
}
}
});
<p>{{($store.getters.filterList).join(',')}}</p>
mapGetters
computed:{
...mapGetters(['filterList'])
}
<p>{{filterList.join('|')}}</p>
3. Vuex 模块 modules - state,mutations,actions,getters
由于vuex使用单一状态树,应用的所有状态会集中到一个较大的对象。当应用变得非常复杂时,store对象就有可能变得相当臃肿。
某个模块 store/modules/user.js
const state = {}
const mutations = {}
const actions = {}
const getters = {}
export default {
state,
mutations,
actions,
getters
}
使用 store/index.js
import user from './modules/user.js'
const store = new Vuex.Store({
modules:{
user
}
})
1.state
分模块之后,子模块的状态是会挂载到根级别的state中,属性名就是模块名。
使用模块中的数据:
- 使用 $store.state.模块名.xxx
- 通过mapState映射,默认根级别的映射 mapSate([‘xxx’]),子模块的映射为mapState(‘模块名’,[‘xxx’]),需要开启命名空间
export default {
namespaced:true, // 开启命名空间
state,
mutations,
actions,
getters
}
const state = {
name:'zs'
}
使用原生方式进行访问
<p>{{$store.state.user.name}}</p>
使用mapState进行访问
computed:{
...mapState('user',['name'])
}
<p>{{name}}</p>
2.getters
使用模块中getters中的数据
- 直接通过 $store.getters[‘模块名/xxx’]
- 通过mapGetters映射,子模块的映射为mapGetters(‘模块名’,[‘xxx’]) - 需要开启命名空间
const getters = {
upperName(state){
return state.name.toUpperCase();
}
}
原生方式进行访问
<p>{{$store.getters['user/upperName']}}</p>
使用mapGetters进行访问
computed:{
...mapGetters('user',['upperName'])
}
<p>{{upperName}}</p>
3.mutations
默认模块中的mutations和actions会被挂载到全局,需要开启命名空间,才会挂载到子模块中。
- 直接通过store调用 $store.commit(‘模块名/xxx’,参数)
- 通过mapMutations映射,子模块的映射mapMutations(‘模块名’,[‘xxx’]),需要开启命名空间
const mutations = {
setName(state,newName){
state.name = newName;
}
}
使用原生进行修改
<button @click="$store.commit('user/setName','zl')">更新名字</button>
使用mapMutations进行修改
methods:{
...mapMutations('user',['setName'])
}
<button @click="setName('lz')">更新名字2</button>
运行结果:
4.actions
默认模块中的mutations和actions会被挂载到全局,需要开启命名空间,才会挂载到子模块中。
- 通过 $store.dispatch(‘模块名/xxx’,参数)
- 通过mapActions,子模块的映射为mapActions(‘模块名’,[‘xxx’]) - 需要开启命名空间
const actions = {
setSyncName(context,n){
setTimeout(()=>{
context.commit('setName', n);
},1000);
}
}
使用原生进行修改
<button @click="$store.dispatch('user/setSyncName','hh')">1秒后修改名字</button>
使用mapActions进行修改
methods:{
...mapActions('user',['setSyncName'])
}
<button @click="setSyncName('ll')">1秒后修改名字2</button>