问题描述
我想通过定义的一个svgGroup对象递归渲染svg对象,然后通过一个select标签选中对应的svg元素,再通过旁边的输入框动态修改svg对象的属性
- 现在出现的问题是,点击select的option之后v-model绑定的属性
selectSvg
立即被修改,但是select的文本不会修改。
- 但是当你点击select的
同样的option
两次之后文本内容就会变化### 问题描述
- 上代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>transform属性</title>
</head>
<body>
<div id="app">
<form @submit.prevent="">
<fieldset>
<legend>Transform属性</legend>
<select v-model="selectSvg">
<option :key="index" :value="item.ref" v-for="(item, index) in flatSvgGrpTpl">
{{item.label}}
</option>
</select>
<input type="text" v-model="transform">
<span>{{expandTransform}}</span>
</fieldset>
<div></div>
</form>
<hr>
<div style="text-align: center ">
<svg height="600" viewBox="-80 -80 600 600" width="600">
<defs>
<g id="coordinate">
<rect :width="coordinateWidth" height="1" x="0" y="-0.5"></rect>
<circle :cx="(idx - 1) * (coordinateWidth / coordinateGap) + ''" cy="0" r="2.5"
v-for="idx in coordinateGap"></circle>
<text :x="(idx - 1) *(coordinateWidth / coordinateGap)" v-for="idx in coordinateGap"
y="0">{{(idx -1) * (coordinateWidth / coordinateGap)}}
</text>
<rect :transform="`translate(${coordinateWidth} 0) rotate(-150)`" height="1"
width="20"></rect>
<rect :transform="`translate(${coordinateWidth} 0) rotate(150)`" height="1"
width="20"></rect>
</g>
<g id="coordinateGroup">
<use xlink:href='#coordinate'></use>
<use transform="rotate(90)" xlink:href='#coordinate'></use>
</g>
</defs>
<svg-grp-tpl :data="svgGroup" :idx="0" ref="svgGrpTpl"></svg-grp-tpl>
</svg>
</div>
</div>
<template id="svgGrpTpl">
<g>
<g :id="item.name" :ref="item.name" v-for="item in data">
<use xlink:href="#coordinateGroup"></use>
<text>{{item.name}}</text>
<svg-grp-tpl :data="item.children" v-if="item.children"></svg-grp-tpl>
</g>
</g>
</template>
</body>
<script src="js/vue.js"></script>
<script>
// 注册一个全局组件
var svgGrpTpl = Vue.extend({
name: 'svgGrpTpl',
template: '#svgGrpTpl',
data() {
return {}
},
props: {
data: Array,
idx: Number
}
});
var app = new Vue({
el: '#app',
components: {svgGrpTpl: svgGrpTpl},
data: {
transform: '',
coordinateWidth: 500,
coordinateGap: 10,
colorList: ['#4ea397', '#22c3aa', '#7bd9a5', '#d0648a'],
// 子组件元素dom节点的数组
svgGroup: [{
name: 'a',
label: undefined,
ref: undefined,
children: [{
name: 'c',
label: undefined,
ref: undefined,
children: [{
name: 'd',
label: undefined,
ref: undefined
}]
}]
}, {
name: 'b',
label: undefined,
}],
// 选中的svg对象
selectSvg: null
},
mounted() {
// 设置svgGroup对应挂载的Svg-Group-Tpl
const iter = (data, vm, depth) => {
data.forEach && data.forEach((item, idx) => {
const curVm = vm.length ? vm[idx] : vm;
item.ref = curVm.$refs[item.name][0];
item.label = new Array(depth + 1).join('└') + item.name;
item.children && iter(item.children, curVm.$children, ++depth);
}
)
};
iter(this.svgGroup, this.$refs.svgGrpTpl, 0);
// 设置默认选中的svg
this.selectSvg = this.svgGroup[0].ref
},
methods: {},
computed: {
expandTransform() {
const cmd = {
t: 'transform',
r: 'rotate',
s: 'scale'
};
// [t, r, s] => \b([trs])\b
var r = new RegExp('\\b([' + Object.keys(cmd).join('') + '])\\b', 'g');
return this.transform.replace(r, word => cmd[word])
},
// 递归结构的this.svgGrpTpl转为数组
flatSvgGrpTpl() {
const ret = [];
const iter = list => {
list.forEach(item => {
ret.push(item);
item.children && iter(item.children)
})
};
iter(this.svgGroup);
return ret
}
}
})
</script>
</html>
this.$set(obj,key,value)