国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Vue2.0 的響應(yīng)式原理 私

這篇具有很好參考價值的文章主要介紹了Vue2.0 的響應(yīng)式原理 私。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

使用的Object.defineProperty()重新定義對象,給data的每個屬性都添加了getter和setter方法。這時候會為對象的每個屬性創(chuàng)建一個Dep實例? (依賴)。Dep實例可以訂閱和通知相關(guān)的Watcher實例。,? 這一步叫? 數(shù)據(jù)劫持? 或者 依賴收集

在數(shù)據(jù)發(fā)生更新后調(diào)用 set 時會通知發(fā)布者 notify 通知對應(yīng)的訂閱者做出數(shù)據(jù)更新,同時將新的數(shù)據(jù)根性到視圖上顯示。 這一步叫 派發(fā)更新

同時,為了解決對象屬性添加和刪除的問題,Vue提供了全局的Vue.set和Vue.delete方法,以及實例的vm.$set和vm.$delete方法。

解釋:

  1. 在創(chuàng)建 Observer 實例的同時還會創(chuàng)建 Dep 實例,用于保存依賴項。因此每個數(shù)據(jù)都有 Observer 的實例,每個 Observer 實例中又都有一個 Dep 的實例。
  2. 當(dāng) Vue 解析到當(dāng)解析到模板字符串 {{ }} 時中數(shù)據(jù)時,就會去創(chuàng)建 Watcher 實例,在 constructor 時會調(diào)用自身的 get 方法,該方法不僅將當(dāng)前的 Watcher 實例賦值給了 Dep.target(表示此時處于依賴收集階段),還讓這個新實例去讀取一下 {{ }} 中的數(shù)據(jù),一旦讀取,就會觸發(fā)這個數(shù)據(jù)的 getter 方法。因為此時正在進(jìn)行收集依賴,Dep.target 一定是為 true 的,于是順利地把當(dāng)前的這個 Watcher 實例記錄到了 dep 中的 subs 數(shù)組里。再然后將 Dep.target 的值重新賦值為 null,表示退出依賴收集階段

總結(jié):

在Vue2中,響應(yīng)式原理是通過使用Object.defineProperty方法來實現(xiàn)的。當(dāng)一個對象被傳入Vue的observe函數(shù)中時,Vue會為對象的每個屬性創(chuàng)建一個Dep實例。Dep實例可以訂閱和通知相關(guān)的Watcher實例。

當(dāng)一個屬性被訪問時,Watcher實例會將自己添加到該屬性的Dep實例的訂閱列表中。當(dāng)該屬性的值發(fā)生變化時,Dep實例會遍歷訂閱列表,通知所有相關(guān)的Watcher實例進(jìn)行更新。

然而,Vue無法檢測到對象屬性的添加和刪除。為了解決這個問題,Vue提供了全局的Vue.set方法或?qū)嵗膙m.$set方法來添加屬性,使用Vue.delete方法或?qū)嵗膙m.$delete方法來刪除屬性。對于數(shù)組的變動,Vue無法檢測到利用索引設(shè)置數(shù)組,但可以使用Vue.set方法或?qū)嵗膙m.$set方法。此外,Vue也無法檢測直接修改數(shù)組長度,但可以使用splice方法來實現(xiàn)。

總結(jié)起來,Vue2的響應(yīng)式原理通過使用Object.defineProperty方法來實現(xiàn)屬性的劫持和偵聽,同時使用Dep和Watcher實例來建立屬性和依賴之間的關(guān)系,并進(jìn)行更新通知。同時,為了解決對象屬性添加和刪除的問題,Vue提供了全局的Vue.set和Vue.delete方法,以及實例的vm.$set和vm.$delete方法。

原理:

通過數(shù)據(jù)劫持 defineProperty + 發(fā)布訂閱者模式,當(dāng) vue 實例初始化后 observer 會針對實例中的 data 中的每一個屬性進(jìn)行劫持并通過 defineProperty() 設(shè)置值后在 get() 中向發(fā)布者添加該屬性的訂閱者,

使用的Object.defineProperty()重新定義對象,給data的每個屬性都添加了getter和setter方法。
在get的時候會調(diào)用dep.depend;?

