程序员scholar 程序员scholar
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
npm

(进入注册为作者充电)

  • Vue2

    • Vue简介
    • Vue 基础使用
    • Vue的基础指令
    • 过滤器(Filters)
    • 侦听器(Watch)
    • 计算属性(computed)
    • vue-cli
    • vue.config.js配置
    • Vue组件
    • 生命周期和数据共享
    • Vue 组件实例与数据代理 (this)
      • 1. Vue 组件实例的常用属性和方法
        • 1. 内置属性
        • 2. 内置方法
        • 3. 内部属性(以 _ 开头)
        • 4. 控制台输出的 Vue 实例解析
      • 2. Vue 组件的数据代理 (this访问)
        • 1. 数据代理的工作原理
        • 2. 数据代理的好处
        • 3. 深入理解数据代理
        • 4. 数据代理的范围
    • $refs 引用
    • 动态组件
    • 插槽 (Slots)
    • 混入 (Mixin)
    • 自定义指令 (directives)
    • 插件 (Plugins)
    • 初识Vue-router
    • Vue-router的常见用法
  • Vue3

  • vue3 + TS 项目集成

  • Vue全家桶
  • Vue2
scholar
2024-07-31
目录

Vue 组件实例与数据代理 (this)

# Vue 组件实例与数据代理 (this)

# 1. Vue 组件实例的常用属性和方法

Vue 组件实例对象包含了许多属性和方法,用于管理和控制组件的行为。这些属性和方法可以分为以下几类:

image-20240731014926190

# 1. 内置属性

这些属性是由 Vue 框架自动添加到每个 Vue 实例中的,通常以 $ 开头,以避免与用户定义的属性冲突。

  1. $el

    • 类型:DOM Element
    • 描述:当前 Vue 实例管理的根 DOM 元素。
    • 示例:
      console.log(this.$el); // 输出当前实例管理的根 DOM 元素
      
      1
  2. $data

    • 类型:Object
    • 描述:当前 Vue 实例的所有响应式数据对象。
    • 示例:
      console.log(this.$data); // 输出当前实例的所有数据
      
      1
  3. $props

    • 类型:Object
    • 描述:当前实例接收的所有 props 对象。
    • 示例:
      console.log(this.$props); // 输出当前实例接收的所有 props
      
      1
  4. $options

    • 类型:Object
    • 描述:用于当前 Vue 实例的初始化选项对象。
    • 示例:
      console.log(this.$options); // 输出初始化选项对象
      
      1
  5. $parent

    • 类型:Vue Instance
    • 描述:当前实例的父实例。
    • 示例:
      console.log(this.$parent); // 输出父实例
      
      1
  6. $root

    • 类型:Vue Instance
    • 描述:当前组件树的根实例。
    • 示例:
      console.log(this.$root); // 输出根实例
      
      1
  7. $refs

    • 类型:Object
    • 描述:包含所有注册了 ref 特性的 DOM 元素和子组件实例。
    • 示例:
      console.log(this.$refs); // 输出所有注册了 ref 的 DOM 元素和子组件实例
      
      1
  8. $slots

    • 类型:Object
    • 描述:包含所有插槽内容。
    • 示例:
      console.log(this.$slots); // 输出所有插槽内容
      
      1
  9. $scopedSlots

    • 类型:Object
    • 描述:包含所有作用域插槽内容。
    • 示例:
      console.log(this.$scopedSlots); // 输出所有作用域插槽内容
      
      1
  10. $isServer

    • 类型:Boolean
    • 描述:当前 Vue 实例是否运行于服务器。
    • 示例:
      console.log(this.$isServer); // 输出当前实例是否运行于服务器
      
      1
  11. $attrs

    • 类型:Object
    • 描述:包含父作用域中不作为 props 被识别且获取的特性绑定。
    • 示例:
      console.log(this.$attrs); // 输出父作用域中不作为 props 被识别的特性绑定
      
      1
  12. $listeners

    • 类型:Object
    • 描述:包含父作用域中的 (不含 .native 修饰符的) v-on 事件监听器。
    • 示例:
      console.log(this.$listeners); // 输出父作用域中的事件监听器
      
      1

# 2. 内置方法

