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

咸宁网站设计互联网公司排名 2022

咸宁网站设计,互联网公司排名 2022,网站建设著作权,潍坊网站模板在哪力有不逮的对象 众所周知#xff0c;在 Vue 中#xff0c;直接修改对象属性的值无法触发响应式。当你直接修改了对象属性的值#xff0c;你会发现#xff0c;只有数据改了#xff0c;但是页面内容并没有改变。 这是什么原因#xff1f; 原因在于#xff1a; Vue 的响应式…力有不逮的对象 众所周知在 Vue 中直接修改对象属性的值无法触发响应式。当你直接修改了对象属性的值你会发现只有数据改了但是页面内容并没有改变。 这是什么原因 原因在于 Vue 的响应式系统是基于Object.defineProperty这个方法的该方法可以监听对象中某个元素的获取或修改经过了该方法处理的数据我们称其为响应式数据。但是该方法有一个很大的缺点新增属性或者删除属性不会触发监听举个栗子 var vm new Vue({data () {return {obj: {a: 1}}} }) // vm.obj.a 现在是响应式的vm.obj.b 2 // vm.obj.b 不是响应式的 复制代码原因在于在 Vue 初始化的时候 Vue 内部会对 data 方法的返回值进行深度响应式处理使其变为响应式数据所以 vm.obj.a 是响应式的。但是之后设置的 vm.obj.b 并没有经过 Vue 初始化时响应式的洗礼所以理所应当的不是响应式。 那么vm.obj.b可以变成响应式吗当然可以通过 vm.$set 方法就可以完美地实现要求在此不再赘述相关原理了之后应该会写一篇文章讲述 vm.$set 背后的原理。 更凄惨的数组 上面说了这么多还没有提到本篇文章的主角——数组现在该主角出场了。 比起对象数组的境遇更加凄惨一些看看官方文档 由于 JavaScript 的限制 Vue 不能检测以下变动的数组 当你利用索引直接设置一个项时例如vm.items[indexOfItem] newValue当你修改数组的长度时例如vm.items.length newLength 有可能官方文档不是很清晰那我们继续举个栗子 var vm new Vue({data () {return {items: [a, b, c]}} }) vm.items[1] x // 不是响应性的 vm.items.length 2 // 不是响应性的 复制代码也就是说数组连自身元素的修改也无法监听原因在于 Vue 对 data 方法返回的对象中的元素进行响应式处理时如果元素是数组时仅仅对数组本身进行响应式化而不对数组内部元素进行响应式化。 这也就导致如官方文档所写的后果无法直接修改数组内部元素来触发响应式。 那么有没有破解方法呢 当然有官方规定了 7 个数组方法通过这 7 个数组方法可以很开心地触发数组的响应式这 7 个数组方法分别是 push()pop()shift()unshift()splice()sort()reverse()可以发现这 7 个数组方法貌似就是原生的那些数组方法为什么这 7 个数组方法可以触发应式触发视图更新呢 你是不是心里想着数组方法了不起呀数组方法就可以为所欲为啊 骚瑞啊这 7 个数组方法是真的可以为所欲为的。 因为它们是变异后的数组方法。 数组变异思路 什么是变异数组方法 变异数组方法即保持数组方法原有功能不变的前提下对其进行功能拓展在 Vue 中这个所谓的功能拓展就是添加响应式功能。 将普通的数组变为变异数组的方法分为两步 功能拓展数组劫持功能拓展 先来个思考题 有这样一个需求要求在不改变原有函数功能以及调用方式的情况下使得每次调用该函数都能在控制台中打印出HelloWorld 其实思路很简单分为三步 使用新的变量缓存原函数重新定义原函数在新定义的函数中调用原函数看看具体的代码实现 function A () {console.log(调用了函数A) }const nativeA A A function () {console.log(HelloWorld)nativeA() } 复制代码可以看到通过这种方式我们就保证了在不改变 A 函数行为的前提下对其进行了功能拓展。 接下来我们使用这种方法对数组原本方法进行功能拓展 // 变异方法名称 const methodsToPatch [push,pop,shift,unshift,splice,sort,reverse ]const arrayProto Array.prototype // 继承原有数组的方法 const arrayMethods Object.create(arrayProto)mutationMethods.forEach(method {// 缓存原生数组方法const original arrayProto[method]arrayMethods[method] function (...args) {const result original.apply(this, args)console.log(执行响应式功能)return result} }) 复制代码从代码中可以看出来我们调用 arrayMethods 这个对象中的方法有两种情况 调用功能拓展方法直接调用 arrayMethods 中的方法调用原生方法这种情况下通过原型链查找定义在数组原型中的原生方法通过上述方法我们实现了对数组原生方法进行功能的拓展但是有一个巨大的问题摆在面前我们该如何让数组实例调用功能拓展后数组方法呢 解决这一问题的方法就是数组劫持。 数组劫持 数组劫持顾名思义就是将原本数组实例要继承的方法替换成我们功能拓展后的方法。 想一想我们在前面实现了一个功能拓展后的数组 arrayMethods 这个自定义的数组继承自数组对象我们只需要将其和普通数组实例连接起来让普通数组继承于它即可。 而想实现上述操作就是通过原型链。 实现方法如下代码所示 let arr [] // 通过隐式原型继承arrayMethods arr.__proto__ arrayMethods// 执行变异后方法 arr.push(1) 复制代码通过功能拓展和数组劫持我们终于实现了变异数组接下来让我们看看 Vue 源码是如何实现变异数组的。 源码解析 我们来到 src/core/observer/index.js 中在 Observer 类中的 constructor 函数 constructor (value: any) {this.value valuethis.dep new Dep()this.vmCount 0def(value, __ob__, this)// 检测是否是数组if (Array.isArray(value)) {// 能力检测const augment hasProto? protoAugment: copyAugment// 通过能力检测的结果选择不同方式进行数组劫持augment(value, arrayMethods, arrayKeys)// 对数组的响应式处理this.observeArray(value)} else {this.walk(value)} } 复制代码Observer 这个类是 Vue 响应式系统的核心组成部分在初始化阶段最主要的功能是将目标对象进行响应式化。在这里我们主要关注其对数组的处理。 其对数组的处理主要是以下代码 // 能力检测 const augment hasProto ? protoAugment : copyAugment // 通过能力检测的结果选择不同方式进行数组劫持 augment(value, arrayMethods, arrayKeys) // 对数组的响应式处理很本文关系不大略过 this.observeArray(value) 复制代码首先定义了 augment 常量这个常量的值由 hasProto 决定。 我们来看看 hasProto export const hasProto __proto__ in {} 复制代码可以发现 hasProto 其实就是一个布尔值常量用来表示浏览器是否支持直接使用 __proto__ 隐式原型 。 所以第一段代码很好理解根据根据能力检测结果选择不同的数组劫持方法如果浏览器支持隐式原型则调用 protoAugment 函数作为数组劫持的方法反之则使用 copyAugment 。 不同的数组劫持方法 现在我们来看看 protoAugment 以及 copyAugment 。 function protoAugment (target, src: Object, keys: any) {/* eslint-disable no-proto */target.__proto__ src/* eslint-enable no-proto */ } 复制代码可以看到 protoAugment 函数极其简洁和在数组变异思路中所说的方法一致将数组实例直接通过隐式原型与变异数组连接起来通过这种方式继承变异数组中的方法。 接下来我们再看看 copyAugment function copyAugment (target: Object, src: Object, keys: Arraystring) {for (let i 0, l keys.length; i l; i) {const key keys[i]// Object.defineProperty的封装def(target, key, src[key])} } 复制代码由于在这种情况下浏览器不支持直接使用隐式原型所以数组劫持方法要麻烦很多。我们知道该函数接收的第一个参数是数组实例第二个参数是变异数组那么第三个参数是什么 // 获取变异数组中所有自身属性的属性名 const arrayKeys Object.getOwnPropertyNames(arrayMethods) 复制代码arrayKeys 在该文件的开头就定义了即变异数组中的所有自身属性的属性名是一个数组。 回头再看 copyAugment 函数就很清晰了将所有变异数组中的方法直接定义在数组实例本身相当于变相的实现了数组的劫持。 实现了数组劫持后我们再来看看 Vue 中是怎样实现数组的功能拓展的。 功能拓展 数组功能拓展的代码位于 src/core/observer/array.js 代码如下 import { def } from ../util/index// 缓存数组原型 const arrayProto Array.prototype // 实现 arrayMethods.__proto__ Array.prototype export const arrayMethods Object.create(arrayProto)// 需要进行功能拓展的方法 const methodsToPatch [push,pop,shift,unshift,splice,sort,reverse ]/*** Intercept mutating methods and emit events*/ methodsToPatch.forEach(function (method) {// cache original method// 缓存原生数组方法const original arrayProto[method]// 在变异数组中定义功能拓展方法def(arrayMethods, method, function mutator (...args) {// 执行并缓存原生数组方法的执行结果const result original.apply(this, args)// 响应式处理const ob this.__ob__let insertedswitch (method) {case push:case unshift:inserted argsbreakcase splice:inserted args.slice(2)break}if (inserted) ob.observeArray(inserted)// notify changeob.dep.notify()// 返回原生数组方法的执行结果return result}) }) 复制代码可以发现源码在实现的方式上和我在数组变异思路中采用的方法一致只不过在其中添加了响应式的处理。 总结 Vue 的变异数组从本质上是来说是一种装饰器模式通过学习它的原理我们在实际工作中可以轻松处理这类保持原有功能不变的前提下对其进行功能拓展的需求。 转载于:https://juejin.im/post/5c05465c518825158c53568e
http://www.huolong8.cn/news/70365/

