Vue 基础
Vue 中封装的数组方法
push, pop, shift, unshift, splice, sort, reverse
Object.defineProperty() 不是不能监听到数组方法,而是 Vue 为了性能,没有对数组进行响应式处理。
观察者模式
在观察者模式中,只有两个主体,分别是目标对象Subject
,观察者Observer
- 观察者需
Observer
要实现update
方法 Subject
需要维护自身的观察者数组observerList
,当自身发生变化时,通过调用自身的notify
方法,依次通知每一个观察者执行update
方法
// 观察者
class Observer {
/**
* 构造器
* @param {Function} cb 回调函数,收到目标对象通知时执行
*/
constructor(cb) {
if (typeof cb === 'function') {
this.cb = cb
} else {
throw new Error('Observer构造器必须传入函数类型!')
}
}
/**
* 被目标对象通知时执行
*/
update() {
this.cb()
}
}
// 目标对象
class Subject {
constructor() {
// 维护观察者列表
this.observerList = []
}
/**
* 添加一个观察者
* @param {Observer} observer Observer实例
*/
addObserver(observer) {
this.observerList.push(observer)
}
/**
* 通知所有的观察者
*/
notify() {
this.observerList.forEach((observer) => {
observer.update()
})
}
}
const observer = new Observer(() => {
console.log('我被通知了')
})
const subject = new Subject()
subject.addObserver(observer)
subject.notify()
js双向绑定
React 是单项数据绑定,双向数据绑定可以理解为给 input 之类的标签绑定 change 事件,通过 view 更新 model
Vue 采用数据劫持
结合发布者-订阅者模式
的方式,实现数据响应式
effect 订阅响应式数据,Proxy 拦截响应式数据的变更,发布事件执行 effect 回调
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])
js<script setup>
const model = defineModel()
</script>
<template>
<input v-model="model" />
</template>
vue发布订阅模式
发布订阅模式中,对于发布者 Publisher 和订阅者 Subscriber 没有特殊的约束,他们好似是匿名活动,借助事件调度中心提供的接口发布和订阅事件,互不了解对方是谁。
类比于 DOM 事件中的 dispatchEvent 和 addEventListener
class PubSub {
constructor() {
// 维护事件及订阅行为
this.events = {}
}
/**
* 注册事件订阅行为
* @param {String} type 事件类型
* @param {Function} cb 回调函数
*/
subscribe(type, cb) {
if (!this.events[type]) {
this.events[type] = []
}
this.events[type].push(cb)
}
/**
* 发布事件
* @param {String} type 事件类型
* @param {...any} args 参数列表
*/
publish(type, ...args) {
if (this.events[type]) {
this.events[type].forEach((cb) => {
cb(...args)
})
}
}
}
jsvue 初始化页面闪动问题
使用 vue 开发时,在 vue 初始化之前,由于 div 是不归 vue 管的,所以我们写的代码在还没有解析的情况下会容易出现花屏现象,看到类似于 {{message}}
的字样,虽然一般情况下这个时间很短暂,但是还是有必要让解决这个问题的。
[v-cloak] {
display: none;
}
css如果没有彻底解决问题,则在根元素加上style="display: none;" :style="{display: 'block'}"