账号密码登录
微信安全登录
微信扫描二维码登录

登录后绑定QQ、微信即可实现信息互通

手机验证码登录
找回密码返回
邮箱找回 手机找回
注册账号返回
其他登录方式
分享
  • 收藏
    X
    vue 通过 select的v-model绑定svg对象,选择option,select中的文本无法及时更新
    171
    0

    问题描述

    我想通过定义的一个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>
    
    1
    打赏
    收藏
    点击回答
    您的回答被采纳后将获得:提问者悬赏的 10 元积分
        全部回答
    • 0
    更多回答
    扫一扫访问手机版
    • 回到顶部
    • 回到顶部