这些方法用于操作 Vue 实例的各种功能。

  1. $watch(expOrFn, callback, [options])

    • 描述:观察 Vue 实例上的一个表达式或计算属性函数的变化。
    • 参数:
      • expOrFn:要观察的表达式或计算属性函数。
      • callback:回调函数。
      • [options]:可选配置对象。
    • 示例:
      this.$watch('someData', function (newVal, oldVal) {
        console.log('someData 发生变化:', newVal, oldVal);
      });
      
      1
      2
      3
  2. $set(target, key, value)

    • 描述:将值设置到响应式对象的指定属性上。
    • 示例:
      this.$set(this.someObject, 'newKey', 'newValue'); // 在 someObject 对象上设置 newKey 属性
      
      1
  3. $delete(target, key)

    • 描述:删除对象的属性。
    • 示例:
      this.$delete(this.someObject, 'someKey'); // 删除 someObject 对象上的 someKey 属性
      
      1
  4. $on(event, callback)

    • 描述:监听当前实例上的自定义事件。
    • 示例:
      this.$on('myEvent', function (payload) {
        console.log('myEvent 触发了:', payload);
      });
      
      1
      2
      3
  5. $once(event, callback)

    • 描述:监听一个自定义事件,但只触发一次,在第一次触发之后移除监听器。
    • 示例:
      this.$once('myEvent', function (payload) {
        console.log('myEvent 触发了一次:', payload);
      });
      
      1
      2
      3
  6. $off(event, [callback])

    • 描述:移除自定义事件监听器。
    • 示例:
      this.$off('myEvent'); // 移除所有 myEvent 事件的监听器
      
      1
  7. $emit(event, [...args])

    • 描述:触发当前实例上的事件。可以传递附加参数。
    • 示例:
      this.$emit('myEvent', 'someData'); // 触发 myEvent 事件,并传递 someData
      
      1
  8. $forceUpdate()

    • 描述:迫使 Vue 实例重新渲染。
    • 示例:
      this.$forceUpdate(); // 迫使 Vue 实例重新渲染
      
      1
  9. $nextTick([callback])

    • 描述:在下次 DOM 更新循环结束之后执行延迟回调。
    • 示例:
      this.$nextTick(function () {
        console.log('DOM 更新完成');
      });
      
      1
      2
      3
  10. $destroy()

    • 描述:完全销毁一个实例。清理它与其他实例的连接,解绑它的全部指令及事件监听器。
    • 示例:
      this.$destroy(); // 销毁当前实例
      
      1

# 3. 内部属性(以 _ 开头)

这些属性是 Vue 的内部属性,通常用于框架内部,开发者一般不需要直接访问。

  1. _uid

    • 描述:实例的唯一标识符。
  2. _isVue

    • 描述:标识这个对象是一个 Vue 实例。
  3. _data

    • 描述:实际存储响应式数据对象。
  4. _watcher

    • 描述:用于监听数据变化的观察者实例。

# 4. 控制台输出的 Vue 实例解析

下面是控制台输出的 Vue 实例部分属性解析:













 




























 

 



