异步动态加载组件数据

背景

在vue项目中,父组件一些数据是通过接口异步获取的,然后子组件通过Props 父子之间通信,父组件和子组件加载的顺序
父beforeCreate=>父created=>父beforeMount=>父beforeCreate=>子created=>子beforeMount=>子mounted=>父mounted
由于父组件的数据是异步的过来的,可会出现父组件还没有获取到数据,子组件就已经加载完毕。导致子组件没有得到最新数据。

模拟异常代码

父组件





    
    
    
    异步组件渲染vue1.x版本
    



    
{{batchId}}

子组件

// 定义一个名为 button-counter 的新组件
Vue.component('button-counter', {
    props: ['name'],
    template: '#displayBatch',
    data: function () {
        return {
            count: 0,
            info:""
        }
    },
    ready: function () {
        this.$nextTick(function () {//节点最新更新后执行
            this.loadData();
            console.log("info" + this.info)
          })
        
    },
    methods: {
        loadData: function() {
            setTimeout(() => {
                this.info = this.name + "uuuuu";
                console.log("info" + this.info)
            },100) 
        }
    }

})

效果:子组件没有显示abcuuuuu;而是nulluuuuu

解决方案

Vue1.x版本

  1. v-if
{{batchId}}

这个可以说是很经典的一个办法,但是会有展示上的问题,即dom结构会先消失而后重新渲染
并不算是一个完美的解决方案,所以暂时Pass掉

  1. 异步组件
Vue.component('button-counter', function(resolve, reject) {
    setTimeout(() => {
        resolve({
            props: ['name'],
            template: '#displayBatch',
            data: function () {
                return {
                    count: 0,
                    info:""
                }
            },
            ready: function () {
                this.$nextTick(function () {
                    this.loadData();
                    console.log("info" + this.info)
                  })
                
            },
            methods: {
                loadData: function() {
        
                    setTimeout(() => {
                        this.info = this.name + "uuuuu";
                        console.log("info" + this.info)
                    },50) 
                }
            }
        
        })
    }, 310);//这个时间理论上可以定义0;因为ajax请求时微观任务,setTimeout是宏观任务;这里为了方便测试设置比300大 就可以
}) 

  1. 监听watch;
    两个方式:子组件可以监听,父组件也可以监听
    子组件实现方式
// 定义一个名为 button-counter 的新组件
Vue.component('button-counter', {
    props: ['name'],
    data: function () {
        return {
            count: 0,
            info:""
        }
    },
    watch:{
        name: function(newVal,oldVal) {
            console.log(newVal)
            if(newVal) {
                // console.log(this.$refs.testbutton.loadData());
                this.loadData();
            }
        }
    },
    methods: {
        loadData: function() {

            setTimeout(() => {
                this.info = this.name + "uuuuu";
            
            },100) 
        }
    },

    template: ''
})

父组件实现方式

 watch: {
    batchId: function(newVal, oldVal) {
        if(newVal) {
            this.$refs.testbutton.loadData();
        }

    }
},
  1. forceUpdate 方法
    父组件
watch: {
    batchId: function(newVal, oldVal) {
        if(newVal) {
            // this.$refs.testbutton.loadData();
            this.$refs.testbutton.$forceUpdate();
        }

    }
},

子组件

    updated: function(){
            console.log("updated")
            this.loadData();
        },

扩展

咋样友好重新渲染组件?
http://www.muzhuangnet.com/show/54308.html

总结

解决问题本质,就是让子组件在父组件数据变化时,要让子组件感知到,强制渲染子组件;
使用v-if 效果最不好,不推荐使用。(但是这个方法是不要动之前已经封装好的子组件)

你可能感兴趣的:(异步动态加载组件数据)