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

灯光设计网站推荐新媒体营销期末试卷及答案

灯光设计网站推荐,新媒体营销期末试卷及答案,平面设计人才网,榆林做网站的公司电话Set和Map类型的数据也属于异质对象,它们有特定的属性和方法用来操作自身。因此创建代理时,针对特殊的方法需要特殊的对待。 Vue 的ref 是基于reactive函数实现的,它在其基础上,增加了基本类型的响应性、解决reactive在解构时丢失…

 Set和Map类型的数据也属于异质对象,它们有特定的属性和方法用来操作自身。因此创建代理时,针对特殊的方法需要特殊的对待。

Vue 的ref 是基于reactive函数实现的,它在其基础上,增加了基本类型的响应性、解决reactive在解构时丢失响应性的问题及在模版字面量中自动脱落Ref.

1 代理Set和Map

function createReactive(obj,isShallow = false) {return new Proxy(obj, {get(target, p, receiver) {track(target,p)const value = Reflect.get(target,p,receiver)if (isShallow) return valuereturn typeof value === 'object' && value !== null ? reactive(value) : value},// 省略其他代码})
}const proxyObj = reactive(new Set())
// 报错 Method get Set.prototype.size called on incompatible receiver 
console.log(proxyObj.size)

上面代码报错:receiver上不兼容size方法。这是因为上面代码中,receiver 指向Proxy的代理对象,它是没有size方法的。下面是对get方法改进。

get(target, p, receiver) {if (p === 'size') return Reflect.get(target,p,target)// 省略其他代码
},

但是,改进后再执行proxyObj.add(1),又报错:receiver 上不兼容add方法。因为是proxyObj执行add函数,add函数里的this始终指向proxyObj。这是可以使用函数的bind方法,来绑定函数中this的值。

get(target, p, receiver) {// 省略其他代码const value = Reflect.get(target,p,receiver)if (typeof value === 'function') return value.bind(target)if (isShallow) return valuereturn typeof value === 'object' && value !== null ? reactive(value) : value
},

1.1 建立响应联系

  1. size属性是一个只读属性,Set的add、delete会改变它的值。
  2. 调用Set的add方法时,如果元素已存在于Set中,就不需要触发响应。调用Set的delete方法时,如果元素不存在于Set中,也不需要触发响应。
const mutableInstrumentation = {add(key) {const target = this.rawconst hadKey = target.has(key)const res = target.add(key)if (!hadKey && res) {trigger(target, key, 'ADD')}return res},delete(key) {const target = this.rawconst hadKey = target.has(key)const res = target.delete(key)if (hadKey && res) {trigger(target, key,'DELETE')}return res}
}
// Proxy 中的get代理
get(target, p, receiver) {// 省略其他代码track(target,p)if (mutableInstrumentation.hasOwnProperty(p)) {return mutableInstrumentation[p]}// 省略其他代码
},

1.2 避免污染原始数据

const proxySet = reactive(new Set())
const map = new Map()
const proxyMap = reactive(map)
proxyMap.set('set',proxySet)
effect(() => {console.log(map.get('set').size)
})
console.log("----------------")
proxySet.add(1) // 触发响应

上面原始数据具有了响应性,这不符合需求(原始数据应不具备响应性)。产生这个的原因是,在设置值时,直接把响应体对象也添加进原始对象了。所以,解决的关键在于:设置值时,如果该对象是响应体对象,则取其目标对象。

// mutableInstrumentation 对象的set方法
set(key,value) {const target = this.rawconst had = target.has(key)const oldValue = target.get(key)target.set(key,value.raw || value) // 去目标对象if (!had) {track(target, 'key', 'ADD')} else if (oldValue !== value && (oldValue === oldValue || value === value)) {trigger(target,key,'SET')}
}

1.3 处理forEach

1)forEach 只与键值对的数量有关,所以当forEach被调用时,让ITERATE_KEY与副作用函数建立联系。

2)当set方法设置的属性存在时,但属性值不同时,也应该触发forEach。

3)forEach函数的参数callback,它是有原始对象调用的,这意味着callback函数中的value及key两个参数不具有响应性,但是它们应该都具备响应性,需要将这两个参数转成响应体。

