Vue 模版为什么不能访问window?
前言
你的建议对我来说非常宝贵, 我会好好考虑并付诸实践的。
压力--
一、前言
今天像往常一样,开开心心的打代码编程,我是属于那种爱思考的。
突然想直接在模板上访问window,是不是很方便?
于是便有了今天这篇文章,一起来探讨一下。
当然,你也可以当做面试题。
二、分析
window访问:
<v-btn v-if="window.ddd.ccc">go</v-btn>
在控制台中,我收到此错误😭:
Vue 警告: Vue 组件的渲染过程中引用了一个名为“窗口”的属性或方法,但该属性或方法并未在当前组件的实例上进行定义。
这是因为 Vue 的模板编译过程和数据绑定机制的限制所致。
原因分析:
-
模板编译限制: Vue 模板在编译时会进行静态分析,用于优化和提升性能😊。模板中的数据绑定和指令会被编译成渲染函数,而这些渲染函数的执行环境并不是全局的 window 对象,而是组件实例的作用域。
-
安全性考虑: 直接在模板中使用 window 对象可能会引起安全问题,尤其是在服务端渲染(SSR)或者某些限制严格的环境中🙃,直接访问全局对象可能会带来不可预测的后果。
三、解决方法
计算属性或方法: 在组件的 computed 属性中定义一个计算属性或者在 methods 中定义一个方法来访问 window 对象,然后在模板中使用该计算属性或方法。
<template>
<div>{{ getWindowWidth }}</div>
</template>
<script>
export default {
computed: {
getWindowWidth() {
return window.innerWidth;
}
}
}
</script>
使用生命周期钩子: 在组件的生命周期钩子中(如 mounted)访问 window 对象,并将值保存在组件实例的数据属性中,然后在模板中使用该数据属性。
<template>
<div>{{ windowWidth }}</div>
</template>
<script>
export default {
data() {
return {
windowWidth: 0
};
},
mounted() {
this.windowWidth = window.innerWidth;
}
}
</script>
全局事件监听: 在 mounted 钩子中添加全局事件监听器,以确保在窗口尺寸变化时更新数据。
<template>
<div>{{ windowWidth }}</div>
</template>
<script>
export default {
data() {
return {
windowWidth: window.innerWidth
};
},
mounted() {
window.addEventListener('resize', this.handleResize);
},
beforeDestroy() {
window.removeEventListener('resize', this.handleResize);
},
methods: {
handleResize() {
this.windowWidth = window.innerWidth;
}
}
}
</script>
四、console.log
为什么在 template 里没办法获取window.对象身上的一些方法呢?
为什么人家react可以呢?
要确定的一个点,template 是 vue 提供的语法糖,最终会编译成 render function
,至于说怎么编译完全取决于 vue 的 compiler。
可以用 Vue SFC Playground 看相关的编译结果
// template
@click="() => console.log(1234)"
// 被编译成了
onClick: _cache[0] || (_cache[0] = () => _ctx.console.log(1234))
console 变成了 _ctx.console,换句话说在 模版中的只能访问到 组件上下文 中的属性,这是 vue 从编译层面就决定了的
受限的全局访问
在 Vue 的模板解析机制中,模板会被转化为一个 render function
。这个函数内部的代码被封装在 with(this){}
的结构之中,这意味着其中的变量会从 this
上进行查找。而当 render
函数被执行时,这个 this
所指向的正是 vm
实例。
模板中的表达式处于沙盒环境之下 🤗,仅能触及有限的全局对象列表。在这个列表里,常见的内置全局对象如 Math
和 Date
会被暴露出来。但倘若某些全局对象未被明确包含在这个列表中,例如用户附加在 window
上的属性,那么在模板内的表达式中就无法对其进行访问。不过,用户完全可以自行在 app.config.globalProperties
上明确地添加这些对象,从而使得所有的 Vue 表达式都能够加以使用。
例如,如果用户在 window
上添加了一个自定义属性 customProperty
,但它未在有限的全局对象列表中,那么在模板表达式中就无法直接使用。但通过在 app.config.globalProperties
中添加 customProperty
,就能够解决这个访问限制的问题。
又如,对于一些复杂的计算,可能会频繁使用 Math
中的方法,由于其在可访问的全局对象列表中,所以能够在模板表达式中方便地进行调用和计算。
至此撒花~
后记
我们在实际项目中或多或少遇到一些奇奇怪怪的问题。
自己也会对一些写法的思考,为什么不行🤔,又为什么行了?
最后,祝君能拿下满意的offer。
👍 如果对您有帮助,您的点赞是我前进的润滑剂。
以往推荐
原文链接
转载自:https://juejin.cn/post/7397701329789091877