关于vue data中的this指向问题

 更新时间:2023年07月03日 14:56:37   作者:s4944315  
这篇文章主要介绍了关于vue data中的this指向问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

vue data的this指向

在data里定义Object类型的变量时,会发现Object中访问不到vue的this属性。

例如:

export default {
  data(){
    return {
      a: "123",
      b: {
        c: this.a
      }
    };
  },
  created() {
    console.log("b: ", this.b.c); // undefined
  }
}

想在b中访问this.a的数据,直接访问会返回undefined,因为这时c中的this指向的是b。

这种情况可以用到Object的get属性进行属性定义。

例如:

export default {
  data(){
    return {
      a: "123",
      b: {
        _target: () => this,
        get target() {
          return this._target();
        },
        get c() {
          return this.target.a;
        },
      },
    };
  },
  created() {
    console.log("b: ", this.b.c); // 123
  }
}

此处将this映射到了Object变量内部,然后通过get的形式定义属性并获取。

当get定义的属性所依赖的属性的值发生改变时,get定义的属性的值也将发生改变。

例如:

export default {
  data(){
    return {
      a: "123",
      b: {
        _target: () => this,
        get target() {
          return this._target();
        },
        get c() {
          return this.target.a;
        },
        d: 123,
        get e() {
          return `依赖于d的值, 会同步发生改变, d的值为: ${this.d}`;
        }
      },
    };
  },
  created() {
    console.log("b: ", this.b.c); // 123
    console.log("e: ", this.b.e); // e:  依赖于d的值, 会同步发生改变, d的值为: 123 c: 123
    setTimeout(() => {
      this.b.d = 456;
      console.log("e: ", this.b.e); // e:  依赖于d的值, 会同步发生改变, d的值为: 456 c: 123
    }, 1000);
    setTimeout(() => {
      this.a = "456";
      console.log("e: ", this.b.e); // e:  依赖于d的值, 会同步发生改变, d的值为: 456 c: 456
    }, 2000);
  }
}

当前方法更像是一种深度计算属性(computed),会随着所依赖的项发生改变而改变。

vue关于this指向的重要原则

在学习js的时候,偶尔会涉及到this的指向问题。大部分情况下,在一个函数中,谁调用这个函数,this就指向谁。

在Vue中,this的指向却显得尤为重要。本节博客将为大家解释Vue中this的指向问题,同时告诉读者,为什么this的指向在Vue中非常重要,以及我们在平时写Vue代码时需要注意的相关内容。

vue底层的相关原理

1.1 MVVM模型的复习

Vue的设计收到了MVVM模型的影响,在看this指向问题前,我想带读者们复习一下MVVM模型的相关知识。

  • M:Model模型,对应的是data中的数据;
  • V:View视图,对应的是模板,也就是页面结构;
  • VM:视图模型,对应的是Vue实例对象。

这里用一个html文件给大家划分一下具体结构:

在这里插入图片描述

1.2 通过差值语法看vm的属性

所有vm中的属性,利用差值语法都可以看到。

为了测试,我们先看看vm是什么。此处,我们先打印一下this,可以看到此时的this是Vue。

准确来说使我们创建的Vue实例。这里面的所有属性都可以通过插值语法看到。

在这里插入图片描述

为了验证上面说的话,现在我利用差值语法随意看Vue实例对象中的一些东西:

在这里插入图片描述

在这里插入图片描述

1.3 为什么差值语法可以看到vm的内部属性

==因为在Vue中,this指向的是vm实例对象Vue。==所以可以利用this看到vm的所有属性。希望读者朋友们可以牢记这一点。

记住这一点在时时刻刻的应用中:我们不要轻易的改变this的指向,如若改变,this不再是vm,页面上的元素将无法正常被渲染。

这里给大家看一个例子:

这段代码的需求是,在 页面中写出姓和名,让Vue帮我们合成姓名。并且在我们修改姓或者名后停顿1s后再帮我们合成。

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../vue.js"></script>
</head>
<body>
  <div id="root">
    姓:<input type="text" v-model="firstName"><br>
    名:<input type="text" v-model="lastName"><br>
    全名:<span>{{ fullName }}</span>
  </div>
  <script>
    new Vue({
      el: '#root',
      data: {
        firstName: '张',
        lastName: '三',
        fullName: ''
      },
      watch: {
        firstName(newValue, oldValue) {
          setTimeout(() => {
            this.fullName = newValue + this.lastName
            console.log(this)
          }, 1000)
        },
        lastName(newValue, oldValue) {
          setTimeout(() => {
            this.fullName = this.firstName + newValue
            console.log(this)
          }, 1000)
        }
      }
    })
  </script>
</body>
</html>