相关文章:

  • 怎么建设自己网站的后台徐州建站网站模板
  • 衡阳公司做网站百度推广网页版
  • 做学校网站用什么模版seo首页优化
  • ps专门做兼职的网站有哪些宁德时代网站哪个公司做的
  • 网站图片代码怎么做阿里巴巴每平每屋设计家官网
  • vs网站开发杭州旅游团购网站建设
  • 南宁免费自助建站模板珠海市 网站建设
  • 建网站与建网页的区别汕头网页网站制作
  • 网站策划书模板范文网站建设进展报告
  • 网站空间过期网络科技有限公司 网站建设
  • 网站设计公司模板下载网站百度推广方案
  • 宁德网站设计做网站交付标准
  • 电商网站有哪些特色商城类网站建设
  • 互联网站源码安徽建设项目建设工程在线
  • 广告网站留电话不用验证码wordpress注册跳过邮箱验证
  • 做网站客户一般会问什么问题做pc端网站精英
  • 网站建设方案格式整个网站的关键词
  • 南宁网站推广哪家好网站建设得花多少钱
  • 网站优化方案和实施自学移动端网站开发
  • 网站建设简单流程图用jsp做网站怎么分区
  • wpf可以应用于网站开发吗wordpress轻社区
  • eclipse 简单网站开发软件开发具体是做什么
  • python做网站例子医疗器械招商网站大全
  • 网站设计摘要 优帮云免费网站的代码
  • 义乌品牌网站建设wordpress伪静态不跳转404
  • 不用网站做淘宝客广州短视频运营营销报价
  • 优秀的图片设计网站推荐萧县建设局网站
  • 网站开发的人凡氪官网
  • 网站设计项目国外点击链接推广平台
  • 网站建设与功能模块网站设计公司-信科网络