1. 程式人生 > 實用技巧 >手寫Vue3.0 API(B站李南江)

手寫Vue3.0 API(B站李南江)

一、Vue3.0響應式

  1.在Vue2.x中是通過defineProperty來實現響應式資料的

  2.在Vue3.x中是通過Proxy來實現響應式資料的

  

let obj = { name: 'lng', age: 18 }     // 原始物件

let state = new Proxy(obj, {    // 攔截原始物件進行操作
  get (obj, key) {
    console.log(obj, key)  // { name: 'lng', age: 18 }  "name"
    return obj[key]
  },
  set (obj, key, value) {
    obj[key] 
= value console.log(obj, key, value) // {name: "jz", age: 18} "name" jz // return true // 更新UI } }) console.log(state.name) // get--lng state.name = 'jz' // set

二、shallowReactive和shallowRef

function shallowRef(val) {  // shallowRef本質還是shallowReactive
    return shallowReactive({ value: val })
}
  
function shallowReactive(obj) { return new Proxy(obj, { get(obj, key) { return obj[key] }, set(obj, key, value) { obj[key] = value console.log('更新UI介面') return true } }) } let obj = { a: 'a', gf: { b:
'b', f: { c: 'c', s: { d: 'd' } } } } /* let state = shallowReactive(obj) // state.a = 1 // 更新UI介面 state.gf.b = 2 state.gf.f.c = 3 state.gf.f.s.d = 4 */ let state = shallowRef(obj) // state.value.a = 1 // state.value.gf.b = 2 // state.value.gf.f.c = 3 // state.value.gf.f.s.d = 4 state.value = { a: '1', gf: { b: '2', f: { c: '3', s: { d: '4' } } } } console.info(state.value)

三、reactive和ref

  function ref(val) {   
    return reactive({value: val})   
  }
  
  function reactive(obj) {
    if(typeof obj === 'object') {
      if (obj instanceof Array) {
        // 如果是一個數據,那麼取出陣列中的每一個元素
        // 判斷每一個元素是否又是一個物件,如果又是一個物件,那麼也需要包裝成 Proxy
        obj.forEach((item, index) => {
          if(typeof item === 'object') {
            obj[index] = reactive(item)
          }
        })
      } else {
        // 如果是一個物件,那麼去除物件屬性的取值
        // 判斷物件屬性的取值是否又是一個物件,如果又是一個物件,那麼也需要包裝成 Proxy
        for (let key in  obj) {
          let item = obj[key]
          if (typeof item === 'object') {
            obj[key] = reactive(item)
          }
        }
      }
    } else {
      console.warn(`${JSON.stringify(obj)} is not object`)
    }
    return new Proxy(obj, {
      get(obj, key) {
        return obj[key]
      },
      set(obj, key, value) {
        obj[key] = value
        console.log('更新UI介面')
        return true
      }
    })
  }
  
  let obj = {
    a: 'a',
    gf: {
      b: 'b',
      f: {
        c: 'c',
        s: {
          d: 'd'
        }
      }
    }
  }
  
  // let state = reactive(obj)
  // state.a = 1 // 更新UI介面
  // state.gf.b = 2 // 更新UI介面
  // state.gf.f.c = 3 // 更新UI介面
  // state.gf.f.s.d = 4 // 更新UI介面
  
  let arr = [{id: 1, name: '魯班'}, {id: 2, name: '虞姬'}]
  let state = reactive(arr)
  state[0].name = '張三' // 更新UI介面
  state[0].age = 666 // 更新UI介面
  state[1].id = 3 // 更新UI介面

四、readonly和shallowReadonly

  function readonly(obj) {  // readonly遞迴只讀
    if(typeof obj === 'object') {
      if (obj instanceof Array) {
        // 如果是一個數據,那麼取出陣列中的每一個元素
        // 判斷每一個元素是否又是一個物件,如果又是一個物件,那麼也需要包裝成 Proxy
        obj.forEach((item, index) => {
          if(typeof item === 'object') {
            obj[index] = readonly(item)
          }
        })
      } else {
        // 如果是一個物件,那麼去除物件屬性的取值
        // 判斷物件屬性的取值是否又是一個物件,如果又是一個物件,那麼也需要包裝成 Proxy
        for (let key in  obj) {
          let item = obj[key]
          if (typeof item === 'object') {
            obj[key] = readonly(item)
          }
        }
      }
    } else {
      console.warn(`${JSON.stringify(obj)} is not object`)
    }
    return new Proxy(obj, {
      get(obj, key) {
        return obj[key]
      },
      set(obj, key, value) {
        console.warn(`${key}是隻讀的,不能賦值`)
        return true
      }
    })
  }
  
  function shallowReadonly(obj) {   // shallowReadonly只讀,但不是遞迴只讀
  
    return new Proxy(obj, {
      get(obj, key) {
        return obj[key]
      },
      set(obj, key, value) {
        console.warn(`${key}是隻讀的,不能賦值`)
      }
    })
  }
  
  let obj = {
    a: 'a',
    gf: {
      b: 'b',
      f: {
        c: 'c',
        s: {
          d: 'd'
        }
      }
    }
  }
  
  // let state = shallowReadonly(obj)
  // state.a = 1 // a是隻讀的,不能賦值
  // state.gf.b = 2 // 空行
  
  let state1 = readonly(obj)
  state1.a = 1 // a是隻讀的,不能賦值
  state1.gf.b = 2 // b是隻讀的,不能賦值

reactive, ref