【Vue面试题十六】、Vue.observable你有了解过吗?说说看

2023-10-12 02:04

本文主要是介绍【Vue面试题十六】、Vue.observable你有了解过吗?说说看,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章底部有个人公众号:热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享? 踩过的坑没必要让别人在再踩,自己复盘也能加深记忆。利己利人、所谓双赢。

面试官:Vue.observable你有了解过吗?说说看

在这里插入图片描述

一、Observable 是什么

Observable 翻译过来我们可以理解成可观察的

我们先来看一下其在Vue中的定义

Vue.observable,让一个对象变成响应式数据。Vue 内部会用它来处理 data 函数返回的对象

返回的对象可以直接用于渲染函数和计算属性内,并且会在发生变更时触发相应的更新。也可以作为最小化的跨组件状态存储器

Vue.observable({ count : 1})

其作用等同于

new vue({ count : 1})

Vue 2.x 中,被传入的对象会直接被 Vue.observable 变更,它和被返回的对象是同一个对象

Vue 3.x 中,则会返回一个可响应的代理,而对源对象直接进行变更仍然是不可响应的

二、使用场景

在非父子组件通信时,可以使用通常的bus或者使用vuex,但是实现的功能不是太复杂,而使用上面两个又有点繁琐。这时,observable就是一个很好的选择

创建一个js文件

// 引入vue
import Vue from 'vue
// 创建state对象,使用observable让state对象可响应
export let state = Vue.observable({name: '张三','age': 38
})
// 创建对应的方法
export let mutations = {changeName(name) {state.name = name},setAge(age) {state.age = age}
}

.vue文件中直接使用即可

<template><div>姓名:{{ name }}年龄:{{ age }}<button @click="changeName('李四')">改变姓名</button><button @click="setAge(18)">改变年龄</button></div>
</template>
import { state, mutations } from '@/store
export default {// 在计算属性中拿到值computed: {name() {return state.name},age() {return state.age}},// 调用mutations里面的方法,更新数据methods: {changeName: mutations.changeName,setAge: mutations.setAge}
}

三、原理分析

源码位置:src\core\observer\index.js

export function observe (value: any, asRootData: ?boolean): Observer | void {if (!isObject(value) || value instanceof VNode) {return}let ob: Observer | void// 判断是否存在__ob__响应式属性if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {ob = value.__ob__} else if (shouldObserve &&!isServerRendering() &&(Array.isArray(value) || isPlainObject(value)) &&Object.isExtensible(value) &&!value._isVue) {// 实例化Observer响应式对象ob = new Observer(value)}if (asRootData && ob) {ob.vmCount++}return ob
}

Observer

export class Observer {value: any;dep: Dep;vmCount: number; // number of vms that have this object as root $dataconstructor (value: any) {this.value = valuethis.dep = new Dep()this.vmCount = 0def(value, '__ob__', this)if (Array.isArray(value)) {if (hasProto) {protoAugment(value, arrayMethods)} else {copyAugment(value, arrayMethods, arrayKeys)}this.observeArray(value)} else {// 实例化对象是一个对象,进入walk方法this.walk(value)}
}

walk函数

walk (obj: Object) {const keys = Object.keys(obj)// 遍历key,通过defineReactive创建响应式对象for (let i = 0; i < keys.length; i++) {defineReactive(obj, keys[i])}
}

defineReactive方法

export function defineReactive (obj: Object,key: string,val: any,customSetter?: ?Function,shallow?: boolean
) {const dep = new Dep()const property = Object.getOwnPropertyDescriptor(obj, key)if (property && property.configurable === false) {return}// cater for pre-defined getter/settersconst getter = property && property.getconst setter = property && property.setif ((!getter || setter) && arguments.length === 2) {val = obj[key]}let childOb = !shallow && observe(val)// 接下来调用Object.defineProperty()给对象定义响应式属性Object.defineProperty(obj, key, {enumerable: true,configurable: true,get: function reactiveGetter () {const value = getter ? getter.call(obj) : valif (Dep.target) {dep.depend()if (childOb) {childOb.dep.depend()if (Array.isArray(value)) {dependArray(value)}}}return value},set: function reactiveSetter (newVal) {const value = getter ? getter.call(obj) : val/* eslint-disable no-self-compare */if (newVal === value || (newVal !== newVal && value !== value)) {return}/* eslint-enable no-self-compare */if (process.env.NODE_ENV !== 'production' && customSetter) {customSetter()}// #7981: for accessor properties without setterif (getter && !setter) returnif (setter) {setter.call(obj, newVal)} else {val = newVal}childOb = !shallow && observe(newVal)// 对观察者watchers进行通知,state就成了全局响应式对象dep.notify()}})
}

