首先讲讲JS中的Proxy
JavaScript 运行环境包含了一些不可枚举、不可写入的对象属性,然而在 ES5 之前开发者无法定义他们自己的不可枚举属性或不可写入属性。ES5 引入 Object.defineProperty()
方法以便开发者在这方面能够像 JS 引擎那样做。
ES6 为了让开发者能进一步接近 JS 引擎的能力,推出了 Proxy
,代理是一种封装,能够拦截并改变 JS 引擎的底层操作。简单的说,就是在目标对象上架设一层 “拦截”,外界对该对象的访问,都必须先通过这层拦截,提供了一种改变 JS 引擎过滤和改写的能力。
Proxy
对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。
术语
handler
包含捕捉器(trap)的占位符对象,可译为处理器对象。
traps
提供属性访问的方法。这类似于操作系统中捕获器的概念。
target
被 Proxy 代理虚拟化的对象。它常被作为代理的存储后端。根据目标验证关于对象不可扩展性或不可配置属性的不变量(保持不变的语义)。
语法
const p = new Proxy(target, handler)
参数
target
要使用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。
handler
一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p 的行为。
方法
Proxy.revocable()
创建一个可撤销的Proxy对象。
举例
const data = {message: "Hello!",longMessage: "Hello! World!",
}const handler = {set(target, key, value) {if (key === "message") {target.longMessage = value + " World!"}target.message = value},
}const proxy = new Proxy(data, handler)proxy.message = "Hello!!!!"console.log(proxy.longMessage)
通过上面的代码,就能实现数据属性的跟踪,更改proxy.message
,此时proxy.longMessage
也会改变。
Vue通过Proxy包裹data(){}
中的属性,属性更改时,触发代理
内置属性ref
用于注册模板引用。
-
预期:
string | Function
-
详细信息
ref
用于注册元素或子组件的引用。使用选项式 API,引用将被注册在组件的
this.$refs
对象里:<!-- 存储为 this.$refs.p --> <p ref="p">hello</p>
使用组合式 API,引用将存储在与名字匹配的 ref 里:
<script setup> import { ref } from 'vue'const p = ref() </script><template><p ref="p">hello</p> </template>
如果用于普通 DOM 元素,引用将是元素本身;如果用于子组件,引用将是子组件的实例。
或者
ref
可以接收一个函数值,用于对存储引用位置的完全控制:<ChildComponent :ref="(el) => child = el" />
关于 ref 注册时机的重要说明:因为 ref 本身是作为渲染函数的结果来创建的,必须等待组件挂载后才能对它进行访问。
this.$refs
也是非响应式的,因此你不应该尝试在模板中使用它来进行数据绑定。
例子
js
const app = Vue.createApp({data() {return {currentUserInput: "",message: "Vue is great!",}},methods: {saveInput(event) {this.currentUserInput = event.target.value},setText() {// this.message = this.currentUserInput;this.message = this.$refs.userText.value// console.dir(this.$refs.userText);},},
})app.mount("#app")
原html
<input type="text" @input="SaveInput" /><button @click="setText">Set Text</button><p>{{ message }}</p>
修改后的html
<input type="text" ref="userText" /><button @click="setText">Set Text</button><p>{{ message }}</p>
当你不需要每次敲击按键时将输入值存储为currentUserInput
,便可以使用ref
内置属性