如果是數(shù)組,則調(diào)用dependArray(對數(shù)組里的每個元素進(jìn)行遞歸調(diào)用dep.depend);
在set的時候會先判斷數(shù)據(jù)是否更新,未更新不做操作,更新則observe(),且dep.notify()

1 在initState()方法里會對組件的props, methods, data,computed, watch等進(jìn)行編譯初始化=>

2 initData()會先獲取組件內(nèi)部的data數(shù)據(jù),然后判斷data里的數(shù)據(jù)和props,或者和methods里的名稱重復(fù),則拋出錯誤提示,然后就會去監(jiān)聽data,執(zhí)行observe方法=>

3? ?Observer()? =>? ?defineReactive,?dependArray =>??defineProperty()? ?=>???Observer()? ? 遞歸

Vue2.0 的響應(yīng)式原理 私,Vue3.0X,vue.js,javascript,前端

Vue2.0 的響應(yīng)式原理 私,Vue3.0X,vue.js,javascript,前端

使用的Object.defineProperty()重新定義對象,給data的每個屬性都添加了getter和setter方法。

在get的時候會調(diào)用dep.depend;如果是數(shù)組,則調(diào)用dependArray(對數(shù)組里的每個元素進(jìn)行遞歸調(diào)用dep.depend);
在set的時候會先判斷數(shù)據(jù)是否更新,未更新不做操作,更新則observe(),且dep.notify()

源碼解析:

不同版本的vue的源碼實現(xiàn)可能會有些不同,我這里的版本是2.6.14

Vue2.0 的響應(yīng)式原理 私,Vue3.0X,vue.js,javascript,前端

首先我們要知道定義響應(yīng)式是在哪個時間段實現(xiàn)的,從源碼中我們可以看到,是在執(zhí)行beforeCreate生命周期函數(shù)之后,Created之前。也就是說,這也就是我們在beforeCreate無法拿到Data中的數(shù)據(jù)的原因。

Vue2.0 的響應(yīng)式原理 私,Vue3.0X,vue.js,javascript,前端

首先我們要知道定義響應(yīng)式是在哪個時間段實現(xiàn)的,從源碼中我們可以看到,是在執(zhí)行beforeCreate生命周期函數(shù)之后,Created之前。也就是說,這也就是我們在beforeCreate無法拿到Data中的數(shù)據(jù)的原因。

第一步:?在initState方法里會對組件的props, methods, data,computed, watch等進(jìn)行編譯初始化

export function initState (vm: Component) {
  vm._watchers = []
  const opts = vm.$options
  if (opts.props) initProps(vm, opts.props)
  if (opts.methods) initMethods(vm, opts.methods)
  if (opts.data) {
    initData(vm)
  } else {
    observe(vm._data = {}, true /* asRootData */)
  }
  if (opts.computed) initComputed(vm, opts.computed)
  if (opts.watch && opts.watch !== nativeWatch) {
    initWatch(vm, opts.watch)
  }
}

第二步:?initData()會先獲取組件內(nèi)部的data數(shù)據(jù),然后判斷data里的數(shù)據(jù)和props,或者和methods里的名稱重復(fù),則拋出錯誤提示,然后就會去監(jiān)聽data,執(zhí)行observe方法

function initData (vm: Component) {
  let data = vm.$options.data
  data = vm._data = typeof data === 'function'
    ? getData(data, vm)
    : data || {}
  if (!isPlainObject(data)) {
    data = {}
    process.env.NODE_ENV !== 'production' && warn(
      'data functions should return an object:\n' +
      'https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function',
      vm
    )
  }
  // proxy data on instance
  const keys = Object.keys(data)
  const props = vm.$options.props
  const methods = vm.$options.methods
  let i = keys.length
  while (i--) {
    const key = keys[i]
    if (process.env.NODE_ENV !== 'production') {
      if (methods && hasOwn(methods, key)) {
        warn(
          `Method "${key}" has already been defined as a data property.`,
          vm
        )
      }
    }
    if (props && hasOwn(props, key)) {
      process.env.NODE_ENV !== 'production' && warn(
        `The data property "${key}" is already declared as a prop. ` +
        `Use prop default value instead.`,
        vm
      )
    } else if (!isReserved(key)) {
      proxy(vm, `_data`, key) //將data上的屬性代理到vm實例上。
    }
  }
  // observe data
  observe(data, true /* asRootData */)
}