// mutableInstrumentation 对象的forEach方法
forEach(callback) {const target = this.rawconst wrap = (val) => typeof val === 'object' ? reactive(val) : valtrack(target,ITERATE_KEY)target.forEach((v,k) => {callback(wrap(v),wrap(k),this)})
}function trigger(target,p,type,newValue) {const map = effectMap.get(target)if (map) {// 省略其他代码if (type === 'ADD' || type === 'DELETE' || (type === 'SET' && Object.prototype.toString.call(target) === '[object Map]')) {// 省略其他代码}// 省略其他代码		}
}

1.4 迭代器方法

集合类型有三个迭代器方法:entries、keys、values,还可以使用 for...of进行迭代。

  1. 使用for...of迭代一个代理对象时,内部会调用[Symbol.iterator]()方法,返回一个迭代器。迭代产生的值不具备响应性,所以需要把这些值包装成响应体。
  2. 可迭代协议指一个对象实现了Symbol.iterator方法,迭代器协议是指一个对象实现了next方法。而entries方法要求返回值是一个可迭代对象,即该对象要实现了Symbol.iterator方法。
  3. values 方法,返回的仅是Map的值,而非键值对。
  4. keys 方法,与上面不同的是,调用set时,如果非添加值,则不应该触发响应。
function trigger(target,p,type,newValue) {const map = effectMap.get(target)if (map) {// 省略其他代码if (type === 'ADD' || type === 'DELETE' && Object.prototype.toString.call(target) === '[object Map]') {const tempSet = map.get(MAP_KEY_ITERATE_KEY)tempSet && tempSet.forEach(fn => {if (activeEffectFun !== fn) addSet.add(fn)})}addSet.forEach(fn => fn())}
}const mutableInstrumentation = {// 省略其他代码[Symbol.iterator]: iterationMethod,entries: iterationMethod,values: valueIterationMethod,keys: keyIterationMethod
}function iterationMethod() {const target = this.rawconst itr = target[Symbol.iterator]()const wrap = (val) => typeof val === 'object' && val != null ? reactive(val) : valtrack(target,ITERATE_KEY)return {next() {const {value,done} = itr.next()return {value: value ? [wrap(value[0]),wrap(value[1])] : value,done}},[Symbol.iterator]() {return this}}
}
function valueIterationMethod() {const target = this.rawconst itr = target.values()const wrap = (val) => typeof val === 'object' && val != null ? reactive(val) : valtrack(target,ITERATE_KEY)return {next() {const {value,done} = itr.next()return {value: wrap(value),done}},[Symbol.iterator]() {return this}}
}
function keyIterationMethod() {const target = this.rawconst itr = target.keys()const wrap = (val) => typeof val === 'object' && val != null ? reactive(val) : valtrack(target,MAP_KEY_ITERATE_KEY)return {next() {const {value,done} = itr.next()return {value: wrap(value),done}},[Symbol.iterator]() {return this}}
}

2 原始值的响应方案ref

Proxy 的代理目标必须是非原始值,如果要让原始值具有响应性,那么要对它进行包装。Vue3 的ref函数就负责这个工作。

function ref(val) {const wrapper = {value: val}// 为了区分数据是经过ref包装的,还是普通对象Object.defineProperty(wrapper,'_v_isRef',{value: true})return reactive(wrapper)
}

2.1 reactive 解构时丢失响应性

const proxyObj = reactive({name: 'hmf',num: 1})
const obj = {...proxyObj} // obj 不再具有响应性。这是因为解构时
{…proxyObj} 等价于 {name: 'hmf',num: 1}

要让obj 具有响应性,则需要使其属性值为一个对象。如下所示:

const obj = {name: {get value() {return proxyObj.name},set value(val) {proxyObj['name'] = val}},num: {get value() {return proxyObj.num},set value(val) {proxyObj['num'] = val}}
}

ref函数优化如下:

function toRefs(obj) {const ret = {}for (const key in obj) {ret[key] = toRef(obj,key)}return ret
}function toRef(obj,key) {const wrapper = {get value() {return obj[key]},set value(val) {obj[key] = val}}Object.defineProperty(wrapper,'_v_isRef',{value: true})return wrapper
}

2.2 自动脱ref

经过toRefs处理的对象,都需要通过对象的value属性来访问,例如

const proxyObj = ref({name: 'hmf',num: 1})
console.log(proxyObj.name.value)
proxyObj.name.value = 'hi'

访问任何属性都需要通过value属性访问,这增加了用户的心智负担。我们需要自动脱ref的能力,即上面proxy.name就可直接访问。

function proxyRefs(target) {return new Proxy(target, {get(target, p, receiver) {const value = Reflect.get(target,p,receiver)return value._v_isRef ? value.value : value},set(target, p, newValue, receiver) {const value = target[p]if (value._v_isRef) {value.value = newValuereturn true}return Reflect.set(target,p,newValue,receiver)},})
}
http://www.yayakq.cn/news/902737/

相关文章:

  • 网站项目建设建设期在线培训系统软件
  • 网站开发可行性分析大庆商城网站建设
  • 电子商务的网站建设要求步骤广州线上推广公司
  • 温州网站开发赣州建站
  • 天津做网站那家好wordpress的批量上传
  • 品牌网站建设内容框架常德县
  • 重庆网站制作哪家好能进封禁网站的浏览器
  • 如何做电商网站分析报告河南省城乡与住房建设厅网站首页
  • 网站侧面的虚浮代码别人网站 自己的二级域名
  • 网站设计公司有原型怎么做网站
  • 爱站网关键词挖掘工具熊猫html设计软件
  • 网页设计汽车网站建设wordpress免费资源模板
  • 装修设计案例网站网站挂黑链赚钱
  • 微网站排版西安互联网品牌搭建
  • 英文网站群建设百度app优化
  • 电子商务网站开发岗位模板类网站建设
  • 国外产品展示网站源码西安建设工程信息网官网入口
  • 网站备案资料查询公司做网站怎么构思
  • dede网站栏目管理空白wordpress 在线投稿
  • 罗湖网站建设罗湖网站设计国外免备案域名注册
  • 制作一个响应式网站开发工具女人做春梦视频网站
  • wordpress建站教程第六节润滑油东莞网站建设技术支持
  • dw做网站首页怎么做河南省住房和城乡建设厅
  • phpwind的代表网站双城网站
  • 建设项目自主验收公示的网站企业网站建设 广州
  • 宝山专业做网站游戏软件开发流程
  • 企业建设网站方案设计phpmyadmin wordpress
  • 可以做百度百科参考资料的网站做网站泰安
  • 区总工会网站建设流程全站加速 wordpress
  • 多语种 小语种网站推广方法搭建网站软件