单组件时生命周期
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(); //调用子组件的初始化
},