这篇关于【Vue面试题十六】、Vue.observable你有了解过吗?说说看的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/192466

相关文章

Vue3使用router,params传参为空问题

《Vue3使用router,params传参为空问题》:本文主要介绍Vue3使用router,params传参为空问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录vue3使用China编程router,params传参为空1.使用query方式传参2.使用 Histo

vue使用docxtemplater导出word

《vue使用docxtemplater导出word》docxtemplater是一种邮件合并工具,以编程方式使用并处理条件、循环,并且可以扩展以插入任何内容,下面我们来看看如何使用docxtempl... 目录docxtemplatervue使用docxtemplater导出word安装常用语法 封装导出方

Vue中组件之间传值的六种方式(完整版)

《Vue中组件之间传值的六种方式(完整版)》组件是vue.js最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用,针对不同的使用场景,如何选择行之有效的通信方式... 目录前言方法一、props/$emit1.父组件向子组件传值2.子组件向父组件传值(通过事件形式)方

一文带你了解SpringBoot中启动参数的各种用法

《一文带你了解SpringBoot中启动参数的各种用法》在使用SpringBoot开发应用时,我们通常需要根据不同的环境或特定需求调整启动参数,那么,SpringBoot提供了哪些方式来配置这些启动参... 目录一、启动参数的常见传递方式二、通过命令行参数传递启动参数三、使用 application.pro

一文带你深入了解Python中的GeneratorExit异常处理

《一文带你深入了解Python中的GeneratorExit异常处理》GeneratorExit是Python内置的异常,当生成器或协程被强制关闭时,Python解释器会向其发送这个异常,下面我们来看... 目录GeneratorExit:协程世界的死亡通知书什么是GeneratorExit实际中的问题案例

Vue 调用摄像头扫描条码功能实现代码

《Vue调用摄像头扫描条码功能实现代码》本文介绍了如何使用Vue.js和jsQR库来实现调用摄像头并扫描条码的功能,通过安装依赖、获取摄像头视频流、解析条码等步骤,实现了从开始扫描到停止扫描的完整流... 目录实现步骤:代码实现1. 安装依赖2. vue 页面代码功能说明注意事项以下是一个基于 Vue.js

Vue中动态权限到按钮的完整实现方案详解

《Vue中动态权限到按钮的完整实现方案详解》这篇文章主要为大家详细介绍了Vue如何在现有方案的基础上加入对路由的增、删、改、查权限控制,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、数据库设计扩展1.1 修改路由表(routes)1.2 修改角色与路由权限表(role_routes)二、后端接口设计

Vue项目的甘特图组件之dhtmlx-gantt使用教程和实现效果展示(推荐)

《Vue项目的甘特图组件之dhtmlx-gantt使用教程和实现效果展示(推荐)》文章介绍了如何使用dhtmlx-gantt组件来实现公司的甘特图需求,并提供了一个简单的Vue组件示例,文章还分享了一... 目录一、首先 npm 安装插件二、创建一个vue组件三、业务页面内 引用自定义组件:四、dhtmlx

Vue ElementUI中Upload组件批量上传的实现代码

《VueElementUI中Upload组件批量上传的实现代码》ElementUI中Upload组件批量上传通过获取upload组件的DOM、文件、上传地址和数据,封装uploadFiles方法,使... ElementUI中Upload组件如何批量上传首先就是upload组件 <el-upl

Vue3中的动态组件详解

《Vue3中的动态组件详解》本文介绍了Vue3中的动态组件,通过`component:is=动态组件名或组件对象/component`来实现根据条件动态渲染不同的组件,此外,还提到了使用`markRa... 目录vue3动态组件动态组件的基本使用第一种写法第二种写法性能优化解决方法总结Vue3动态组件动态