第三步:在這里observe()中,會先判斷data中的數(shù)據(jù)是否是對象,然后判斷data中是否已經(jīng)有了ob(也就是Observer實例)最后判斷是否滿足監(jiān)聽的條件。才會創(chuàng)建一個新的Observer對象

/**
 * Attempt to create an observer instance for a value,
 * returns the new observer if successfully observed,
 * or the existing observer if the value already has one.
 */
export function observe (value: any, asRootData: ?boolean): Observer | void {
  if (!isObject(value) || value instanceof VNode) {
    return
  }
  let ob: Observer | void
  if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {
    ob = value.__ob__
  } else if (
    shouldObserve &&
    !isServerRendering() &&
    (Array.isArray(value) || isPlainObject(value)) &&
    Object.isExtensible(value) &&
    !value._isVue
  ) {
    ob = new Observer(value)
  }
  if (asRootData && ob) {
    ob.vmCount++
  }
  return ob
}


第四步:

每一個observer實例都有自己的一個Dep, 在new Oberver后,會判斷傳入的value也就是vm.data是不是數(shù)組。

如果是數(shù)組,會采用函數(shù)劫持的方法重寫數(shù)組的方法,先判斷數(shù)組支不支持原型鏈,支持就將當(dāng)前數(shù)組的原型指向已經(jīng)重寫了Array里的7種方法的arrayMethod,當(dāng)數(shù)組里的方法被調(diào)用時,Dep會notify通知視圖更新,然后執(zhí)行ObserveArray方法,如果數(shù)組里的數(shù)據(jù)是對象,則繼續(xù)回調(diào)observe();
如果是對象,則調(diào)用this.walk(),在walk()中,會遍歷data的屬性執(zhí)行defineReactive()定義響應(yīng)式
?

/**
 * Observer class that is attached to each observed
 * object. Once attached, the observer converts the target
 * object's property keys into getter/setters that
 * collect dependencies and dispatch updates.
 */
export class Observer {
  value: any;
  dep: Dep;
  vmCount: number; // number of vms that have this object as root $data

  constructor (value: any) {
    this.value = value
    this.dep = new Dep()
    this.vmCount = 0
    def(value, '__ob__', this)
    if (Array.isArray(value)) {
      if (hasProto) {
        protoAugment(value, arrayMethods)
      } else {
        copyAugment(value, arrayMethods, arrayKeys)
      }
      this.observeArray(value)
    } else {
      this.walk(value)
    }
  }

  /**
   * Walk through all properties and convert them into
   * getter/setters. This method should only be called when
   * value type is Object.
   */
  walk (obj: Object) {
    const keys = Object.keys(obj)
    for (let i = 0; i < keys.length; i++) {
      defineReactive(obj, keys[i])
    }
  }

  /**
   * Observe a list of Array items.
   */
  observeArray (items: Array<any>) {
    for (let i = 0, l = items.length; i < l; i++) {
      observe(items[i])
    }
  }
}

第五層:

使用的Object.defineProperty()重新定義對象,給data的每個屬性都添加了getter和setter方法。
在get的時候會調(diào)用dep.depend;如果是數(shù)組,則調(diào)用dependArray(對數(shù)組里的每個元素進(jìn)行遞歸調(diào)用dep.depend);
在set的時候會先判斷數(shù)據(jù)是否更新,未更新不做操作,更新則observe(),且dep.notify()
以下是Dep的代碼,我們可以將Dep看作一個觀察者。
?

/**
 * Define a reactive property on an Object.
 */
