一周的时间,几乎每天都要工作十几个小时,敲代码+写作文,界面原型算是完成了,下一步是写内核的HTML处理引擎,纯JS实现。本次实战展示告一段落,等RXEditor下一个版本完成,再继续分享吧。
剩下的功能:标签式输入、名值对输入、对话框(modal dialog),边框输入,全部完成。
演示地址:https://vular.cn/studio-ui/
css class输入,样式跟属性输入,效果:
对话框(model dialog效果)
前几期功能效果总览:
标签输入框用来输入CSS class,名字一如既往的好听,就叫RxLabelInput吧。
输入值一个数组,因为有多处要操作数组,增、删、改、克隆、比较等。比较好的一个方式是把Array类用继承的方式重写一下,把这写方法加到里面。但是RXEidtor内核用纯JS实现,并放在一个iFrame里面,它跟主界面只能通过windows message传递数据,带有方法的类无法作为消息被传递,暂时先不用这个方法,只把相关功能抽取成独立函数,放在valueOperate.js里面。
如果以后数组操作量更大,再考虑转成一个通用的数组类。
前几期介绍过,使用计算属性changed来标识数据是否被修改过,changed计算属性内部,需要比较两个值是否相等,普通字符串不会有问题,要比较数组用这样的方式最方便,先排序、转成字符串、比较字符串:
aValue.sort().toString() === bValue.sort().toString()
数组的sort方法会改变原来的数组值,会引发数据刷新,从而再次调用计算属性,形成死循环,调试了很长时间,就算空数组也会死循环。所以,需要把数据复制一份出来,再比较:
if(Array.isArray(a) && Array.isArray(b)){
//复制数组
let aValue = a.concat()
//复制数组
let bValue = b.concat()
//比较数组
return aValue.sort().toString() === bValue.sort().toString()
}
组件代码:
<template>
<div class="label-list">
<div
class="label-item"
v-for = "val in inputValue"
>
{
{
val}}
<span
class="remove-button"
@click="remove(val)"
>×</span>
</div>
<div style="width: 100%"></div>
<div class="add-button"
@click="addClick"
>+</div>
<div style="width: 100%"></div>
<input
v-show="isAdding"
v-model="newValue"
autofocus="autofocus"
:placeholder="$t('widgets.enter-message')"
@keyup.13 = "finishAdd"
ref="inputControl"
/>
</div>
</template>
<script>
import {
addToArray, removeFromArray} from './valueOperate'
export default {
props:{
value:{
default:[] },
},
computed:{
inputValue: {
get:function() {
return this.value;
},
set:function(val) {
this.$emit('input', val);
},
},
},
data () {
return {
isAdding : false,
newValue : '',
}
},
methods: {
addClick(){
this.isAdding = true;
this.$refs.inputControl.style.display = 'block'
this.$refs.inputControl.focus()
},
finishAdd(){
if(this.newValue){
this.newValue.split(' ').forEach((val)=>{
if(val){
addToArray(val, this.inputValue)
}
})
this.newValue = ''
}
this.isAdding = false
},
remove(val){
removeFromArray(val, this.inputValue)
}
},
}
</script>
<style>
.label-list{
background: rgba(0,0,0, 0.15);
display