2021.8.4
使用vuex4替换emit。进行组件化。
坑32(vuex4、keep-alive、el-tabs、标签页,缓存):背景是需要进行组件化,标签页组件将被多层嵌套,之后emit将不再适用(用起来需要多层传递)。
以下是之前的操作,主要使用emit传递打开着的标签页信息:
前传1(keep-alive基础使用): 踩坑记3 keep-alive 缓存、el-tabs 获取点击前后的参数 等_Alloom的博客-CSDN博客;
前传2(keep-alive+emit保存标签页打开着的组件): 踩坑记4 keep-alive、emit 仅保存标签页打开的组件_Alloom的博客-CSDN博客。
现在改用vuex4。首先是目录结构,新建store文件(与router文件平级),内新建index.js、mutations.js、actions.js文件以及modules.js文件夹(内放模块文件,例如layout.js)。actions.js和module.js暂时未用到。参考: 项目结构 | Vuex (vuejs.org)
以下是index.js,keepComponents即为保存缓存的组件名数组,该文件导出将作为store使用:
import { createStore } from 'vuex'
import mutations from './mutations'
// import actions from './actions'
// import layoutModule from './modules/layout'
const state={
keepComponents: ['Index']
}
const store = createStore({
state,
mutations,
// actions,
// modules:{
// layout:layoutModule
// }
})
export default store
以下是mutations.js,接收tabs信息(之后可能还会用于其他信息提取及存储,故而整体传输),改变keepComponents的值,该文件会被导入到index.js中:
const mutations={
tabsChanged(state, payload){
//tabs的name转化为components的name
state.keepComponents=payload.tabList.map(tab=>
tab.name.split('-')
.map(n=>{
n=n[0].toUpperCase()+n.slice(1)
return n
})
.join(''))
}
}
export default mutations
另外需要在main.js中增加导入import store from './store/index'和使用app.use(store)。
而组件中使用,首先必须导入import { useRouter } from 'vue-router'。
在使用el-tabs的文件内,当tabs改变后,调用commit提交mutation:
// 提交tabs改变后的信息给store,用于更新keep-alive保存的组件列表
store.commit('tabsChanged',{
tabList: tabList.value
})
在使用keep-alive的文件中,读取keepComponents及使用:
//setup()中
return {
keepComponents:computed(()=>store.state.keepComponents)
}
//template中
<router-view v-slot="{ Component }">
<keep-alive :include="keepComponents">
<component :is="Component" />
</keep-alive>
</router-view>
坑33(el-breadcrumb、props):尝试了面包屑的组件化,可以达成目标效果,但最终放弃了此方案。该面包屑用于显示当前页面路径。
放弃原因:面包屑组件化后,需要从父组件通过props传值(因为设计上路由信息是在父组件中声明的router.afterEach()中获取),传递的是当前嵌套的路由;在组件化前,该路由信息直接由el-breadcrumb获取进行响应式渲染;而组件化后,其经历了props传递、computed添加响应性、由el-breadcrumb获取这几个步骤才得以渲染。
记录一下子组件读取及更新props的方法,以下是script中部分代码:
<script>
import { computed } from 'vue'
export default {
name:'Breadcrumb',
props:{
matchedRoutes:Array
},
setup(props){
const state=reactive({
matchedRoutes:[]
})
return {
matchedRoutes:computed(()=>props.matchedRoutes)
}
}
}
</script>
by 莫得感情踩坑机(限定)