【Lecture】simpleMDE编辑器回显:子组件依赖父组件异步调用结果的解决

单组件时生命周期

在这里插入图片描述

1)初始化显示
beforeCreate() created() beforeMount() mounted() //这些方法只执行一次
2) 更新状态: this.xxx = value
beforeUpdate() updated() //可执行多次
3) 销毁 vue实例:vm.$destory()
beforeDestory() destoryed() //只执行一次

常用的生命周期方法
created()/mounted(): 发送ajax请求, 启动定时器等异步任务
beforeDestory(): 做收尾工作, 如: 清除定时器,订阅解绑

参考link

父子组件时生命周期

正常情况下,父子组件的生命周期顺序

加载渲染过程
  父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted
子组件更新过程
  父beforeUpdate->子beforeUpdate->子updated->父updated
父组件更新过程
  父beforeUpdate->父updated
销毁过程
  父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

问题来了

需求:在利用simpleMDE制作一款编辑器的时候,需要将之前编辑保存的内容回显
做法:利用当前组件调用simpleMDE的功能组件,并将从数据库查询到的数据通过v-model传入

 <!-- 编写正文介绍 -->
          <lecMde v-model="lec.content" class="mde" ref="lecMDE" />
          <!-- <el-card shadow="never" class="d2-card">
            <pre>{{ lec.content }}</pre>
          </el-card> -->
import lecMde from "../components/simpleMDE/lec_mde";

//生命周期 - 挂载完成(可以访问DOM元素)
  mounted() {
    this.lec.content = text;

    console.log("父初始", this.lec.content);

    // console.log(this.$route.query.lecId);
    if (this.$route.query.lecId) {
      this.lec.lecId = this.$route.query.lecId;
      this.$request({  //异步调用
        url: `product/lecinfo/infos/${this.lec.lecId}`,
        method: "get",
        params: {},
        headers: {},
      }).then(({ data }) => {
        if (data && data.code === 0) {
          this.lec = data.data;
          console.log("父加载数据后", this.lec.content);
        }
      });
    }
  },

子组件

  mounted() {
    // 初始化
    // this.init(); //不让它在这初始化,因为其依赖父组件的数据,那就在数据完事后调用该方法
  },
  methods: {
    // 初始化
    init() {
      console.log("md初始化", this.value);  //这个value是利用props接收父组件通过v-model绑定的属性
      // 合并参数
      const config = Object.assign({}, this.defaultConfig, this.config);
      // 初始化
      this.mde = new SimpleMDE({
        ...config,
        // 初始值
        initialValue: this.value,
        // 挂载元素
        element: this.$refs.mde,
      });
      this.mde.codemirror.on("change", () => {
        // console.log("codemirror变化了",this.mde.value());
        this.$emit("input", this.mde.value()); //改变父组件中v-model和子组件中的value值为当前this.mde.value()
      });
    },
 }

原本的情况是,子组件lec_mde.vue中在mounted时调用自定义的init()方法进行初始化.而加载渲染顺序为

父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted

如果父组件就这样将异步调用放入mounted的话,子组件接收的值为

那我就将异步调用放父组件的created()吧然后你会发现,子组件接收的值为初始的 text,并不是异步返回的值.请求发过去,继续下面的操作,可能子组件都mounted完了,响应还没回来.

为了避免上述问题,为使子承父业,那就等结果回来了,再去触发子的init()方法

解决实现

在父组件调用子组件时加入ref,用来调用该子组件中的方法或data里的属性等

 <lecMde v-model="lec.content" class="mde" ref="lecMDE" />

然后在父组件中的某个methods里的方法中,点击按钮触发调用(为保证异步调用完成)

this.$refs.lecMDE.init(); //调用子组件的初始化
注意:vue的生命周期,如果在节点DOM未实例化之前使用this.$refs属性会报错(TypeError: this.$refs.lecMDE is undefined),vue生命周期中mounted可访问DOM元素(即已实例化完成)

最终打印输出如下:

父初始 
# 标题
- 列表
- 列表
alert('Hello')
[D2Admin in github](https://github.com/d2-projects/d2-admin) index.vue:373

父加载数据后 
[D2Admin in github](https://github.com/d2-projects/d2-admin)
![Img](https://img-blog.csdnimg.cn/img_convert/974468cb9288bce06d08cf19e604314e.png)
index.vue:388

------------------------------------------------------------------------------------------

md初始化 
[D2Admin in github](https://github.com/d2-projects/d2-admin)
![Img](https://img-blog.csdnimg.cn/img_convert/974468cb9288bce06d08cf19e604314e.png)

在这里插入图片描述

MD加载多次的解决

由于事件是click触发,但是每次点击都会在方法中初始化一下MD,这怎么行,这样MD的窗口会越来越多,所以整个一次性事件

<el-form-item>
   <el-button type="success" @mousedown.native.once="showLecMD" @mouseup.native="collectLecBaseInfo"
     >下一步:设置正文介绍</el-button
   >
 </el-form-item>
    showLecMD() {
      this.$refs.lecMDE.init(); //调用子组件的初始化
    },
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星空•物语

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值