V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zuicaidenage
V2EX  ›  前端开发

拜托 vue 的小伙伴们帮忙看个问题

  •  
  •   zuicaidenage · 2019-01-18 12:36:33 +08:00 · 3158 次点击
    这是一个创建于 2140 天前的主题,其中的信息可能已经有所发展或是发生改变。

    现在我的页面上有个 select

    <select type="text" class="form-control" v-bind="chooseItem" v-on:change="changeApp($event.target.value)">
           <option value="" selected="selected">-- 应用来源 --</option>
           <option v-for="item in channelList" :value="item.id" v-text="item.name"></option>
    </select>
    

    我绑定了一个 chooseItem data 为 chooseItem:{}, 然后我的 methods 里有两个方法

    add: function () {
                    this.editLayer.display = true;
                    // this.chooseItem = {};
                    // this.chooseItem.app = "";
                },
    changeApp: function(val){
                  this.$set(this.chooseItem,'app',val)
                }
    

    add 方法调用后会展示这个选择框

    我写了个 computed

    computed : {
              productList:function(){
                if(app == '**') {
                  return this.products[0]
                }else if (app == '***') {
                  return this.products[1]
                }else {
                  return {}
                }
              }
            },
    

    我发现如果我注释掉 methods 里的this.chooseItem.app = "";时,我的 computed 才会随着 select 的切换改变值,不加注释的话 computed 就毫无反应,不过这是什么原因呢?难道是这行代码使 chooseItem.app 变成了非响应式属性嘛?

    第 1 条附言  ·  2019-01-18 16:15:01 +08:00
    computed 里少粘了一行代码
    `let app = this.channelList.filter(t=>t.id==this.chooseItem.app)[0]`

    我就是有个选择框,我想要根据选择框选的值来确定第二个选择框的选项,所以我利用了 computed 属性来根据第一个选择框的值的变化来计算出第二个选择框的选项,现在我注释掉上面说的那行代码就是可以的

    我自己手写了个 demo
    https://v2it.cn/computed.html
    第 2 条附言  ·  2019-01-18 16:19:20 +08:00
    <!DOCTYPE html>
    <html lang="en" dir="ltr">
    
    <head>
      <meta charset="utf-8">
      <title>hello</title>
      <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
      <style media="screen">
        .hide {
          display: none
        }
      </style>
    </head>
    
    <body>
      <div id="demo">
        <div id="selectDiv" class="hide">
          <select type="text" class="form-control" v-bind="obj.a" v-on:change="change($event.target.value)" >
            <option value="" select='selected'></option>
            <option value="b">b</option>
            <option value="c">c</option>
            <option value="d">d</option>
          </select>
          <p>{{c}}</p>
        </div>
        <button type="button" name="button" @click='showDiv()' value="show">show</button>
      </div>
    </body>
    <script type="text/javascript">
      var demo = new Vue({
        el: '#demo',
        data: {
          obj: {},
          test: ''
        },
        computed: {
          c: function() {
            return this.obj.a+" computed"
          }
        },
        methods: {
          change(val) {
            this.$set(this.obj, 'a', val)
          },
          showDiv(){
            this.obj={}
            // this.obj.a=''   这行注释掉的话切换选择框计算属性是有效的,去掉注释就不行
            document.getElementById('selectDiv').removeAttribute('class')
          }
        }
      })
    </script>
    
    </html>
    
    13 条回复    2019-01-19 16:02:34 +08:00
    corkspin
        1
    corkspin  
       2019-01-18 12:50:50 +08:00
    对象变了吧,监听不到 property 的变化
    FakeLeung
        2
    FakeLeung  
       2019-01-18 12:59:23 +08:00
    修改对象要用 $set。试试。
    shintendo
        3
    shintendo  
       2019-01-18 13:08:08 +08:00
    你的 data 是怎么定义的?
    zuicaidenage
        4
    zuicaidenage  
    OP
       2019-01-18 13:39:39 +08:00
    @FakeLeung `this.$set(this.chooseItem,'app',val)` 就是这行吧
    zuicaidenage
        5
    zuicaidenage  
    OP
       2019-01-18 13:40:03 +08:00
    @shintendo chooseItem: {}
    zuicaidenage
        6
    zuicaidenage  
    OP
       2019-01-18 13:40:37 +08:00
    @corkspin 只是 chooseItem 的属性变了吧
    shintendo
        7
    shintendo  
       2019-01-18 15:20:20 +08:00
    没看懂你的 computed 里面的 app 这个变量是哪来的,跟 chooseItem.app 什么关系。
    只说一下,只有定义在 data 里面的属性是响应式的,后续用$set 新加的属性也是响应式的,直接用.赋值的属性不是响应式的。
    好的实践是尽可能地把要用到的变量和属性都在 data 里面定义出来。
    nekoneko
        8
    nekoneko  
       2019-01-18 15:58:44 +08:00
    真的没看懂想干嘛。。。。
    zuicaidenage
        9
    zuicaidenage  
    OP
       2019-01-18 15:59:34 +08:00
    @shintendo 代码删多了。。 `let app = this.channelList.filter(t=>t.id==this.chooseItem.app)[0]`
    corkspin
        10
    corkspin  
       2019-01-18 19:30:38 +08:00
    // this.obj.a='' 这行注释掉的话切换选择框计算属性是有效的,去掉注释就不行
    corkspin
        11
    corkspin  
       2019-01-18 19:33:11 +08:00
    // this.obj.a='' 这行注释掉的话切换选择框计算属性是有效的,去掉注释就不行
    动态增加属性,不能监听。change 方法里的这个 this.$set(this.obj, 'a', val)检查到已经有了的属性也不会监听。
    所以应该就这样了吧
    Trim21
        12
    Trim21  
       2019-01-18 20:28:03 +08:00 via Android
    在 data 里给 obj.a 加一个默认值就好了
    zuicaidenage
        13
    zuicaidenage  
    OP
       2019-01-19 16:02:34 +08:00 via iPhone
    多谢楼上两位指点
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1390 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 23:42 · PVG 07:42 · LAX 15:42 · JFK 18:42
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.