一、注意:document?.getElementById 获取值DOM为真的情况,
v-show的情况DOM节点都可以获取到
v-if 的情况下,只要mounted所有DOM都执行完成,如果为 false,会获取不到
二、this.$refs获取DOM的情况
v-show,判断为假,在mounted都能获取到当前DOM
v-if绑定的div,如果为假,(mounted)生命周期中都获取不到
三、ref只有在三中情况能获取到
- mounted所有DOM都加载完成
- 微任务 / 网络进程(接口请求中) / 浏览器进程(用户交互(点击事件))
<!DOCTYPE html>
<html>
<head>
<title></title>
<script type="text/javascript" src="https://cdn.jsdelivr.net/vue/2.1.3/vue.js"></script>
</head>
<body>
<div id="app">
<p id="messageID">{{ message }}</p>
<p v-if="hasShow" ref="VIFmessageID" id="VIFmessageID">v-if的文本信息{{ message }}111</p>
<!-- 生命周期都执行完之后会执行异步(setTimeout)或者微任务(Promise),需要请求中修改 hasShow 得值,那么就需要在请求之后获取 ref, -->
<p v-show="hasShow" ref="VSHOWmessageID2" id="VSHOWmessageID2">v-show的文本信息{{ message }}111</p>
<p ref="refAAA">refffff--的文本信息{{ message }}111</p>
<!-- ref 只有在 mounted生命周期 检测页面所有的 DOM都加载完成之后,才能够获取 -->
</div>
<script type="text/javascript">
function initShow(info, that) {
debugger
console.group(`${info}状态===============》`);
console.log("%c%s", "color:red" , "el : " + that.$el); //undefined
console.log("%c%s", "color:red","data : " + that.$data); //undefined
const VIFmessageID = document?.getElementById('VIFmessageID')
const VSHOWmessageID2 = document?.getElementById('VSHOWmessageID2')
console.log("%c%s", "color: #ce0325", "v-if---messageID", VIFmessageID ? true : false)
console.log("%c%s", "color: #ce0325", "v-if---innerHTML", VIFmessageID?.innerHTML);
// 在生命周期 mounted中,会渲染所有的DOM,由于getUserInfo 请求在后,获取数据在前,所有打印 为false
console.log("%c%s", "color: #1f5716", "v-show--messageID2", VSHOWmessageID2 ? true : false)
console.log("%c%s", "color: #1f5716", "v-show--innerHTML", VSHOWmessageID2?.innerHTML);
console.log("%c%s", "color: orange","同步---refs : " + that.$refs['refAAA']); //undefined
that.$nextTick(() => {
console.log("%c%s", "color:blue","微任务--nextTick : " + that.$refs['refAAA']); //undefined
})
// 1、定时器是异步的,先调用,也会放在任务队列,等微任务(promise)先执行完成之后再执行异步
// setTimeoutFN()
// 2、请求接口,微任务,在这里获取refs,相当于 this.$nextTick 回调
if (info === 'created创建完毕状态' || info === 'mounted挂载结束状态') {
getUserInfo(info, that)
}
}
function setTimeoutFN(){
setTimeout(() => {
console.log('setTimeout,我应该再微任务(nextTick)之后执行')
}, 1000)
}
function getUserInfo(info, that) {
// 在接口请求之后,在获取refs的值不会报错,因为 promise 是微任务,相当于页面同步任务先执行完成之后再 执行
return new Promise((resolve, reject) => {
setTimeout(() => { //
that.hasShow = true
debugger
console.log("%c%s", "color:green","接口请求--获取refs : " + that.$refs['refAAA']);
console.log("%c%s", "color:green",info,"VIFmessageID : " + that.$refs['VIFmessageID']);
/*
疑问1?为什么 created 中修改 that.hasShow = true 值,却获取不到 refs.VIFmessageID
因为created中只是修改状态,最后执行时,此时created中 真正的DOM还没有加载完成(等所有生命周期,同步任务,微任务,都执行完之后,宏任务),所以获取不到
疑问2?为什么 mounted 中就可以获取 refs.VIFmessageID
因为 mounted中是所有的 DOM 渲染完成,当然能获取到了
*/
resolve()
}, 1500) // 微任务先调用,看 excutor 执行的是同步还是异步,都是异步看谁的时长短,就先执行
})
}
var app = new Vue({
el: '#app',
data: {
message : "这是文本信息吧???",
hasShow: false
},
beforeCreate() {
initShow('beforeCreate', this)
},
created: function () {
// this.hasShow = true
// created页面DOM还没有生成完毕,template模版字符串编译完成,在 mounted中console.log('v-if', VIFmessageID?.innerHTML); 会打印,因为页面已经完成 DOM 构建
initShow('created创建完毕状态', this)
},
beforeMount: function () {
initShow('beforeMount挂载前状态', this)
},
mounted: function () {
// mounted中只页面已经加载完成,console.log('v-if', VIFmessageID?.innerHTML); 不会打印,因为页面真是的 DOM 已经完成。
// this.hasShow = true
initShow('mounted挂载结束状态', this)
},
// beforeUpdate: function () {
// console.group('beforeUpdate 更新前状态===============》');
// console.log("%c%s", "color:red","el : " + this.$el);
// console.log(this.$el);
// console.log("%c%s", "color:red","data : " + this.$data);
// console.log("%c%s", "color:red","message: " + this.message);
// },
// updated: function () {
// console.group('updated 更新完成状态===============》');
// console.log("%c%s", "color:red","el : " + this.$el);
// console.log(this.$el);
// console.log("%c%s", "color:red","data : " + this.$data);
// console.log("%c%s", "color:red","message: " + this.message);
// },
// beforeDestroy: function () {
// console.group('beforeDestroy 销毁前状态===============》');
// console.log("%c%s", "color:red","el : " + this.$el);
// console.log(this.$el);
// console.log("%c%s", "color:red","data : " + this.$data);
// console.log("%c%s", "color:red","message: " + this.message);
// },
// destroyed: function () {
// console.group('destroyed 销毁完成状态===============》');
// console.log("%c%s", "color:red","el : " + this.$el);
// console.log(this.$el);
// console.log("%c%s", "color:red","data : " + this.$data);
// console.log("%c%s", "color:red","message: " + this.message)
// }
})
</script>
</body>
</html>
疑问一、使用debugger可以看出,在beforeCreate执行时,字符串模版已经编译,可以使用document.getElementById可以获取到,不受影响。
疑问二、this.$refs和document.getElementById()都是用于获取DOM元素的方法,但它们有以下几个不同点:
- ref在mounted之后才能够获取,是等所有的字符串模版都编译完成
疑问三、四、代码示例请看 getUserInfo 函数返回的值。
疑问三?为什么 created 中修改 that.hasShow = true 值,却获取不到 refs.VIFmessageID
- 因为created中只是修改状态,最后执行时,此时created中 真正的DOM还没有加载完成(等所有生命周期,同步任务,微任务,都执行完之后,宏任务),所以获取不到
疑问四?为什么 mounted 中就可以获取 refs.VIFmessageID
- 因为 mounted中是所有的 DOM 渲染完成,当然能获取到了