vue组件库的在线主题编辑器的实现思路(2)

<div> <Color></Color> <Button></Button> <Radio></Radio> <Checkbox></Checkbox> <Inputer></Inputer> <Autocomplete></Autocomplete> <InputNumber></InputNumber> //... </div>

同时需要监听一下editingActionType值的变化来滚动到对应组件的位置:

<script> { watch: { '$store.state.editingActionType'(newVal) { this.scrollTo(newVal) } }, methods:{ scrollTo(id) { switch (id) { case 'Input': id = 'Inputer' break; default: break; } let component = this.$children.find((item) =>{ return item.$options._componentTag === id }) if (component) { let el = component._vnode.elm let top = el.getBoundingClientRect().top + document.documentElement.scrollTop document.documentElement.scrollTop = top - 20 } } } } </script>

编辑区域

编辑区域主要分为三部分,工具栏、选择栏、控件区。这部分是本项目的核心也是最复杂的一部分。

先看一下变量列表的数据结构:

{ "name": "Color",// 组件类型/类别 "config": [{// 配置列表 "type": "color",// 变量类型,根据此字段渲染对应类型的控件 "key": "$--color-brand",// sass变量名 "value": "#e72528",// sass变量对应的值,可以是具体的值,也可以是sass变量名 "category": "Brand Color"// 列表,用来分组进行显示 }] }

此列表是后端返回的,选择器的选项是遍历该列表取出所有的name字段的值而组成的。

vue组件库的在线主题编辑器的实现思路

因为有些变量的值是依赖另一个变量的,所依赖的变量也有可能还依赖另一个变量,所以需要对数据进行处理,替换成变量最终的值,实现方式就是循环遍历数据,这就要求所有被依赖的变量也存在于这个列表中,否则就找不到了,只能显示变量名,所以这个实现方式其实是有待商榷的,因为有些被依赖的变量它可能并不需要或不能可编辑,本项目目前版本是存在此问题的。

此外还需要和当前编辑中的主题变量的值进行合并,处理如下:

// Editor组件 async getVariable() { try { // 获取变量列表,res.data就是变量列表,数据结构上面已经提到了 let res = await api.getVariable() // 和当前主题变量进行合并 let curTheme = store.getUserThemeByNameFromStore(this.$store.state.editingTheme) || {} let list = [] // 合并 list = this.merge(res.data, curTheme.theme) // 变量进行替换处理,因为目前存在该情况的只有颜色类型的变量,所以为了执行效率加上该过滤条件 list = store.replaceVariable(list, ['color']) // 排序 list = this.sortVariable(list) this.variableList = list // 存储到vuex this.$store.commit('updateVariableList', this.variableList) } catch (error) { console.log(error) } }

merge方法就是遍历合并对应变量key的值,主要看replaceVariable方法:

function replaceVariable(data, types) { // 遍历整体变量列表 for(let i = 0; i < data.length; i++) { let arr = data[i].config // 遍历某个类别下的变量列表 for(let j = 0; j < arr.length; j++) { // 如果不在替换类型范围内的和值不是变量的话就跳过 if (!types.includes(arr[j].type) || !checkVariable(arr[j].value)) { continue } // 替换处理 arr[j].value = findVariableReplaceValue(data, arr[j].value) || arr[j].value } } return data }

findVariableReplaceValue方法通过递归进行查找:

function findVariableReplaceValue(data, value) { for(let i = 0; i < data.length; i++) { let arr = data[i].config for(let j = 0; j < arr.length; j++) { if (arr[j].key === value) { // 如果不是变量的话就是最终的值,返回就好了 if (!checkVariable(arr[j].value)) { return arr[j].value } else {// 如果还是变量的话就递归查找 return findVariableReplaceValue(data, arr[j].value) } } } } }

接下来是具体的控件显示逻辑,根据当前编辑中的类型对应的配置数据进行渲染,模板如下:

// Editor组件 <template> <div> <div v-for="items in data" :key="items.name"> <div>{{items.name}}</div> <ul> <li v-for="item in items.list" :key="item.key"> <div>{{parseName(item.key)}}</div> <Control :data="item" @change="valueChange"></Control> </li> </ul> </div> </div> </template>

data是对应变量类型里的config数据,是个计算属性:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/2407ad341903403c54dc75a997afe849.html