最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue3響應(yīng)式對象Reactive和Ref的用法解讀

 更新時(shí)間:2022年09月07日 10:49:43   作者:SunsetFeng  
這篇文章主要介紹了Vue3響應(yīng)式對象Reactive和Ref的用法,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

一、內(nèi)容簡介

本篇文章著重結(jié)合源碼版本V3.2.20介紹Reactive和Ref。前置技能需要了解Proxy對象的工作機(jī)制,以下貼出的源碼均在關(guān)鍵位置備注了詳細(xì)注釋。

備注:本篇幅只講到收集依賴和觸發(fā)依賴更新的時(shí)機(jī),并未講到如何收集依賴和如何觸發(fā)依賴。響應(yīng)式原理快捷通道。

二、Reactive

1. 關(guān)鍵源碼

/*源碼位置:/packages/reactivity/src/reactive.ts*/
/**
?* 創(chuàng)建響應(yīng)式代理對象
?* @param target 被代理對象
?* @param isReadonly 是否只讀
?* @param baseHandlers 普通對象的攔截操作
?* @param collectionHandlers 集合對象的攔截操作
?* @param proxyMap 代理Map
?* @returns?
?*/
function createReactiveObject(
? target: Target,
? isReadonly: boolean,
? baseHandlers: ProxyHandler<any>,
? collectionHandlers: ProxyHandler<any>,
? proxyMap: WeakMap<Target, any>
) {
? //如果不是對象,則警告,Proxy代理只支持對象
? if (!isObject(target)) {
? ? if (__DEV__) {
? ? ? console.warn(`value cannot be made reactive: ${String(target)}`)
? ? }
? ? return target
? }
? //如果被代理對象已經(jīng)是一個(gè)proxy對象且是響應(yīng)式的并且此次創(chuàng)建的新代理對象不是只讀的,則直接返回被代理對象
? //這兒存在一種情況需要重新創(chuàng)建,即被代理對象已經(jīng)是一個(gè)代理對象了,且可讀可寫。但新創(chuàng)建的代理對象是只讀的
? //那么,本次生成的那個(gè)代理對象最終是只讀的。響應(yīng)式必須可讀可寫,只讀的代理對象是非響應(yīng)式的。
? if (
? ? target[ReactiveFlags.RAW] &&
? ? !(isReadonly && target[ReactiveFlags.IS_REACTIVE])
? ) {
? ? return target
? }
? //從map中找,如果對象已經(jīng)被代理過,則直接從map中返回,否則生成代理
? const existingProxy = proxyMap.get(target)
? if (existingProxy) {
? ? return existingProxy
? }
? // 獲取代理類型,即采用集合類型的代理還是普通對象類型的代理
? const targetType = getTargetType(target)
? if (targetType === TargetType.INVALID) {
? ? return target
? }
? // 生成代理對象并存入map中
? const proxy = new Proxy(
? ? target,
? ? targetType === TargetType.COLLECTION ? collectionHandlers : baseHandlers
? )
? proxyMap.set(target, proxy)
? return proxy
}

2. 源碼流程分析

Vue中創(chuàng)建響應(yīng)式代理對象都是通過createReactiveObject方法創(chuàng)建。這個(gè)方法里面的主要邏輯很簡單,就是生成一個(gè)目標(biāo)對象的代理對象,代理對象最為核心的操作攔截則由外部根據(jù)是否只讀和是否淺響應(yīng)傳入,然后將這個(gè)代理對象存起來以備下次快捷獲取。

三、代理攔截操作

1. 數(shù)組操作

(1).關(guān)鍵源碼