上述代码是没有什么问题的。并且在定时器中,使用箭头函数,打印出来的this都是vue实例

在这里插入图片描述

原因:箭头函数中的this指向它的外层调用者。

现在看一个反例:我们把箭头函数改成普通函数,则会出现问题:

<body>
  <div id="root">
    姓:<input type="text" v-model="firstName"><br>
    名:<input type="text" v-model="lastName"><br>
    全名:<span>{{ fullName }}</span>
  </div>
  <script>
    new Vue({
      el: '#root',
      data: {
        firstName: '张',
        lastName: '三',
        fullName: ''
      },
      watch: {
        firstName(newValue, oldValue) {
          setTimeout(() => {
            this.fullName = newValue + this.lastName
            console.log(this)
          }, 1000)
        },
        // lastName(newValue, oldValue) {
        //   setTimeout(() => {
        //     this.fullName = this.firstName + newValue
        //     console.log(this)
        //   }, 1000)
        // }
        // 这是一个错误写法,因为它改变了this的指向。它的this是window。那么就没办法读到vue中的数据了
        lastName(newValue, oldValue) {
          setTimeout(function() {
            this.fullName = this.firstName + newValue
            console.log(this)
          }, 1000)
        }
      }
    })
  </script>

没办法正常运行并且,this打印出来的是window:

在这里插入图片描述

在这里插入图片描述

==原因:普通函数中的this指向它的直接调用者。

==由于定时器的this指向的是window。此时此刻,改变了this的指向,所以会报错。

心得

1.所被Vue管理的函数,最好写成普通函数。这样的this指向实例对象;

2.所有不被Vue所管理的函数(定时器,ajax,回调)最好写成箭头函数,这样this依旧指向Vue或者组件的实例对象。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Vue.js 点击按钮显示/隐藏内容的实例代码

    Vue.js 点击按钮显示/隐藏内容的实例代码

    下面小编就为大家分享一篇Vue.js 点击按钮显示/隐藏内容的实例代码,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-02-02
  • Vue3监听属性与Computed的区别详解

    Vue3监听属性与Computed的区别详解

    在 Vue 3 中,watch 和 computed 都是非常重要的概念,它们都可以用于观察和响应数据的变化,但在使用场景和原理上存在明显的区别,本文将详细解析 Vue 3 中监听属性 (watch) 和计算属性 (computed) 的区别,需要的朋友可以参考下
    2024-02-02
  • vue如何使用js对图片进行点击标注圆点并记录它的坐标

    vue如何使用js对图片进行点击标注圆点并记录它的坐标

    这篇文章主要介绍了vue如何使用js对图片进行点击标注圆点并记录它的坐标,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-04-04
  • vue商城中商品“筛选器”功能的实现代码

    vue商城中商品“筛选器”功能的实现代码

    这篇文章主要介绍了vue商城中商品“筛选器”功能的实现,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-07-07
  • 使用Bootstrap4 + Vue2实现分页查询的示例代码

    使用Bootstrap4 + Vue2实现分页查询的示例代码

    本篇文章主要介绍了使用Bootstrap4 + Vue2实现分页查询的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-12-12
  • vue2使用wangeditor实现数学公式和富文本编辑器

    vue2使用wangeditor实现数学公式和富文本编辑器

    这篇文章主要为大家详细介绍了vue2如何使用wangeditor实现数学公式和富文本编辑器功能,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下
    2023-12-12
  • Vue 子组件更新props中的属性值问题

    Vue 子组件更新props中的属性值问题

    这篇文章主要介绍了Vue 子组件更新props中的属性值问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-10-10
  • Vue中使用element-ui给按钮绑定一个单击事件实现点击按钮就弹出dialog对话框

    Vue中使用element-ui给按钮绑定一个单击事件实现点击按钮就弹出dialog对话框

    最近遇到了个需求是使用element-ui插件编写页面,点击按钮,弹出对话框,这篇文章主要给大家介绍了关于Vue中使用element-ui给按钮绑定一个单击事件实现点击按钮就弹出dialog对话框的相关资料,需要的朋友可以参考下
    2022-11-11
  • vue2创建高复用组件的方法示例

    vue2创建高复用组件的方法示例

    Vue2中的高复用组件通常是指那些设计得足够通用,并能多次在项目中重复使用的组件,本文给大家详细介绍了vue2创建高复用组件的方法示例,并通过代码示例讲解的非常详细,需要的朋友可以参考下
    2024-07-07
  • vue引入element-ui之后,页面是空白的问题及解决

    vue引入element-ui之后,页面是空白的问题及解决

    这篇文章主要介绍了vue引入element-ui之后,页面是空白的问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-01-01

最新评论