export function defineReactive (
  obj: Object,
  key: string,
  val: any,
  customSetter?: ?Function,
  shallow?: boolean
) {
  const dep = new Dep()

  const property = Object.getOwnPropertyDescriptor(obj, key)
  if (property && property.configurable === false) {
    return
  }

  // cater for pre-defined getter/setters
  const getter = property && property.get
  const setter = property && property.set
  if ((!getter || setter) && arguments.length === 2) {
    val = obj[key]
  }

  let childOb = !shallow && observe(val)
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function reactiveGetter () {
      const value = getter ? getter.call(obj) : val
      if (Dep.target) {
        dep.depend()
        if (childOb) {
          childOb.dep.depend()
          if (Array.isArray(value)) {
            dependArray(value)
          }
        }
      }
      return value
    },
    set: function reactiveSetter (newVal) {
      const value = getter ? getter.call(obj) : val
      /* eslint-disable no-self-compare */
      if (newVal === value || (newVal !== newVal && value !== value)) {
        return
      }
      /* eslint-enable no-self-compare */
      if (process.env.NODE_ENV !== 'production' && customSetter) {
        customSetter()
      }
      // #7981: for accessor properties without setter
      if (getter && !setter) return
      if (setter) {
        setter.call(obj, newVal)
      } else {
        val = newVal
      }
      childOb = !shallow && observe(newVal)
      dep.notify()
    }
  })
}

第六層?解釋? ?第五層:

depend方法就是將當(dāng)前dep的實例添加到對應(yīng)的Watcher中,
notify方法就是通知所有收集的Wacher進(jìn)行更新,subs[i].update()

/* @flow */

import type Watcher from './watcher'
import { remove } from '../util/index'
import config from '../config'

let uid = 0

/**
 * A dep is an observable that can have multiple
 * directives subscribing to it.
 */
export default class Dep {
  static target: ?Watcher;
  id: number;
  subs: Array<Watcher>;

  constructor () {
    this.id = uid++
    this.subs = [] //存儲所有訂閱的Watcher
  }

  addSub (sub: Watcher) {
    this.subs.push(sub)
  }

  removeSub (sub: Watcher) {
    remove(this.subs, sub)
  }

  depend () {
    if (Dep.target) {
      Dep.target.addDep(this)
    }
  }

  notify () {
    // stabilize the subscriber list first
    const subs = this.subs.slice()
    if (process.env.NODE_ENV !== 'production' && !config.async) {
      // subs aren't sorted in scheduler if not running async
      // we need to sort them now to make sure they fire in correct
      // order
      subs.sort((a, b) => a.id - b.id)
    }
    for (let i = 0, l = subs.length; i < l; i++) {
      subs[i].update()
    }
  }
}

// The current target watcher being evaluated.
// This is globally unique because only one watcher
// can be evaluated at a time.
Dep.target = null
const targetStack = []

export function pushTarget (target: ?Watcher) {
  targetStack.push(target)
  Dep.target = target
}

export function popTarget () {
  targetStack.pop()
  Dep.target = targetStack[targetStack.length - 1]
}

第七層.Watcher.js

當(dāng)解析到模板字符串 {{ }} 時,會默認(rèn)去 new Watcher 實例。

/**
 * 每一次的 new Watcher 都是獨立的,因此構(gòu)造器接收的三個參數(shù),雖然名字一樣但確實不同的數(shù)據(jù),就像是 vm.$watch() 接收的參數(shù)一樣,
 * @param {*} target 需要監(jiān)視的對象,當(dāng)做修改時,他就是
 * @param {*} expression 這個對象中的某個屬性,它是一個表達(dá)式 比如 obj.a.b.c
 * @param {*} callback 回調(diào)函數(shù),需要執(zhí)行的操作 
 */

import Dep from "./Dep";

// 這個 uid 用于對每一個的 Watcher 實例添加唯一的 id
var uid = 0

// 在這里哪一步算是調(diào)用了 get 方法???????,解析到模板的時候

export default class Watcher {
    constructor(target, expression, callback) {
        console.log('我是 Watcher 構(gòu)造器');
        this.id = uid++;

        // 模板字符串中的整個表達(dá)式
        this.target = target;

        // 通過拆分表達(dá)式(對象中的對象...),獲得需要 Watch 的那個數(shù)據(jù)。比如傳入的是 a.b.c.d 我們需要監(jiān)視屬性 d,就需要拆分
        this.getter = parsePath(expression)  // 有兩種方法供使用 parsePath 會返回一個函數(shù);如果用 reduce 方法,那么 getter 就會是一個具體的值,此時一定要修改下邊的 get 方法!!!

        this.callback = callback

        // 調(diào)用該方法,進(jìn)入依賴收集階段
        this.value = this.get()
    }
    // 當(dāng)更新 dep 中的依賴項時,會調(diào)用每一個 Watcher 實例身上的 update 方法
    update() {
        console.log('我是Watcher實例身上的update方法');
        this.run()
    }