//源碼位置: /packages/reactivity/src/baseHandlers.ts
function createArrayInstrumentations() {
? const instrumentations: Record<string, Function> = {}
? // instrument identity-sensitive Array methods to account for possible reactive
? // values
? ;(['includes', 'indexOf', 'lastIndexOf'] as const).forEach(key => {
? ? instrumentations[key] = function (this: unknown[], ...args: unknown[]) {
? ? ? //獲取原始數(shù)組
? ? ? const arr = toRaw(this) as any
? ? ? for (let i = 0, l = this.length; i < l; i++) {
? ? ? ? //收集依賴 鍵值為索引 i
? ? ? ? track(arr, TrackOpTypes.GET, i + '')
? ? ? }
? ? ? // 調(diào)用數(shù)組的原始方法
? ? ? const res = arr[key](...args)
? ? ? if (res === -1 || res === false) {
? ? ? ? // 如果不存在,則將參數(shù)參數(shù)轉(zhuǎn)換為原始數(shù)據(jù)在試一次(這兒可能是防止傳入的是代理對象導(dǎo)致獲取失敗)
? ? ? ? return arr[key](...args.map(toRaw))
? ? ? } else {
? ? ? ? return res
? ? ? }
? ? }
? })
? // instrument length-altering mutation methods to avoid length being tracked
? // which leads to infinite loops in some cases (#2137)
? ;(['push', 'pop', 'shift', 'unshift', 'splice'] as const).forEach(key => {
? ? instrumentations[key] = function (this: unknown[], ...args: unknown[]) {
? ? ? //由于上面的方法會(huì)改變數(shù)組長度,因此暫停收集依賴,不然會(huì)導(dǎo)致無限遞歸
? ? ? pauseTracking()
? ? ? //調(diào)用原始方法
? ? ? const res = (toRaw(this) as any)[key].apply(this, args)
? ? ? //復(fù)原依賴收集
? ? ? resetTracking()
? ? ? return res
? ? }
? })
? return instrumentations
}

(2).源碼流程分析

上述源碼其實(shí)就是重寫了對于數(shù)組方法的操作,在通過數(shù)組的代理對象訪問以上數(shù)組方法時(shí),就會(huì)執(zhí)行重寫后的數(shù)組方法。

內(nèi)部邏輯很簡單,對于改變了數(shù)組長度的方法,先暫停依賴收集,調(diào)用原始數(shù)組方法,然后復(fù)原依賴收集。

對于判斷元素是否存在的數(shù)組方法,執(zhí)行依賴收集并調(diào)用數(shù)組原始方法。

總結(jié)來說最終都是調(diào)用了數(shù)組的原始方法,只不過在調(diào)用前后添加了關(guān)于依賴收集相關(guān)的行為。

2.Get操作

(1).關(guān)鍵源碼

