3. 手写组合API

shallowReactive 与 reactive

  1. const reactiveHandler = {
  2. get (target, key) {
  3. if (key==='_is_reactive') return true
  4. return Reflect.get(target, key)
  5. },
  6. set (target, key, value) {
  7. const result = Reflect.set(target, key, value)
  8. console.log('数据已更新, 去更新界面')
  9. return result
  10. },
  11. deleteProperty (target, key) {
  12. const result = Reflect.deleteProperty(target, key)
  13. console.log('数据已删除, 去更新界面')
  14. return result
  15. },
  16. }
  17. /*
  18. 自定义shallowReactive
  19. */
  20. function shallowReactive(obj) {
  21. return new Proxy(obj, reactiveHandler)
  22. }
  23. /*
  24. 自定义reactive
  25. */
  26. function reactive (target) {
  27. if (target && typeof target==='object') {
  28. if (target instanceof Array) { // 数组
  29. target.forEach((item, index) => {
  30. target[index] = reactive(item)
  31. })
  32. } else { // 对象
  33. Object.keys(target).forEach(key => {
  34. target[key] = reactive(target[key])
  35. })
  36. }
  37. const proxy = new Proxy(target, reactiveHandler)
  38. return proxy
  39. }
  40. return target
  41. }
  42. /* 测试自定义shallowReactive */
  43. const proxy = shallowReactive({
  44. a: {
  45. b: 3
  46. }
  47. })
  48. proxy.a = {b: 4} // 劫持到了
  49. proxy.a.b = 5 // 没有劫持到
  50. /* 测试自定义reactive */
  51. const obj = {
  52. a: 'abc',
  53. b: [{x: 1}],
  54. c: {x: [11]},
  55. }
  56. const proxy = reactive(obj)
  57. console.log(proxy)
  58. proxy.b[0].x += 1
  59. proxy.c.x[0] += 1

shallowRef 与 ref

  1. /*
  2. 自定义shallowRef
  3. */
  4. function shallowRef(target) {
  5. const result = {
  6. _value: target, // 用来保存数据的内部属性
  7. _is_ref: true, // 用来标识是ref对象
  8. get value () {
  9. return this._value
  10. },
  11. set value (val) {
  12. this._value = val
  13. console.log('set value 数据已更新, 去更新界面')
  14. }
  15. }
  16. return result
  17. }
  18. /*
  19. 自定义ref
  20. */
  21. function ref(target) {
  22. if (target && typeof target==='object') {
  23. target = reactive(target)
  24. }
  25. const result = {
  26. _value: target, // 用来保存数据的内部属性
  27. _is_ref: true, // 用来标识是ref对象
  28. get value () {
  29. return this._value
  30. },
  31. set value (val) {
  32. this._value = val
  33. console.log('set value 数据已更新, 去更新界面')
  34. }
  35. }
  36. return result
  37. }
  38. /* 测试自定义shallowRef */
  39. const ref3 = shallowRef({
  40. a: 'abc',
  41. })
  42. ref3.value = 'xxx'
  43. ref3.value.a = 'yyy'
  44. /* 测试自定义ref */
  45. const ref1 = ref(0)
  46. const ref2 = ref({
  47. a: 'abc',
  48. b: [{x: 1}],
  49. c: {x: [11]},
  50. })
  51. ref1.value++
  52. ref2.value.b[0].x++
  53. console.log(ref1, ref2)

shallowReadonly 与 readonly

  1. const readonlyHandler = {
  2. get (target, key) {
  3. if (key==='_is_readonly') return true
  4. return Reflect.get(target, key)
  5. },
  6. set () {
  7. console.warn('只读的, 不能修改')
  8. return true
  9. },
  10. deleteProperty () {
  11. console.warn('只读的, 不能删除')
  12. return true
  13. },
  14. }
  15. /*
  16. 自定义shallowReadonly
  17. */
  18. function shallowReadonly(obj) {
  19. return new Proxy(obj, readonlyHandler)
  20. }
  21. /*
  22. 自定义readonly
  23. */
  24. function readonly(target) {
  25. if (target && typeof target==='object') {
  26. if (target instanceof Array) { // 数组
  27. target.forEach((item, index) => {
  28. target[index] = readonly(item)
  29. })
  30. } else { // 对象
  31. Object.keys(target).forEach(key => {
  32. target[key] = readonly(target[key])
  33. })
  34. }
  35. const proxy = new Proxy(target, readonlyHandler)
  36. return proxy
  37. }
  38. return target
  39. }
  40. /* 测试自定义readonly */
  41. /* 测试自定义shallowReadonly */
  42. const objReadOnly = readonly({
  43. a: {
  44. b: 1
  45. }
  46. })
  47. const objReadOnly2 = shallowReadonly({
  48. a: {
  49. b: 1
  50. }
  51. })
  52. objReadOnly.a = 1
  53. objReadOnly.a.b = 2
  54. objReadOnly2.a = 1
  55. objReadOnly2.a.b = 2

isRef, isReactive 与 isReadonly

  1. /*
  2. 判断是否是ref对象
  3. */
  4. function isRef(obj) {
  5. return obj && obj._is_ref
  6. }
  7. /*
  8. 判断是否是reactive对象
  9. */
  10. function isReactive(obj) {
  11. return obj && obj._is_reactive
  12. }
  13. /*
  14. 判断是否是readonly对象
  15. */
  16. function isReadonly(obj) {
  17. return obj && obj._is_readonly
  18. }
  19. /*
  20. 是否是reactive或readonly产生的代理对象
  21. */
  22. function isProxy (obj) {
  23. return isReactive(obj) || isReadonly(obj)
  24. }
  25. /* 测试判断函数 */
  26. console.log(isReactive(reactive({})))
  27. console.log(isRef(ref({})))
  28. console.log(isReadonly(readonly({})))
  29. console.log(isProxy(reactive({})))
  30. console.log(isProxy(readonly({})))