    // 進(jìn)入依賴收集階段,讓全局的 Dep.target 設(shè)置為 Watcher 本身
    get(){
        // Webpack 在打包的時候 Dep 是全局唯一的,不管多少個JS 文件在用 dep 的時候,都是這一個文件
        // 因此執(zhí)行到這里
        console.log(this);  // Watcher 實例
        Dep.target = this;   
        // debugger;
        const obj = this.target;

        var value;

        // 防止找不到,用try catch一下,只要能找,就一直找
        try {
            value = this.getter(obj)    // 獲取需要監(jiān)視的那個值。這里因為constructor 的時候 this.get() 返回的是一個函數(shù)
        } finally {
            Dep.target = null   // 清空全局 target 的指向,同時也表示退出依賴收集階段
        }
        return value        
    }

    // 其實可以直接 getAndInvoke,但是 Vue 源碼時這樣寫的
    run(){
        this.getAndInvoke(this.callback)
    }

    //
    getAndInvoke(callback){
        // 獲取到修改后的新值   舊值是 this.value
        const value = this.get()
        if(value !== this.value || typeof value == 'object'){
            const oldValue = this.value;
            this.value = value;
            callback.call(this.target, value, oldValue)
        }
    }
}





// 拆分表達(dá)式:
// 方法一:將 str 用 . 分割成數(shù)組 segments,然后循環(huán)數(shù)組,一層一層去讀取數(shù)據(jù),最后拿到的 obj 就是 str 中想要讀的數(shù)據(jù)
// 假設(shè) let o = {a:{b:{c:{d:55}}}},我想要取得 d 的值,經(jīng)過拆分后的 segments 數(shù)組的值為 ['a', 'b', 'c', 'd']
// 第一次循環(huán)后 obj = {b:{c:{d:55}}}, 第二次 obj = {c:{d:55}}, 第三次 obj = {d:55}, 第四次 obj = 55
function parsePath(str) {
    let segments = str.split(".");
    return function (obj) {
        for (let key of segments) {
            if (!obj) return;   // 當(dāng)沒有傳入 obj 時,直接 return
            obj = obj[key];
        }
        return obj;
    };
}
// 方法二 用 reduce 方法實現(xiàn)
// function parsePathReduce(str) {
//     let segments = str.split(".");
//     let result = segments.reduce((total, item) => {
//         total = total[item]
//         return total
//     }, str)
//     return result
// }

前置知識:


首先要了解三個最重要的對象:
Observer 對象:將 Vue 中的數(shù)據(jù)對象在初始化過程中轉(zhuǎn)換為 Observer 對象。
Watcher 對象:將模板和 Observer 對象結(jié)合在一起生成 Watcher 實例,Watcher 是訂閱者中的訂閱者。
Dep對象:Watcher 對象和 Observer 對象之間紐帶,每一個 Observe r都有一個 Dep 實例,用來存儲訂閱者 Watcher。
?

過程:

  1. 在生命周期的 initState 方法中將 data,prop,method,computed,watch等所有數(shù)據(jù)全部進(jìn)行數(shù)據(jù)劫持,將所有數(shù)據(jù)變?yōu)?Observer 實例,并且每個數(shù)據(jù)身上還有 Dep 實例。
  2. 然后在 initRender 方法中也就是模板編譯過程,遇到的指令和數(shù)據(jù)綁定都會生成 Watcher 實例,并且把這個實例存入對應(yīng)數(shù)據(jù)的 Dep 實例中的 subs 數(shù)組里。這樣每一個數(shù)據(jù)的 Dep 實例里就都存放了依賴關(guān)系。
  3. 當(dāng)數(shù)據(jù)變化時,數(shù)據(jù)的 setter 方法被調(diào)用,觸發(fā) dep.notify 方法,就會通知 Dep 實例依賴列表,執(zhí)行 update 方法通知 Watcher,Watcher 會執(zhí)行 run 方法去更新視圖。
  4. 更新視圖的過程,我猜是 Vue 接下來要進(jìn)行 diff 算法,對比新舊模板,然后重新渲染頁面。
    ?

