likes
comments
collection
share

Vue 模版为什么不能访问window?

作者站长头像
站长
· 阅读数 25

前言


你的建议对我来说非常宝贵, 我会好好考虑并付诸实践的。

Vue 模版为什么不能访问window?

压力--

一、前言

今天像往常一样,开开心心的打代码编程,我是属于那种爱思考的。

突然想直接在模板上访问window,是不是很方便?

于是便有了今天这篇文章,一起来探讨一下。

当然,你也可以当做面试题。

二、分析

window访问:

<v-btn v-if="window.ddd.ccc">go</v-btn>

在控制台中,我收到此错误😭

Vue 警告: Vue 组件的渲染过程中引用了一个名为“窗口”的属性或方法,但该属性或方法并未在当前组件的实例上进行定义。

Vue 模版为什么不能访问window?

这是因为 Vue 的模板编译过程和数据绑定机制的限制所致。

原因分析:

  • 模板编译限制: Vue 模板在编译时会进行静态分析,用于优化和提升性能😊。模板中的数据绑定和指令会被编译成渲染函数,而这些渲染函数的执行环境并不是全局的 window 对象,而是组件实例的作用域。

  • 安全性考虑: 直接在模板中使用 window 对象可能会引起安全问题,尤其是在服务端渲染(SSR)或者某些限制严格的环境中🙃,直接访问全局对象可能会带来不可预测的后果。

Vue 模版为什么不能访问window?

三、解决方法

计算属性或方法: 在组件的 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 实例。

Vue 模版为什么不能访问window?

模板中的表达式处于沙盒环境之下 🤗,仅能触及有限的全局对象列表。在这个列表里,常见的内置全局对象如 Math 和 Date 会被暴露出来。但倘若某些全局对象未被明确包含在这个列表中,例如用户附加在 window 上的属性,那么在模板内的表达式中就无法对其进行访问。不过,用户完全可以自行在 app.config.globalProperties 上明确地添加这些对象,从而使得所有的 Vue 表达式都能够加以使用。

例如,如果用户在 window 上添加了一个自定义属性 customProperty ,但它未在有限的全局对象列表中,那么在模板表达式中就无法直接使用。但通过在 app.config.globalProperties 中添加 customProperty ,就能够解决这个访问限制的问题。

又如,对于一些复杂的计算,可能会频繁使用 Math 中的方法,由于其在可访问的全局对象列表中,所以能够在模板表达式中方便地进行调用和计算。

至此撒花~

后记

我们在实际项目中或多或少遇到一些奇奇怪怪的问题。

自己也会对一些写法的思考,为什么不行🤔,又为什么行了?

最后,祝君能拿下满意的offer。

👍 如果对您有帮助,您的点赞是我前进的润滑剂。

以往推荐

原文链接

转载自:https://juejin.cn/post/7397701329789091877
评论
请登录