//源碼位置: /packages/reactivity/src/baseHandlers.ts
/**
?* 創(chuàng)建并且返回一個(gè)Get方法
?* @param isReadonly 是否只讀
?* @param shallow 是否淺響應(yīng)
?* @returns?
?*/
function createGetter(isReadonly = false, shallow = false) {
? return function get(target: Target, key: string | symbol, receiver: object) {
? ? //這兒不重要,其實(shí)就是通過代理對象訪問這幾個(gè)特殊屬性時(shí),返回相應(yīng)的值,和響應(yīng)式無關(guān)
? ? if (key === ReactiveFlags.IS_REACTIVE) {
? ? ? return !isReadonly
? ? } else if (key === ReactiveFlags.IS_READONLY) {
? ? ? return isReadonly
? ? } else if (
? ? ? key === ReactiveFlags.RAW &&
? ? ? receiver ===
? ? ? ? (isReadonly
? ? ? ? ? ? shallow
? ? ? ? ? ? ? shallowReadonlyMap
? ? ? ? ? ? : readonlyMap
? ? ? ? ? : shallow
? ? ? ? ? ? shallowReactiveMap
? ? ? ? ? : reactiveMap
? ? ? ? ).get(target)
? ? ) {
? ? ? return target
? ? }
??
? ? const targetIsArray = isArray(target)
? ? //如果是調(diào)用的數(shù)組方法,則調(diào)用重寫后的數(shù)組方法,前提不是只讀的
? ? if (!isReadonly && targetIsArray && hasOwn(arrayInstrumentations, key)) {
? ? ? return Reflect.get(arrayInstrumentations, key, receiver)
? ? }
? ? //調(diào)用原始行為獲取值
? ? const res = Reflect.get(target, key, receiver)
? ? //訪問Symbol對象上的屬性和__proto__,__v_isRef,__isVue這3個(gè)屬性,直接返回結(jié)果值
? ? if (isSymbol(key) ? builtInSymbols.has(key) : isNonTrackableKeys(key)) {
? ? ? return res
? ? }
? ? if (!isReadonly) {
? ? ? //不是只讀,則收集依賴
? ? ? track(target, TrackOpTypes.GET, key)
? ? }
? ? if (shallow) {
? ? ? //如果對象是淺響應(yīng)的 則返回結(jié)果
? ? ? return res
? ? }
? ? if (isRef(res)) {
? ? ? //如果值是Ref對象且是通過數(shù)組代理對象的下標(biāo)訪問的,則不做解包裝操作,否則返回解包裝后的值
? ? ? // ref unwrapping - does not apply for Array + integer key.
? ? ? const shouldUnwrap = !targetIsArray || !isIntegerKey(key)
? ? ? return shouldUnwrap ? res.value : res
? ? }
? ? if (isObject(res)) {
? ? ? //走到這兒需要滿足非淺響應(yīng)。如果結(jié)果是一個(gè)對象,則將改對象轉(zhuǎn)換為只讀代理對象或者響應(yīng)式代理對象返回
? ? ? //e.g.?
? ? ? // test:{
? ? ? // ? a:{
? ? ? // ? ? c:10
? ? ? // ? }
? ? ? // }
? ? ? //以上測試對象當(dāng)訪問屬性a時(shí),此時(shí)res是一個(gè)普通對象,如果不轉(zhuǎn)換為代理對象,則對a.c的操作不會(huì)被攔截處理,導(dǎo)致無法響應(yīng)式處理
? ? ? // Convert returned value into a proxy as well. we do the isObject check
? ? ? // here to avoid invalid value warning. Also need to lazy access readonly
? ? ? // and reactive here to avoid circular dependency.
? ? ? return isReadonly ? readonly(res) : reactive(res)
? ? }
? ??
? ? return res
? }
}

(2).源碼流程分析

上述Get方法是在通過代理對象獲取某一個(gè)值時(shí)觸發(fā)的。流程很簡單,就是對幾個(gè)特殊屬性做了特殊返回。

如果是數(shù)組方法,則調(diào)用重寫后的數(shù)組方法,不是則調(diào)用原始行為獲取值。

如果不是只讀,則收集依賴,對返回結(jié)果進(jìn)行判斷特殊處理。其中最關(guān)鍵的地方在于收集依賴和將獲取到的嵌套對象轉(zhuǎn)換為響應(yīng)式對象。

3. Set操作

(1).關(guān)鍵源碼