缺陷:只能夠監(jiān)聽初始化實例中的 data 數(shù)據(jù),動態(tài)添加值不能響應(yīng),要使用對應(yīng)的 Vue.set()。

  • Vue 是無法檢測到對象屬性的添加和刪除,但是可以使用全局 Vue.set 方法(或 vm.$set 實例方法)。
  • Vue 無法檢測利用索引設(shè)置數(shù)組,但是可以使用全局 Vue.set方法(或 vm.$set 實例方法)。
  • 無法檢測直接修改數(shù)組長度,但是可以使用 splice。

vue2.0重寫數(shù)組

		// 數(shù)組方法重寫
        let oldArrayPrototy = Array.prototype
        // 使用Object.create 將數(shù)組原型上的方法放到newArrayPrototy.prototype上
        let newArrayPrototy = Object.create(arrayFn)
        // 需要重寫的數(shù)組方法列表
        let method = [
            'push',
            'pop',
            'shift',
            'unshift',
            'reverse',
            'sort',
            'splice'
        ]
        method.forEach((item) => {
        	//newArrayPrototy[item] 就是 arr.某一個方法
            newArrayPrototy[item] = function (...args) {
                // 關(guān)鍵部分
                let result = oldArrayPrototy[item].call(this, ...args)
                // 對傳進(jìn)來的數(shù)據(jù)做一些處理
                let insterted
                switch (item) {
                    case 'push':
                    case 'unshift':
                        insterted = args
                    case 'splice':
                        insterted = args.slice(2)
                    default:
                        break
                }
                return result
            }
        })

Vue2.0響應(yīng)式原理源碼解析_瑪已的博客-CSDN博客

Vue2的響應(yīng)式原理_vue2響應(yīng)式原理_高等數(shù)學(xué)真簡單的博客-CSDN博客文章來源地址http://www.zghlxwxcb.cn/news/detail-681132.html

