开篇词
最近一段时间,一直在做主题方面的工作。我们的主题,并不是简单切换一下颜色,或者排版变化这些,而是变化比较大的主题。比如说:主题1和主题2看起来完全不一样,功能甚至都不一样。这样,通过切换css就无法做到了,因此我思考良久,使用了如下2种方法。
动态改变主题
首先需要解决的是如何知道你需要显示哪个主题,并且可以动态切换。我选择的方法是queryString。
我们打开url的时候,可以在后面缀上?theme=xx,读取这个xx储存起来即可。
第一种办法:动态组件
当主题的路由并没有发生变化,仅是组件内部的样式,功能发生了变化,我们可以将一个组件复制一遍,修改完后,通过懒加载和动态组件实现。
// 页面组件
<template>
<div>
<component :is="themeName" />
</div>
</template>
<script>
export default{
name: 'Home',
components:{
theme1:()=>import('@/theme/theme1/a'),
theme2:()=>import('@/theme/theme2/a'),
},
computed:{
themeName(){
retun `theme${this.$store.state.themeId}`
}
}
}
</script>
在组件中,我将script部分抽离出来,因为大部分组件其实在逻辑上是相同。哪怕有一些不同,我们也可以直接在主题2的组件中更改,减少对主题1的影响。
//action.js
export default{
name:'Theme1',
....
}
<template>
<div class="theme1"></div>
</template>
<script>
import action from '../componentAction/action'
action.name='Theme1'
export default action
</script>
<style scoped>
</style>
这样实现的有点是可以通过子组件的style scoped实现样式隔离,同时功能数据上都会隔离,例如两个子组件中的swiper不会相互影响。 同时,懒加载也减小了首页的加载时体积。 后面再增加新增的主题也只是照猫画虎而已。
第二种办法,路由隔离
路由隔离其实就是简单的theme1写一个路由的数组,theme2写一套路由。
// router.js
{
path:'/theme3',
name:'theme3Index',
component: () => import('../views/theme3/Index.vue'),
children:[
{
path: '/theme3/entry',
name: 'theme3Entry',
component: () => import('../views/theme3/entry.vue'),
}
]
}
这种办法其实是下下之策,我使用这个主要是因为路由变化了,比如之前是直接进入a.vue,但是现在前面多加了一层entry页面,所以只能改变路由。 这种办法也实现了比较好的隔离。
总结
以上两种思路是我针对于我们当前业务的思考,仅供参考。
其实这两种方法都有一个共同的问题,就是代码冗余。每个组件都避不可免的带有一部分之前主题的代码,虽然,大部分逻辑代码可以抽离出来,但是css和template却无法抽离。
如果每次一个主题增加一个dom,一个功能块,如果每次都用v-if,那么其实代码以后会更加难以维护。因此,我选择了按照主题去划分代码。