//源碼位置: /packages/reactivity/src/baseHandlers.ts
/**
?* 創(chuàng)建并返回一個(gè)Set方法
?* @param shallow 是否淺響應(yīng)
?* @returns?
?*/
function createSetter(shallow = false) {
? return function set(
? ? target: object,
? ? key: string | symbol,
? ? value: unknown,
? ? receiver: object
? ): boolean {
? ? //獲取改變之前的值
? ? let oldValue = (target as any)[key]
? ? if (!shallow) {
? ? ? value = toRaw(value)
? ? ? oldValue = toRaw(oldValue)
? ? ? //對Ref類型值的特殊處理
? ? ? //比較2個(gè)值,如果舊值是Ref對象,新值不是,則直接變Ref對象的value屬性
? ? ? if (!isArray(target) && isRef(oldValue) && !isRef(value)) {
? ? ? ? //這兒看似沒有觸發(fā)依賴更新,其實(shí)Ref對象的value進(jìn)行賦值會(huì)觸發(fā)Ref對象的寫操作,在那個(gè)操作里面會(huì)觸發(fā)依賴更新
? ? ? ? oldValue.value = value
? ? ? ? return true
? ? ? }
? ? } else {
? ? ? // in shallow mode, objects are set as-is regardless of reactive or not
? ? }
? ? const hadKey =
? ? ? isArray(target) && isIntegerKey(key)
? ? ? ? ? Number(key) < target.length
? ? ? ? : hasOwn(target, key)
? ? const result = Reflect.set(target, key, value, receiver)
? ? // don't trigger if target is something up in the prototype chain of original
? ? // 這個(gè)判斷其實(shí)是處理一個(gè)代理對象的原型也是代理對象的情況,以下是測試代碼
? ? // let hiddenValue: any
? ? // const obj = reactive<{ prop?: number }>({})
? ? // const parent = reactive({
? ? // ? set prop(value) {
? ? // ? ? hiddenValue = value
? ? // ? },
? ? // ? get prop() {
? ? // ? ? return hiddenValue
? ? // ? }
? ? // })
? ? // Object.setPrototypeOf(obj, parent)
? ? // obj.prop = 4
? ? // 當(dāng)存在上述情形,第一次設(shè)置值時(shí),由于子代理沒有prop屬性方法,會(huì)觸發(fā)父代理的set方法。父代理的這個(gè)判斷此時(shí)是false,算是一個(gè)優(yōu)化,避免2個(gè)觸發(fā)更新
? ? if (target === toRaw(receiver)) {
? ? ? if (!hadKey) {
? ? ? ? //觸發(fā)add類型依賴更新
? ? ? ? trigger(target, TriggerOpTypes.ADD, key, value)
? ? ? } else if (hasChanged(value, oldValue)) {
? ? ? ? //觸發(fā)set類型依賴更新
? ? ? ? trigger(target, TriggerOpTypes.SET, key, value, oldValue)
? ? ? }
? ? }
? ? return result
? }
}

(2).源碼流程分析

當(dāng)設(shè)置時(shí),首先對舊值是Ref類型對象做了個(gè)特殊處理,如果滿足條件,則走Ref對象的set方法邏輯觸發(fā)依賴更新。

否則根據(jù)是否存在key值,判斷是新增屬性,還是修改屬性,觸發(fā)不同類型的依賴更新。

之所以要區(qū)分依賴類型,是因?yàn)槟承傩詴?huì)連帶別的屬性更改,比如數(shù)組直接設(shè)置下標(biāo),會(huì)導(dǎo)致length的更改,這個(gè)時(shí)候需要收集length為鍵值的依賴,以便連帶更新依賴的length屬性的地方。

4. 其余行為攔截操作

(1).關(guān)鍵源碼

//源碼位置: /packages/reactivity/src/baseHandlers.ts
/**
?* delete操作符時(shí)觸發(fā)
?* @param target 目標(biāo)對象
?* @param key 鍵值
?* @returns?
?*/
function deleteProperty(target: object, key: string | symbol): boolean {
? const hadKey = hasOwn(target, key)
? const oldValue = (target as any)[key]
? const result = Reflect.deleteProperty(target, key)
? if (result && hadKey) {
? ? //觸發(fā)依賴更新
? ? trigger(target, TriggerOpTypes.DELETE, key, undefined, oldValue)
? }
? return result
}
/**
?* in 操作符時(shí)觸發(fā)
?* @param target 目標(biāo)對象
?* @param key 鍵值
?* @returns?
?*/
function has(target: object, key: string | symbol): boolean {
? const result = Reflect.has(target, key)
? if (!isSymbol(key) || !builtInSymbols.has(key)) {
? ?? ?//收集依賴
? ? track(target, TrackOpTypes.HAS, key)
? }
? return result
}
/**
?* Object.keys()等類似方法時(shí)調(diào)用
?* @param target 目標(biāo)對象
?* @returns?
?*/
function ownKeys(target: object): (string | symbol)[] {
? //收集依賴
? track(target, TrackOpTypes.ITERATE, isArray(target) ? 'length' : ITERATE_KEY)
? return Reflect.ownKeys(target)
}

(2).源碼流程分析

上述源碼其實(shí)就是在對一些特殊操作符或者特定API時(shí)的特殊處理,本質(zhì)還是收集依賴和觸發(fā)依賴更新,沒什么好講的。

四、Ref對象

1. 思考一個(gè)問題

為什么存在了Reactive代理對象后,已經(jīng)可以進(jìn)行依賴收集和依賴更新了,還要設(shè)計(jì)一個(gè)Ref類型。

