当前位置: 首页 > news >正文

c mvc网站开发杭州科技公司

c mvc网站开发,杭州科技公司,竞价排名采用什么计费方式,怎么做跟别人一样的网站vue3响应式原理初探 为什么要使用proxy取代defineProperty使用proxy如何完成依赖收集呢? 为什么要使用proxy取代defineProperty 原因1:defineproperty无法检测到原本不存在的属性。打个🌰 new Vue({data(){return {name:wxs,age:25}}})在vue…

vue3响应式原理初探

  • 为什么要使用proxy取代defineProperty
  • 使用proxy如何完成依赖收集呢?

为什么要使用proxy取代defineProperty

原因1:defineproperty无法检测到原本不存在的属性。打个🌰

	new Vue({data(){return {name:'wxs',age:25}}})

在vue2中,底层会通过definproperty来响应式data返回的对象,也就是{name:'wxs',age:25},具体的响应式监听如下。

	const obj = {name:'wxs',age:25}Object.entries(obj).forEach(([key,value]) => {Object.defineProperty(obj,key,{get(){return value},set(newValue){console.log(`监听到属性${key}改变`)value = newValue}})})obj.name = 11obj.age = 22obj.ak47 = 'ak47'

看看控制台输出
请添加图片描述
可以看出,由于初始化中并没有初始化ak47,所以在vue2中对未初始化的对象key值的修改是无法监听到的。
再来看看es6新特性proxy的优越性

 const obj = {name:'wxs',age:25}const prxoyTarget = new Proxy(obj,{get(target,key){return target.key},set(target,key,value){console.log(`监听到${key}需要改成${value}`)target[key] = value}})prxoyTarget.name = 11prxoyTarget.age = 22prxoyTarget.ak47 = 'ak47'

在这里插入图片描述
所以回答这个问题的思路就很清晰了
1、proxy可以完成对未初始化对象key的代理监听,而definproperty不可以,相比较之下,proxy更加优越。
2、由vue2的响应式原理可以看出,vue底层需要对vue实例的返回的每一个key进行get和set操作,无论这个值有没有被用到。所以在vue中定义的data属性越多,那么初始化开销就会越大。而proxy是一个惰性的操作,它只会在用到这个key的时候才会执行get,改值的时候才会执行set。所以在vue3中实现响应式的性能实际上要比vue2实现响应式性能要好。

使用proxy如何完成依赖收集呢?

首先看到vue3官网中给出的初始化一个vue实例的基础用法。
在这里插入图片描述
因为我们需要响应式一个对象,所以我们使用reactive api。

<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script><div id="app">{{ message }}</div><script>const { createApp, reactive, toRefs } = VuecreateApp({setup() {const data = reactive({name: 'wxs'})return data}}).mount('#app')
</script>

由这个简单的实例可得知,vue对象内部首先暴露了一个createApp函数用于新建vue实例,那么大致写出Vue内部的执行逻辑,注意看以下代码,重点部分都有注释讲解