VueComponent {
  _uid: 22, // 实例的唯一标识符
  _isVue: true, // 标识这个对象是一个 Vue 实例
  __v_skip: true, // 内部用于跳过某些操作的标识符
  _scope: EffectScope, // 响应式范围
  $options: {…}, // 初始化选项对象
  $attrs: {…}, // 父作用域中不作为 props 被识别的特性绑定
  $children: [VueComponent], // 子组件实例数组
  $createElement: ƒ (a, b, c, d), // 创建元素的方法
  $el: div, // 当前实例管理的根 DOM 元素
  $listeners: {…}, // 父作用域中的事件监听器
  $parent: VueComponent {…}, // 父实例
  $refs: {}, // ref 引用对象
  $root: Vue {…}, // 根实例
  $scopedSlots: {…}, // 作用域插槽对象
  $slots: {}, // 插槽对象
  $vnode: VNode {…}, // 虚拟节点
  handleUpdateMessage:

 ƒ (), // 自定义方法
  receivedMessage: "Hello from Child", // 自定义数据属性
  __v_skip: true, // 内部用于跳过某些操作的标识符
  _c: ƒ (a, b, c, d), // 创建元素的方法
  _data: {
    receivedMessage: "Hello from Child", // 数据对象
    __ob__: Observer {…} // 数据的观察者对象
  },
  _directInactive: false, // 内部标识
  _events: {}, // 事件对象
  _hasHookEvent: false, // 内部标识
  _inactive: null, // 内部标识
  _isBeingDestroyed: false, // 内部标识
  _isDestroyed: false, // 内部标识
  _isMounted: true, // 内部标识
  _provided: {}, // 内部标识
  _renderProxy: Proxy(VueComponent) {…}, // 渲染代理
  _self: VueComponent {…}, // 自身实例
  _staticTrees: null, // 静态树
  _uid: 22, // 实例的唯一标识符
  _vnode: VNode {…}, // 虚拟节点
  _watcher: Watcher {…}, // 观察者实例
  $data: {…}, // 数据对象
  $isServer: false, // 是否为服务端渲染
  $props: {…}, // props 对象
  $ssrContext: null, // 服务端渲染上下文
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

总结

  • Vue 实例包含了许多属性和方法,用于管理和控制组件的行为。
  • 常用的内置属性以 $ 开头,例如 $el、$data、$props 等。
  • Vue 实例还提供了许多内置方法,例如 $watch、$set、$delete 等。
  • 控制台输出的 Vue 实例包含了各种内部属性和方法,通常以 _ 开头,用于框架内部。

# 2. Vue 组件的数据代理 (this访问)

# 1. 数据代理的工作原理

在 Vue 中,组件的 data 属性实际上被代理到了 Vue 实例上。这意味着你可以直接通过 this 访问 data 中定义的属性,而不需要通过 this.$data。

数据代理的原理

当你在 Vue 实例的 data 选项中定义数据时,Vue 会通过 Object.defineProperty 为每一个数据属性创建一个 getter 和 setter。这些 getter 和 setter 会被挂载到 Vue 实例上,使得你可以直接通过 this 访问和修改这些数据属性。

示例代码

new Vue({
  el: '#app',
  data() {
    return {
      message: 'Hello, Vue!'
    };
  },
  created() {
    console.log(this.message); // 输出: Hello, Vue!
    console.log(this.$data.message); // 输出: Hello, Vue!
    this.message = 'Hello, World!';
    console.log(this.message); // 输出: Hello, World!
    console.log(this.$data.message); // 输出: Hello, World!
  }
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

在上面的示例中:

  1. data 函数返回一个对象,其中定义了 message 属性。
  2. 在 created 生命周期钩子中,通过 this.message 和 this.$data.message 都可以访问到 message 属性。
  3. 当你修改 this.message 时,实际上是通过代理机制修改了 this.$data.message 的值。

# 2. 数据代理的好处

  1. 简化访问:直接通过 this 访问数据属性,使得代码更加简洁和直观。
  2. 响应式系统:通过 getter 和 setter 实现响应式系统,当数据变化时,可以自动更新 DOM。
  3. 统一接口:不管数据是在 data 中定义的,还是通过 props 传递过来的,都可以通过 this 统一访问。

# 3. 深入理解数据代理

在 Vue 2 中,当你通过 this 访问组件实例的属性时,实际上是通过 Object.defineProperty 定义的 getter 和 setter 来实现的。这些 getter 和 setter 是在 Vue 实例初始化时,通过内部的响应式系统为每一个属性定义的。

具体来说,Vue 会遍历 data 对象中的每一个属性,并调用类似于 defineReactive 的内部方法,为每一个属性定义 getter 和 setter。当你通过 this 访问这些属性时,Vue 会触发相应的 getter 方法,从而返回属性值;当你修改这些属性时,Vue 会触发相应的 setter 方法,从而更新属性值并触发视图更新。

以下是一个简化版本的 Vue 内部工作原理的示例代码:







 
 




















 
















// 定义一个 Vue 实例
const vm = new Vue({
  data() {
    return {
      message: 'Hello, Vue!'
    };
  },
  created() {
    // 在 created 生命周期钩子中访问 message 属性
    console.log(this.message); // 输出: Hello, Vue!
    this.message = 'Hello, World!';
    console.log(this.message); // 输出: Hello, World!
  }
});

// 内部工作原理简化示例
function Vue(options) {
  // 获取 data 函数返回的对象
  const data = options.data();
  // 将数据代理到 Vue 实例上
  for (const key in data) {
    // 定义响应式属性
    defineReactive(this, key, data[key]);
  }
  // 调用 created 生命周期钩子
  options.created.call(this);
}

function defineReactive(obj, key, val) {
  // 使用 Object.defineProperty 定义 getter 和 setter
  Object.defineProperty(obj, key, {
    get() {
      console.log(`Getting key "${key}":`, val);
      return val;
    },
    set(newVal) {
      console.log(`Setting key "${key}" to:`, newVal);
      if (val !== newVal) {
        val = newVal;
        // 触发更新机制
      }
    }
  });
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

原理解释

  1. 定义 Vue 实例:创建一个包含 data 和 created 生命周期钩子的 Vue 实例。
  2. 内部工作原理:
    • 在 Vue 实例初始化时,获取 data 函数返回的对象。
    • 遍历 data 对象中的每一个属性,并调用 defineReactive 方法,为每一个属性定义 getter 和 setter。
  3. defineReactive 方法:使用 Object.defineProperty 为对象的属性定义 getter 和 setter,实现响应式的数据绑定。
  4. 访问和修改属性:在 created 生命周期钩子中,通过 this 访问和修改 message 属性,触发相应的 getter 和 setter 方法。

通过这种方式,Vue 实现了数据的响应式绑定,使得你可以通过 this 直接访问和修改组件实例中的属性,而不需要显式地使用 $data 或其他前缀。

# 4. 数据代理的范围

Vue 主要代理了以下四种类型的属性和方法,可以直接通过 this 访问,不需要加 $ 符号:

  1. data 中的属性:定义在 data 中的属性会被代理到 Vue 实例上,可以直接通过 this 访问。
  2. props 中的属性:定义在 props 中的属性也会被代理到 Vue 实例上,可以直接通过 this 访问。
  3. methods 中的方法:定义在 methods 中的方法同样会被代理到 Vue 实例上,可以直接通过 this 调用。
  4. computed 中的计算属性:定义在 computed 中的计算属性也会被代理到 Vue 实例上,可以直接通过 this 访问。

以下是一个示例代码,展示了这四种类型的属性和方法是如何被代理的:

new Vue({
  el: '#app',
  data() {
    return {
      message: 'Hello, Vue!' // data 中的属性
    };
  },
  props: {
    propMessage: {
      type: String,
      default: 'Hello from prop' // props 中的属性
    }
  },
  methods: {
    greet() {
      console.log('Greet method called'); // methods 中的方法
    }
  },
  computed: {
    reversedMessage() {
      return this.message.split('').reverse().join(''); // computed 中的计算属性
    }
  },
  created() {
    // 访问 data 中的属性
    console.log(this.message); // 输出: Hello, Vue!
    console.log(this.$data.message); // 输出: Hello, Vue!

    // 访问 props 中的属性
    console.log(this.propMessage); // 输出: Hello from prop
    console.log(this.$props.propMessage); // 输出: Hello from prop

    // 调用 methods 中的方法
    this.greet(); // 输出: Greet method called
    // 注意:这里不能使用 this.$greet(),这样会导致错误

    // 访问 computed 中的计算属性
    console.log(this.reversedMessage); // 输出: !euV ,olleH
    // 注意:这里不能使用 this.$reversedMessage,这样会导致错误
  }
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

总结

  • data 中的属性可以通过 this.message 或 this.$data.message 访问。
  • props 中的属性可以通过 this.propMessage 或 this.$props.propMessage 访问。
  • computed 中的计算属性只能通过 this.reversedMessage 访问,不能使用 $ 符号访问。
  • methods 中的方法只能通过 this.greet() 调用,不能使用 $ 符号调用。

通过这些示例,可以清楚地看到,Vue 实例代理了 data、props、methods 和 computed 中的属性和方法,使得开发者可以通过 this 直接访问这些属性和方法,而不需要通过 $ 符号。

编辑此页 (opens new window)
上次更新: 2025/01/30, 23:55:43
生命周期和数据共享
$refs 引用

← 生命周期和数据共享 $refs 引用→

Theme by Vdoing | Copyright © 2019-2025 程序员scholar
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式