測試一:針對以下測試代碼,Ref對象值的改變正確觸發(fā)了更新

?? ?//源碼位置 /packages/reactivity/__test__/ref.spec.ts
? ? const a = ref(1)
? ? let dummy
? ? let calls = 0
? ? effect(() => {
? ? ? calls++
? ? ? dummy = a.value;
? ? })
? ? a.value = 2;
? ? //此時(shí)dummy = 2,a對象值的改變觸發(fā)了依賴更新

測試二:修改以上代碼,更新失敗

? ? const a = 1
? ? let dummy
? ? let calls = 0
? ? effect(() => {
? ? ? calls++
? ? ? dummy = a;
? ? })
? ? a= 2;
? ? //此時(shí)dummy = 1,a的改變沒有觸發(fā)依賴更新

上述2個(gè)示例很明顯的表明出了,對于非響應(yīng)式對象的改變,不會(huì)觸發(fā)依賴更新。Reactive是通過代理實(shí)現(xiàn)的,代理只支持對象,不支持非對象的基礎(chǔ)類型。所以需要設(shè)計(jì)一個(gè)Ref類型來包裝這些類型數(shù)據(jù),以便擁有響應(yīng)式狀態(tài)

2. 簡要說明

既然設(shè)計(jì)了Ref來支持非對象屬性,那么也一定需要兼容對象屬性。內(nèi)部其實(shí)很簡單,如果是對象,則直接轉(zhuǎn)為Reactive代理對象。

3. 關(guān)鍵源碼

class RefImpl<T> {
? private _value: T
? private _rawValue: T
? public dep?: Dep = undefined
? public readonly __v_isRef = true
? constructor(value: T, public readonly _shallow: boolean) {
? ? //原始數(shù)據(jù)
? ? this._rawValue = _shallow ? value : toRaw(value)
? ? //外部訪問到的數(shù)據(jù),轉(zhuǎn)換為響應(yīng)式
? ? this._value = _shallow ? value : toReactive(value)
? }
? get value() {
? ? //跟蹤依賴
? ? trackRefValue(this)
? ? return this._value
? }
? set value(newVal) {
? ? newVal = this._shallow ? newVal : toRaw(newVal)
? ? if (hasChanged(newVal, this._rawValue)) {
? ? ? //如果原始數(shù)據(jù)之間的比較不一樣,則賦值
? ? ? this._rawValue = newVal
? ? ? //把新值轉(zhuǎn)換為響應(yīng)式對象
? ? ? this._value = this._shallow ? newVal : toReactive(newVal)
? ? ? //觸發(fā)依賴
? ? ? triggerRefValue(this, newVal)
? ? }
? }
}
//轉(zhuǎn)換響應(yīng)式對象方法
export const toReactive = <T extends unknown>(value: T): T =>
? isObject(value) ? reactive(value) : value
type CustomRefFactory<T> = (
? track: () => void,
? trigger: () => void
) => {
? get: () => T
? set: (value: T) => void
}
//收集依賴
export function trackRefValue(ref: RefBase<any>) {
? //是否可以收集
? if (isTracking()) {
? ? //獲取原始數(shù)據(jù)
? ? ref = toRaw(ref)
? ? if (!ref.dep) {
? ? ? //如果不存在依賴,就創(chuàng)建一個(gè)依賴對象
? ? ? ref.dep = createDep()
? ? }
? ? //收集依賴
? ? if (__DEV__) {
? ? ? trackEffects(ref.dep, {
? ? ? ? target: ref,
? ? ? ? type: TrackOpTypes.GET,
? ? ? ? key: 'value'
? ? ? })
? ? } else {
? ? ? trackEffects(ref.dep)
? ? }
? }
}
//觸發(fā)依賴更新
export function triggerRefValue(ref: RefBase<any>, newVal?: any) {
? ref = toRaw(ref)
? if (ref.dep) {
? ? if (__DEV__) {
? ? ? triggerEffects(ref.dep, {
? ? ? ? target: ref,
? ? ? ? type: TriggerOpTypes.SET,
? ? ? ? key: 'value',
? ? ? ? newValue: newVal
? ? ? })
? ? } else {
? ? ? triggerEffects(ref.dep)
? ? }
? }
}
/**
?* 自定義響應(yīng)式對象
?*/
class CustomRefImpl<T> {
? public dep?: Dep = undefined
? private readonly _get: ReturnType<CustomRefFactory<T>>['get']
? private readonly _set: ReturnType<CustomRefFactory<T>>['set']
? public readonly __v_isRef = true
? constructor(factory: CustomRefFactory<T>) {
? ? const { get, set } = factory(
? ? ? () => trackRefValue(this),
? ? ? () => triggerRefValue(this)
? ? )
? ? this._get = get
? ? this._set = set
? }
? get value() {
? ? return this._get()
? }
? set value(newVal) {
? ? this._set(newVal)
? }
}

