前言
- 主讲$set
- vue的data里边声明或者已经赋值过的对象或者数组(数组里边的值是对象)时, 不会更新视图
这个时候可以使用
$set
(删除可以用$del
)
- 其实每个对象或者数组, 都加了个dep, 在数据劫持时, 对数据的值也要进行劫持(递归劫持数据),
如果是对象或者数据 将返回本身的
Observer
实例 再在getter
中, 如果返回有数据, 让对象或 者数组dep收集watcher
- 如果添加了数据 就会通知
target.__ob__.dep.notify
更新视图
- 数组的添加和删除用的都是
splice
方法
示例
<div id="app">
{{obj}} - {{arr}}
</div>
<script>
var vm = new Vue({
data: {
obj: {n: 1},
arr: [0]
},
})
vm.$mount('#app')
setTimeout(() => {
vm.$set(vm.obj, 'xxxx', 123456)
vm.$set(vm.arr, 1, 100)
}, 2000)
</script>
正题
$set
和$del
方法
import { set, del } from './observer/index'
Vue.prototype.$set = set
Vue.prototype.$del = del
/**
* @description set
*/
export function set(target, key, value) {
// 数组采用splice方法
if (Array.isArray(target)) {
target.length = Math.max(target.length, key)
target.splice(key, 1, value)
return value
}
// 如果对象本身上已有 返回
if (target.hasOwnProperty(key)) {
target[key] = value
return value
}
const ob = target.__ob__
// 如果数据没有劫持 就是个普通对象 直接赋值 返回
if (!ob) {
target[key] = value
return value
}
// 数据进行劫持
defineReactive(ob.value, key, value)
// 发布
ob.dep.notify()
return value
}
/**
* @description del
*/
export function del (target, key) {
if (Array.isArray(target)) {
target.splice(key, 1)
return
}
const ob = target.__ob__
if (!target.hasOwnProperty(key)) return
delete target[key]
if (!ob) return
ob.dep.notify()
}
observe
class Observer {
constructor(data) {
this.value = data
// 看这里
this.dep = new Dep()
Object.defineProperty(data, '__ob__', {
value: this,
enumerable: false
})
// 其他 ....
}
/**
* @description 劫持对象数据
*/
function defineReactive(data, key, value) {
// 看这里 这里可以获取实例
let childOb = observe(value)
let dep = new Dep()
Object.defineProperty(data, key, {
enumerable: true,
configurable: true,
get() {
if (Dep.target) {
dep.depend()
// 看这里 数组或者对象收集watcher
if (childOb) {
childOb.dep.depend()
// 多层数组[[[]]]
if (Array.isArray(value)) { dependArray(value) }
}
}
return value
},
set(newValue) {
if (newValue !== value) {
observe(newValue)
value = newValue
dep.notify()
}
}
})
}
export function observe(data) {
if (!isObject(data)) return
if (data.__ob__) return data.__ob__
// 对象和数组都可返回实例
return new Observer(data)
}
完
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
- 找不到素材资源介绍文章里的示例图片?
- 对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
- 模板不会安装或需要功能定制以及二次开发?
- 请QQ联系我们
发表评论
还没有评论,快来抢沙发吧!