const Vue = {// 从官网示例可得,从vue中解构出了createApp函数,那么其内部肯定有createApp的定义createApp(options){// createApp实现细节后文补充return {// 在mount中执行初次挂载mount(domSelector){// 在vue3的源码中也会在mount中执行挂载任务,但是由于此文主要讲解的是vue3的响应式原理,那么AST解析和diff比较就略过,直接显示setup的返回值即可(也就是模拟vue的模版内容为 <div>{{ name }}</div>)。  document.querySelector(domSelector).innerHTML = '页面渲染'}}},// 响应式代理,在前一小节有介绍,此节不做赘述。reactive(target){return new Proxy(target,{get(target,key){// 代理对象的get方法return target[key]},set(target,key,newValue){// 代理对象的set方法target[key] = newValue}})}}

将上述代码执行之后,浏览器应该会出现如下页面
在这里插入图片描述
但是很明显,我们想要将响应式数据呈现在页面上。比如代码中定义到的name。那么我们可以将createApp做如下改写。具体思路是拿出setUp的返回值。然后将返回值渲染到页面。

	 createApp(options) {let dataSource = nullif (options.setup) {dataSource = options.setup()}return {// 在mount中执行初次挂载mount(domSelector) {document.querySelector(domSelector).innerHTML = dataSource.name}}},	

这样就将响应式数据和template模版之间构建了联系。(但是千万不要被这个简化的代码所迷惑,实际上vue底层会执行diff算法来比较最小化更新之后在渲染页面。因为此文是介绍vue3的响应式原理,所以此过程略过)
完成createApp的补充之后,实际上我们已经完成了vue的初次渲染工作。那么剩下的就是需要完成vue组件的更新工作了(其实也就是说,在响应式数据更新的时候,重新执行一下mount里的代码完成页面刷新)
理清思路之后,稍微重构一下mount函数

mount(domSelector) {const update = () => document.querySelector(domSelector).innerHTML = dataSource.nameeffect(update)}

实际上,vue3是通过effect函数来将更新函数和响应式数据来建立链接。所谓的建立链接,也就是通过effect执行的函数中如果包含了响应式对象,如果响应式对象发生改变,函数就会重新执行。
来看看effect函数的实现细节。

	let currentCallback = nullconst effect = (callback) => {currentCallback = callbackcallback()currentCallback = null}

有同学可能会问了,先存一下callback,然后执行一下更新函数,再置空,那么这个赋值不就是脱了裤子放屁-----多此一举吗?那么看看这两行中间夹缝生存的的这一行神奇的代码callback()。执行一下传入的callback,那么也就是update函数。如果执行update函数必然会触发dataSource.name的get方法。那么我们就可以在这里完成依赖收集。将代理对象和key和更新函数之间建立如下的链接关系。
在这里插入图片描述

	// 在get里面触发依赖收集get(target, key) {track(target,key)// 代理对象的get方法return target[key]},
// 从上图出发,定义的track函数const track = (target,key) => {let depMap = reactiveMap.get(target)if(!depMap){depMap = new Map()reactiveMap.set(target,depMap)}let watcherSet = depMap.get(key)if(!watcherSet){watcherMap = new Set();watcherSet.add(currentCallback)depMap.set(key,watcherSet)}}
	// 依赖收集完成,定义触发函数 触发函数其实就是track函数的逆运算,把track存起来的东西全部取出来const trigger = (target, key) => {reactiveMap.get(target).get(key).forEach(cb => cb())}

最后将trigger写到set里面。

	 set(target, key, newValue) {// 代理对象的set方法target[key] = newValuetrigger(target, key)}

大功告成,可以直接改变对象值看看效果。

	createApp({setup() {const data = reactive({name: 'wxs'})setTimeout(() => {data.name = '456'}, 1000)return data}}).mount('#app')

老规矩 贴上全部代码

<!DOCTYPE html>
<html><head><meta charset="UTF-8"><!-- import CSS --><link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"><style>.pagination-container {position: sticky;bottom: 0;z-index: 100;}#box {width: 100%;height: 50%;background: black;}</style>
</head><body><div id="app">{{name}}</div>
</body><!-- <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script> --><script>let currentCallback = nullconst effect = (callback) => {currentCallback = callbackcallback()currentCallback = null}let reactiveMap = new Map();const track = (target, key) => {let depMap = reactiveMap.get(target)if (!depMap) {depMap = new Map()reactiveMap.set(target, depMap)}let watcherSet = depMap.get(key)if (!watcherSet) {watcherSet = [];watcherSet.push(currentCallback)depMap.set(key, watcherSet)}}const trigger = (target, key) => {reactiveMap.get(target).get(key).forEach(cb => cb())}const Vue = {createApp(options) {let dataSource = nullif (options.setup) {dataSource = options.setup()}return {// 在mount中执行初次挂载mount(domSelector) {const update = () => document.querySelector(domSelector).innerHTML = dataSource.nameeffect(update)}}},reactive(target) {return new Proxy(target, {get(target, key) {track(target, key)// 代理对象的get方法return target[key]},set(target, key, newValue) {// 代理对象的set方法target[key] = newValuetrigger(target, key)}})}}const { createApp, reactive } = VuecreateApp({setup() {const data = reactive({name: 'wxs'})setTimeout(() => {data.name = '456'}, 1000)return data}}).mount('#app')</script>
</html>

各位看官稍安勿躁,全部代码算上css才100行,当然,vue内部实现肯定比我这个要复杂,比如它内部存更新函数是用的set等等,但是对于响应式原理而言,我们只需要拿出最精华的部分即可。第一遍看不懂没关系,我看视频也是看了七八遍才看懂,各位coder们一定要有耐心,拿下vue3响应式!

http://www.yayakq.cn/news/206176/

相关文章:

  • 电子商务网站开发与建设试卷网站配色方法
  • 瀑布流网站后台麻将网站怎么做的
  • 北京互联网公司建网站路由器做映射后 内网可以访问到我的网站 但是外网无法访问
  • 免费字体设计 常见网站怎样做市场营销策划
  • huang色网站医院网站设计方案
  • php 网站版面素材网站制作推广招聘
  • 手机网站安全证书过期怎么处理网站实名认证资料
  • 网页制作与网站建设试题企业信息查询官网系统
  • 巴中网站制作公司公司网站建设需要注意哪些内容
  • 成都科技网站建设找帝国网站程序
  • 网站建设 兼职 外包阿里巴巴运营岗位
  • 用记事本做网站网站建设设计流程
  • 12380网站建设情况总结企业网站用户群
  • 怎么做公司官方网站企业网站设计模板
  • 网站空间付款方式网站内置多语言
  • 响应式酒店网站模板win优化大师官网
  • 移动网站建站做网站优化常用工具
  • 唐汉网站建设wordpress侧边栏浮动
  • 宁波网站建设方案联系方式服务器维修
  • 网站的下拉列表怎么做海沧建设局网站
  • 网站建设需要的框架结构wordpress插件使用方法
  • 鹤山市住房和城乡建设局网站简述网站规划的一般步骤
  • 免费网站建设找云狄wordpress自定义页面分页
  • 临沂电商网站建设网站开发东莞
  • 网站怎么做浏览量才会多手机设计图制作软件app免费
  • asp在网站开发中起什么作用wordpress主题缩略图
  • 网站制作企业对比北京企业网站备案需要多久
  • 国内网站搭建googleplay商店
  • 注册公司网站优化百度百科
  • 阿里云做电脑网站公司变更登记申请书下载