响应性
什么是响应性
响应性是一种允许我们以声明式的方式去适应变化的一种编程范例。
Vue.js如何追踪数据的变化呢?
在生成Vue.js实例时,使用带有getter和setter的处理程序遍历传入的data,将其所有property转换为Proxy对象。
Proxy代理对象,顾名思义,在访问对象前增加一个中间层,通过中间层做一个中转,通过操作代理对象,实现目标对象的修改。
Proxy对象对于用户来说是不可见的,但在内部,它使Vue.js能够在property值被访问或修改的情况下进行依赖跟踪和变更通知。
响应性原理
reactive()方法和watchEffect()方法是Vue3中响应式的两个核心方法
reactive()方法负责将数据变成响应式代理对象
watchEffect()方法的作用是监听数据变化去更新视图或调用函数
为什么使用组合API
通过创建Vue.js组件,可以将接口的可重复部分及其功能提取到可重用的代码段中,从而使应用程序可维护且灵活。
然而,当应用程序非常复杂(成百上千组件)时,再使用组件的选项(data、computed、methods、watch)组织逻辑,可能导致组件难以阅读和理解。
如果能够将与同一个逻辑相关的代码配置在一起将有效解决逻辑复杂、可读性差等问题。
这正是使用组合API的目的。
setup组件选项
Vue组件提供setup选项,供开发者使用组合API。
setup选项在创建组件前执行,一旦props被解析,便充当组合式API的入口点。由于在执行setup时尚未创建组件实例,因此在setup选项中没有this。
这意味着,除了props之外,无法访问组件中声明的任何属性,包括本地状态、计算属性或方法。
setup选项是一个接受props和context参数的函数。
此外,从setup返回的所有内容都将暴露给组件的其余部分(计算属性、方法、生命周期钩子、模板等等)。
setup函数的参数
1)setup函数中的第一个参数(props)
setup函数中的props是响应式的,当传入新的属性时,它将被更新。
2)setup函数中的第二个参数(context)
context上下文是一个普通的JavaScript对象,它暴露组件的4个属性:attrs、slots、emit以及expose。
setup函数的返回值
1)对象
如果setup返回一个对象,则可以在组件的模板中访问该对象的属性。
2)渲染函数
setup还可以返回一个渲染函数,该函数可以直接使用在同一作用域中声明的响应式状态。
使用ref创建响应式引用
1.声明响应式状态
要为JavaScript对象创建响应式状态,可以使用reactive()方法。
reactive()方法接收一个普通对象然后返回该对象的响应式代理。
示例代码如下:
const book = Vue.reactive({ title: '好书' })
reactive()方法响应式转换是“深层的”即影响对象内部所有嵌套的属性。
基于ES的 Proxy实现,返回的代理对象不等于原始对象。
建议使用代理对象,避免依赖原始对象。
2.使用ref创建独立的响应式值对象
ref接受一个参数值并返回一个响应式且可改变的ref对象。
ref对象拥有一个指向内部值的单一属性.value。
示例代码如下:
const readersNumber = Vue.ref(1000)
console.log(readersNumber.value) //1000
readersNumber.value++
console.log(readersNumber.value) // 1001
当ref作为渲染上下文的属性返回(即在setup()返回的对象中)并在模板中使用时,它会自动开箱,无需在模板内额外书写.value。
setup内部调用生命周期钩子函数
在setup内部,可通过在生命周期钩子函数前面加上“on”来访问组件的生命周期钩子函数。
因为setup是围绕beforeCreate和created生命周期钩子函数运行的,所以不需要显式地定义它们。
换句话说,在这些钩子函数中编写的任何代码都应该直接在setup函数中编写。
这些on函数接受一个回调函数,当钩子函数被组件调用时将会被执行。
示例代码如下:
setup() {
// mounted时执行
onMounted(() => {
console.log('Component is mounted!')
})
}
提供/注入
使用provide和inject可实现组件链传值。
也就是说,父组件可以作为其所有子组件的依赖项提供程序,而不管组件层次结构有多深,父组件有一个provide选项来提供数据,子组件有一个inject选项来使用这个数据。
现在,在组合API中,也可以使用provide方法和inject方法实现传值,但两者都只能在当前活动实例的setup()期间调用。
provide方法
首先,从vue显式导入provide方法;然后,在setup()中使用provide方法定义每个property。 provide方法有两个参数:
1、 name:代表字符串类型的属性名称
2、value:代表任意类型的属性值
inject方法
首先,从vue显式导入inject方法;然后,在setup()中使用inject方法注入每个property值。 inject方法有两个参数:
1、name:被注入的属性名称(字符串类型)
2、defaultValue:默认值(可选)
模板引用
在使用组合API时,响应式引用和模板引用的概念是统一的。
为了获得对模板内元素或组件实例的引用,可以声明一个ref并从setup()返回。
响应式计算与侦听
响应式计算
使用响应式计算方法computed有两种方式:
1、传入一个getter函数,返回一个默认不可手动修改的ref对象
2、传入一个拥有get和set函数的对象,创建一个可手动修改的计算状态
响应式侦听
可使用响应性侦听watchEffect方法,对响应性进行侦听。
该方法立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数。
总结
介绍了响应性原理与组合API思想。
响应性是一种以声明式的方式去适应变化的一种编程范例,非侵入性的响应性系统是Vue.js最独特的特性之一。
组合API可以将与同一个逻辑相关的代码配置在一起将有效解决逻辑复杂、可读性差等问题。