到了這里,關(guān)于Vue2.0 的響應(yīng)式原理 私的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • Web前端 ---- 【Vue3】Proxy響應(yīng)式原理

    Web前端 ---- 【Vue3】Proxy響應(yīng)式原理

    目錄 前言 安裝Vue3項目 安裝 Proxy 語法格式 從本文開始進(jìn)入vue3的學(xué)習(xí)。本文介紹vue3中的響應(yīng)式原理,相較于vue2中通過object.defineProperty(vue2中的響應(yīng)式)來實現(xiàn)響應(yīng)式,vue3中換成了Proxy來進(jìn)行實現(xiàn)。 相較于vue2通過vue-cli腳手架來創(chuàng)建項目,這里更推薦使用create-vue來創(chuàng)建vue3的

    2024年01月16日
    瀏覽(64)
  • 【前端vue升級】vue2+js+elementUI升級為vue3+ts+elementUI plus

    【前端vue升級】vue2+js+elementUI升級為vue3+ts+elementUI plus

    gogo code 是一個基于 AST (源代碼的抽象語法結(jié)構(gòu)樹狀表現(xiàn)形式)的 JavaScript/Typescript/HTML 代碼轉(zhuǎn)換工具,可以用它來構(gòu)建一個代碼轉(zhuǎn)換程序來幫助自動化完成如框架升級、代碼重構(gòu)、多平臺轉(zhuǎn)換等工作。 當(dāng)前 GoGoCode 支持解析和操作如下類型的代碼: ○JavaScript(JSX) ○Typescript

    2024年02月12日
    瀏覽(31)
  • 前端2023最全面試題(javaScript、typeScript、vue2、vue3、html、css、uniapp、webpack、vite、react)

    答案:JavaScript中的閉包是一種函數(shù),它有權(quán)訪問其詞法環(huán)境的變量和其它函數(shù)。這意味著,即使其包含它的函數(shù)已經(jīng)執(zhí)行完畢,其詞法環(huán)境仍然存在,因此可以訪問其作用域內(nèi)的變量。 答案:回調(diào)函數(shù)是在某個特定事件之后執(zhí)行的函數(shù)。在JavaScript中,通常使用回調(diào)函數(shù)來處

    2024年02月06日
    瀏覽(35)
  • Vue2和vue3中雙向數(shù)據(jù)綁定的原理,ES6的Proxy對象代理和JavaScript的Object.defineProperty,使用詳細(xì)

    簡介: Object.defineProperty大家都知道,是vue2中雙向數(shù)據(jù)綁定的原理,它 是 JavaScript 中一個強(qiáng)大且常用的方法,用于定義對象屬性,允許我們精確地控制屬性的行為,包括讀取、寫入和刪除等操作; 而Proxy是vue3中雙向數(shù)據(jù)綁定的原理,是ES6中一種用于創(chuàng)建代理對象的特殊對象,

    2024年02月15日
    瀏覽(46)
  • 持續(xù)不斷更新中... 自己整理的一些前端知識點以及前端面試題,包括vue2,vue3,js,ts,css,微信小程序等

    答: 在普通的前端項目工程中,在script標(biāo)簽中增加setup即可使用api 使用setup()鉤子函數(shù) 答: 不要在計算屬性中進(jìn)行異步請求或者更改DOM 不要直接修改computed的值 區(qū)別: 計算屬性值基于其響應(yīng)式依賴被緩存,意思就是只要他之前的依賴不發(fā)生變化,那么調(diào)用他只會返回之前緩

    2024年02月11日
    瀏覽(58)
  • Vue2.0 的響應(yīng)式原理 私

    Vue2.0 的響應(yīng)式原理 私

    使用的Object.defineProperty()重新定義對象,給data的每個屬性都添加了getter和setter方法。這時候會為對象的每個屬性創(chuàng)建一個Dep實例? (依賴)。Dep實例可以訂閱和通知相關(guān)的Watcher實例。,? 這一步叫? 數(shù)據(jù)劫持? 或者 依賴收集 在數(shù)據(jù)發(fā)生更新后調(diào)用 set 時會通知發(fā)布者 notify

    2024年02月11日
    瀏覽(19)
  • vue2響應(yīng)式原理----發(fā)布訂閱模式

    vue2響應(yīng)式原理----發(fā)布訂閱模式

    很多人感覺vue2的響應(yīng)式其實用到了觀察者+發(fā)布訂閱。我們先來看一下簡單的發(fā)布訂閱的代碼: 從上面中發(fā)現(xiàn)一個重要的點,發(fā)布者和訂閱者是根據(jù)key值來區(qū)分的,然后通過消息中心來中轉(zhuǎn)的,他們家是是實現(xiàn)不知道對方是誰。 而觀察者模式中觀察者是一開始就知道自己觀察

    2024年04月14日
    瀏覽(18)
  • 202 vue2的響應(yīng)式原理 通俗易懂!

    Object.defineProperty + 依賴追蹤 。 在Vue實例化過程中,會 遞歸 地將 每個數(shù)據(jù)對象 的 屬性 轉(zhuǎn)換為 getter/setter ,并維護(hù)一個 依賴收集器(Dep) 。 每個屬性 都有一個關(guān)聯(lián)的 watcher ,當(dāng) 數(shù)據(jù)發(fā)生 變化時 , watcher 會 被通知 并 更新視圖 。 Vue 2.x 實現(xiàn)響應(yīng)式數(shù)據(jù): vue實例化 時,會

    2024年02月06日
    瀏覽(30)
  • 【前端面經(jīng)】Vue3和Vue2的區(qū)別

    Vue是一種非常流行的JavaScript框架,因其易用性和靈活性在開發(fā)人員中備受歡迎。Vue2是Vue框架的上一個重要版本,于2016年發(fā)布。但是,Vue3是最新版本的Vue框架,于2020年正式發(fā)布并帶來了一些重大變化。本文將探討Vue3和Vue2之間的主要區(qū)別。 Vue3的一個顯著優(yōu)勢是其更小的代碼

    2024年02月02日
    瀏覽(18)
  • vue3響應(yīng)式原理

    vue3響應(yīng)式原理

    Vue 3 中的響應(yīng)式原理是通過使用 ES6 的 Proxy 對象來實現(xiàn)的。在 Vue 3 中,每個組件都有一個響應(yīng)式代理對象,當(dāng)組件中的數(shù)據(jù)發(fā)生變化時,代理對象會立即響應(yīng)并更新視圖。 具體來說,當(dāng)一個組件被創(chuàng)建時,Vue 會為組件的 data 對象創(chuàng)建一個響應(yīng)式代理對象。這個代理對象可以

    2024年02月15日
    瀏覽(37)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包