四. 源碼解析

Ref對象實(shí)際是代理的簡化版,針對value設(shè)置了一個(gè)getter,setter讀取器。

這個(gè)讀取器可以對讀寫操作進(jìn)行攔截,因此可以進(jìn)行依賴的收集和更新。

同時(shí)又巧妙了對reactive做了一層封裝,假如傳入的是一個(gè)多層嵌套的復(fù)雜對象,最終是類似ref.value.a其實(shí)操作的已經(jīng)是reactive代理對象上的屬性,已經(jīng)和ref無關(guān)了。對于CustomRefImpl類型,其實(shí)核心和RefImpl是一樣的,更加精簡,只不過將Get方法和Set方法交給程序員自己去實(shí)現(xiàn)了。

只需要在這個(gè)Get方法里面調(diào)用track方法進(jìn)行依賴收集和在Set方法里面調(diào)用依賴更新即可。

示例代碼如下:

? ? let value = 1
? ? const custom = customRef((track, trigger) => ({
? ? ? get() {
? ? ? ? track()
? ? ? ? return value
? ? ? },
? ? ? set(newValue: number) {
? ? ? ? value = newValue
? ? ? ? trigger()
? ? ? }
? ? }))
? ? let dummy
? ? effect(() => {
? ? ? dummy = custom.value?
? ? })
? ? custom.value = 2
? ? //此時(shí)dummy = 2;

五、總結(jié)

1. 收集依賴和觸發(fā)依賴的本質(zhì)

export const enum TrackOpTypes {
? GET = 'get',
? HAS = 'has',
? ITERATE = 'iterate'
}
export const enum TriggerOpTypes {
? SET = 'set',
? ADD = 'add',
? DELETE = 'delete',
? CLEAR = 'clear'
}

以上時(shí)源碼中定義的收集依賴的和觸發(fā)依賴的類型。其實(shí)也就是當(dāng)涉及讀操作時(shí)收集依賴,當(dāng)設(shè)計(jì)寫操作時(shí)觸發(fā)依賴更新。

2. 響應(yīng)式對象本質(zhì)是對數(shù)據(jù)進(jìn)行了包裝,攔截了讀寫操作。

3. 上述篇幅并未講到集合類型代理的處理,原理其實(shí)一樣,有興趣的可以自行翻閱源碼。

4. 本篇幅只講到收集依賴和觸發(fā)依賴的時(shí)機(jī),并未講到如何收集和如何觸發(fā)。

