美文网首页
异步动态加载组件数据

异步动态加载组件数据

作者: Raral | 来源:发表于2022-09-13 16:40 被阅读0次

背景

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

模拟异常代码

父组件

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>异步组件渲染vue1.x版本</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js"></script>
</head>

<body>
    <div id="app">{{batchId}}
        <button-counter ref="testbutton" :name="batchId"></button-counter>
    </div>

</body>
<template id="displayBatch" style="display: none;">
    <button id="testbutton" >{{info}}</button>
</template>
<script src="./component.js"></script>
<script>
    let vm2 = new Vue({
        el: "#app",
        data: {
            msg: "123123",
            batchId: null
        },
        ready: function () {
           this.test1();
        },
        methods: {
            test1: function () {
                let _this = this;
                setTimeout(() => {
                    console.log("异步1")
                    _this.batchId = "abc";
                }, 300);//模拟:延迟时间一定要比子组件数据长,否则复现不了
            }
        }

    })

</script>

</html>

子组件

// 定义一个名为 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
<div id="app">{{batchId}}
        <button-counter v-if="batchId != null " :name="batchId"></button-counter>
    </div>

这个可以说是很经典的一个办法,但是会有展示上的问题,即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: '<button ref="testbtn">{{info}}</button>'
})

父组件实现方式

 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 效果最不好,不推荐使用。(但是这个方法是不要动之前已经封装好的子组件)

相关文章

  • 异步动态加载组件数据

    背景 在vue项目中,父组件一些数据是通过接口异步获取的,然后子组件通过Props 父子之间通信,父组件和子组件加...

  • (异步)动态加载组件

    1、使用创建组件工厂的方式 普遍写法 创建组件工厂 viewContainer创建组件 2、ng-cont...

  • vue中异步组件实现动态挂载

    本篇文章很简单,我们主要想说明两个问题 动态组件Component 和 异步加载组件。 一、常用的组件加载方式 首...

  • 【Vue3 从入门到实战 进阶式掌握完整知识体系】017-探索组

    8、动态组件和异步组件 动态组件 运行结果 内容缓存 运行结果 异步组件 运行结果

  • Vue里的nextTick方法

    需要先异步动态加载数据后,然后使用v-for渲染节点,再执行插件的滑动轮播行为。解决这个问题,我们通过在组件中使用...

  • webpack打包优化 - 懒加载

    webpack 懒加载 分割代码会产生chunk,异步加载的时候也会产生chunk 引入动态数据 -> 懒加载(当...

  • Python 实战:week1 爬取霉霉图片

    运行效果: 作业代码: 项目代码 小结 异步加载 通过 JS 实现动态加载数据,在与当前 HTML 页面的加载并不...

  • vue-01

    vue+webpack 优化 一.异步加载 1.异步加载组件,其实就是组件懒加载。可以理解为:当我需要使用组件的时...

  • react记录 二

    目录 一.react异步加载组件,分模块加载,提高打开性能 二. 三. 四. 一.react异步加载组件,分模块加...

  • loading data dynamically and as

    .py .html .js 异步加载数据,动态追加元素到页面,动态生成html标签中的内容。好处:It just ...

网友评论

      本文标题:异步动态加载组件数据

      本文链接:https://www.haomeiwen.com/subject/quclortx.html