组件这种情况怎么双向绑定数据?

<template>
    <div id="test">
       <counter v-if="modelLock"></counter>
    </div>
</template>

<script>
  import Vue from 'vue'
  
  
  export default {
     name:'Test',
     data(){
       return {
          modelLock:false,
          obj:{},
          templateModal:''
       }
     },
     created() {
       this.obj={
          list:[
             { text:11111 },
             { text:22222 },
             { text:33333 }
          ]
       }
       this.templateModal ='<div><span v-for="item in data.list">{{item.text}}</span></div>'
       this.templateInit(this.obj, this.templateModal)
  
       var that = this
       setTimeout(function(){
         that.obj={
           list:[
                 { text:4444 },
                 { text:5555 },
                 { text:6666 }
           ]
         }
       },3000)
       
       
     },
     methods:{
        templateInit(data,temp){
           Vue.component("counter",{
               data:function(){
                  return{
                     data: data
                  }
               },
               template:temp,
               methods:{
                  showFn(item){
                     alert(item.text)
                  }
               }
           })
           this.modelLock = true
        }
     }
  }  
</script>








如题上面这种写法无法双向绑定

that.obj={
           list:[
                 { text:4444 },
                 { text:5555 },
                 { text:6666 }
           ]
         }

而这种写法却可以

that.obj.list =[
                 { text:4444 },
                 { text:5555 },
                 { text:6666 }
           ] 

这样写能双向绑定,有什么办法让这种写法也能双向绑定

that.obj={
           list:[
                 { text:4444 },
                 { text:5555 },
                 { text:6666 }
           ]
         }

因为我obj里的数据从接口获取是未知的,现在组件里的数据只绑定一次
求指教

阅读 2.2k
3 个回答
 var that = this
 setTimeout(function () {
   that.$set(that.obj, 'list', [{ text: 4444 }, { text: 5555 }, { text: 6666 }])
 }, 3000)

可以通过Vue 提供的set方法实现,Vue set

Vue2 无法检测 property 的添加或移除。由于 Vue 会在初始化实例时对 property 执行 getter/setter 转化,所以 property 必须在 data 对象上存在才能让 Vue 将它转换为响应式的

可以考虑在obj上在包上一层,以防止替换counter的整个data后响应式失效
参考代码

<template>
  <div id="test">
    <counter v-if="modelLock"></counter>
  </div>
</template>

<script>
import Vue from "vue";

export default {
  name: "Test",
  data() {
    return {
      modelLock: false,
      obj: {},
      templateModal: "",
      counterReactiveData: {
        obj: { list: [{ text: 11111 }, { text: 22222 }, { text: 33333 }] },
      },
    };
  },
  created() {
    this.templateModal =
      '<div><span v-for="item in data.obj.list">{{item.text}}</span></div>';
    this.templateInit(this.counterReactiveData, this.templateModal);

    var that = this;
    setTimeout(function () {
      that.counterReactiveData.obj = {
        list: [{ text: 4444 }, { text: 5555 }, { text: 6666 }],
      };
    }, 3000);
  },
  methods: {
    templateInit(data, temp) {
      Vue.component("counter", {
        data: function () {
          return {
            data: data,
          };
        },
        template: temp,
        methods: {
          showFn(item) {
            alert(item.text);
          },
        },
      });
      this.modelLock = true;
    },
  },
};
</script>

官方定义:

Vue 不允许在已经创建的实例上动态添加新的根级响应式属性 (root-level reactive property)。然而它可以使用 Vue.set(object, key, value) 方法将响应属性添加到嵌套的对象上:

this.$set( this.obj, 'list', [{ text: 4444 }, { text: 5555 }, { text: 6666 }])
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题