這些僅為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • vue項(xiàng)目中vue-i18n和element-ui國際化開發(fā)實(shí)現(xiàn)過程

    vue項(xiàng)目中vue-i18n和element-ui國際化開發(fā)實(shí)現(xiàn)過程

    這篇文章主要介紹了vue項(xiàng)目中vue-i18n和element-ui國際化開發(fā)實(shí)現(xiàn)過程,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2018-04-04
  • Vue指令之 v-cloak、v-text、v-html實(shí)例詳解

    Vue指令之 v-cloak、v-text、v-html實(shí)例詳解

    當(dāng)用戶頻繁刷新頁面或網(wǎng)速慢時(shí),頁面未完成 Vue.js 的加載時(shí),導(dǎo)致 Vue 來不及渲染,這就會(huì)導(dǎo)致在瀏覽器中直接暴露插值(表達(dá)式),這篇文章主要介紹了Vue指令 v-cloak、v-text、v-html,需要的朋友可以參考下
    2019-08-08
  • 淺談VUE項(xiàng)目打包后運(yùn)行頁面一片白問題

    淺談VUE項(xiàng)目打包后運(yùn)行頁面一片白問題

    本文主要介紹了淺談VUE項(xiàng)目打包后運(yùn)行頁面一片白問題,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2023-01-01
  • 使用Vant完成通知欄Notify的提示操作

    使用Vant完成通知欄Notify的提示操作

    這篇文章主要介紹了使用Vant完成通知欄Notify的提示操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-11-11
  • vue 導(dǎo)航內(nèi)容設(shè)置選中狀態(tài)樣式的例子

    vue 導(dǎo)航內(nèi)容設(shè)置選中狀態(tài)樣式的例子

    今天小編就為大家分享一篇vue 導(dǎo)航內(nèi)容設(shè)置選中狀態(tài)樣式的例子,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-11-11
  • Vue唯一可以更改vuex實(shí)例中state數(shù)據(jù)狀態(tài)的屬性對象Mutation的講解

    Vue唯一可以更改vuex實(shí)例中state數(shù)據(jù)狀態(tài)的屬性對象Mutation的講解

    今天小編就為大家分享一篇關(guān)于Vue唯一可以更改vuex實(shí)例中state數(shù)據(jù)狀態(tài)的屬性對象,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • vue 實(shí)現(xiàn)websocket發(fā)送消息并實(shí)時(shí)接收消息

    vue 實(shí)現(xiàn)websocket發(fā)送消息并實(shí)時(shí)接收消息

    這篇文章主要介紹了vue 實(shí)現(xiàn)websocket發(fā)送消息并實(shí)時(shí)接收消息,項(xiàng)目結(jié)合vue腳手架和websocket來搭建,本文給大家分享實(shí)例代碼,需要的朋友可以參考下
    2019-12-12
  • vue 過濾器和自定義指令的使用

    vue 過濾器和自定義指令的使用

    本文主要介紹Vue.js中過濾器和自定義指令相關(guān)的知識點(diǎn),包括過濾器的定義方式,和使用方法,以及自定義指令的概念和注冊方式。
    2021-05-05
  • Vue.js基礎(chǔ)知識匯總

    Vue.js基礎(chǔ)知識匯總

    Vue.js 專注于 MVVM 模型的 ViewModel 層。它通過雙向數(shù)據(jù)綁定把 View 層和 Model 層連接了起來。Vue.js和其他庫相比是一個(gè)小而美的庫,作者的主要目的是通過一個(gè)盡量簡單的 API 產(chǎn)生可反映的數(shù)據(jù)綁定和可組合的視圖組件,感覺作者的思路非常清晰。
    2016-04-04
  • 使用vue+element?ui實(shí)現(xiàn)走馬燈切換預(yù)覽表格數(shù)據(jù)

    使用vue+element?ui實(shí)現(xiàn)走馬燈切換預(yù)覽表格數(shù)據(jù)

    這次做項(xiàng)目的時(shí)候遇到需要切換預(yù)覽表格數(shù)據(jù)的需求,所以下面這篇文章主要給大家介紹了關(guān)于使用vue+element?ui實(shí)現(xiàn)走馬燈切換預(yù)覽表格數(shù)據(jù)的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-08-08

最新評論

镇巴县| 江津市| 分宜县| 宜城市| 静乐县| 临潭县| 加查县| 中卫市| 澄城县| 铁岭市| 兴安县| 乳源| 阳江市| 孝昌县| 南川市| 星座| 甘南县| 道孚县| 汉中市| 邳州市| 尚义县| 东阳市| 旌德县| 邹平县| 叶城县| 黄浦区| 恩平市| 诸城市| 闵行区| 翁源县| 西华县| 抚松县| 三台县| 荣成市| 肥乡县| 波密县| 淮阳县| 迁安市| 田阳县| 固镇县| 河津市|