{ computed: { data() { // 找出当前编辑中的变量类别 let _data = this.$store.state.variableList.find(item => { return item.name === this.$store.state.editingActionType }) if (!_data) { return [] } let config = _data.config // 进行分组 let categorys = [] config.forEach(item => { let category = categorys.find(c => { return c.name === item.category }) if (!category) { categorys.push({ name: item.category, list: [item] }) return false } category.list.push(item) }) return categorys } } }
Control是具体的控件显示组件,某个变量具体是用输入框还是下拉列表都在这个组件内进行判断,核心是使用component动态组件:
// Control组件 <template> <div> <component :is="showComponent" :data="data" :value="data.value" @change="emitChange" :extraColorList="extraColors"></component> </div> </template> <script> // 控件类型映射 const componentMap = { color: 'ColorPicker', select: 'Selecter', input: 'Inputer', shadow: 'Shadow', fontSize: 'Selecter', fontWeight: 'Selecter', fontLineHeight: 'Selecter', borderRadius: 'Selecter', height: 'Inputer', padding: 'Inputer', width: 'Inputer' } { computed: { showComponent() { // 根据变量类型来显示对应的控件 return componentMap[this.data.type] } } } </script>
一共有颜色选择组件、输入框组件、选择器组件、阴影编辑组件,具体实现很简单就不细说了,大概就是显示初始传入的变量,然后修改后触发修改事件change,经Control组件传递到Editor组件,在Editor组件上进行变量修改及发送编译请求,不过其中阴影组件的实现折磨了我半天,主要是如何解析阴影数据,这里用的是很暴力的一种解析方法,如果有更好的解析方式的话可以留言进行分享:
// 解析css阴影数据 // 因为rgb颜色值内也存在逗号,所以就不能简单的用逗号进行切割解析 function parse() { if (!this.value) { return false } // 解析成复合值数组 // let value = "0 0 2px 0 #666,0 0 2px 0 #666, 0 2px 4px 0 rgba(0, 0, 0, 0.12), 0 2px 4px 0 hlsa(0, 0, 0, 0.12),0 2px 4px 0 #sdf, 0 2px 4px 0 hlsa(0, 0, 0, 0.12), 0 2px 0 hlsa(0, 0, 0, 0.12), 0 2px hlsa(0, 0, 0, 0.12), 0 2px 4px 0 hlsa(0, 0, 0, 0.12)" // 根据右括号来进行分割成数组 let arr = this.value.split(/\)\s*,\s*/gim) arr = arr.map(item => { // 补上右括号 if (item.includes('(') && !item.includes(')')) { return item + ')' } else {// 非rgb颜色值的直接返回 return item } }) let farr = [] arr.forEach(item => { let quene = [] let hasBrackets = false // 逐个字符进行遍历 for (let i = 0; i < item.length; i++) { // 遇到非颜色值内的逗号直接拼接目前队列里的字符添加到数组 if (item[i] === ',' && !hasBrackets) { farr.push(quene.join('').trim()) quene = [] } else if (item[i] === '(') {//遇到颜色值的左括号修改标志位 hasBrackets = true quene.push(item[i]) } else if (item[i] === ')') {//遇到右括号重置标志位 hasBrackets = false quene.push(item[i]) } else {// 其他字符直接添加到队列里 quene.push(item[i]) } } // 添加队列剩余的数据 farr.push(quene.join('').trim()) }) // 解析出单个属性 let list = [] farr.forEach(item => { let colorRegs = [/#[a-zA-Z0-9]{3,6}$/, /rgba?\([^()]+\)$/gim, /hlsa?\([^()]+\)$/gim, /\s+[a-zA-z]+$/] let last = '' let color = '' for (let i = 0; i < colorRegs.length; i++) { let reg = colorRegs[i] let result = reg.exec(item) if (result) { color = result[0] last = item.slice(0, result.index) break } } let props = last.split(/\s+/) list.push({ xpx: parseInt(props[0]), ypx: parseInt(props[1]), spread: parseInt(props[2]) || 0, blur: parseInt(props[3]) || 0, color }) }) this.list = list }
回到Editor组件,编辑控件触发了修改事件后需要更新变量列表里面对应的值及对应主题列表里面的值,同时要发送编译请求:
// data是变量里config数组里的一项,value就是修改后的值 function valueChange(data, value) { // 更新当前变量对应key的值 let cloneData = JSON.parse(JSON.stringify(this.$store.state.variableList)) let tarData = cloneData.find((item) => { return item.name === this.$store.state.editingActionType }) tarData.config.forEach((item) => { if (item.key === data.key) { item.value = value } }) // 因为是支持颜色值修改为某些变量的,所以要重新进行变量替换处理 cloneData = store.replaceVariable(cloneData, ['color']) this.$store.commit('updateVariableList', cloneData) // 更新当前主题 let curTheme = store.getUserThemeByNameFromStore(this.$store.state.editingTheme, true) if (!curTheme) {// 当前是官方主题则创建新主题 let theme = store.createNewUserTheme('', { [data.key]: value }) this.$store.commit('updateEditingTheme', theme.name) } else {// 修改的是自定义主题 curTheme.theme.common = { ...curTheme.theme.common, [data.key]: value } store.updateUserTheme(curTheme.name, { theme: curTheme.theme }) } // 请求编译 this.updateVariable() }
接下来是发送编译请求: