vue 通过 select的v-model绑定svg对象,选择option,select中的文本无法及时更新

问题描述

我想通过定义的一个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>
阅读 2.9k
推荐问题