通过Object.defineProperty来实现响应式

    1. const obj = {
    2. name: 'zxt',
    3. age: '18',
    4. sex: 'nan',
    5. son: {
    6. name: 'zzz',
    7. sex: 'nan'
    8. },
    9. arr: [1, 2, 3],
    10. }
    11. /**
    12. * 监听对象每一项的读取与写入
    13. * @param {*} obj 对象
    14. * @param {*} prop 属性
    15. * @param {*} value 值
    16. */
    17. function defineReactive(obj, prop, value) {
    18. if (typeof value === "object") {
    19. forIn(obj[prop]);
    20. }
    21. Object.defineProperty(obj, prop, {
    22. get() {
    23. console.log('读');
    24. return value;
    25. },
    26. set(nowValue) {
    27. console.log('写');
    28. value = nowValue;
    29. render();
    30. }
    31. })
    32. }
    33. /**
    34. * 迭代对象的每一个属性
    35. * @param {*} obj
    36. */
    37. function forIn(obj) {
    38. /**
    39. * 当为数组是,为其绑定数组异变方法
    40. */
    41. if (Array.isArray(obj)) {
    42. obj.__proto__ = arrMethods;
    43. return;
    44. }
    45. if (typeof obj == 'object') {
    46. for (const key in obj) {
    47. defineReactive(obj, key, obj[key]);
    48. };
    49. }
    50. }
    51. function render() {
    52. console.log('页面渲染啦');
    53. }
    54. /**
    55. * 数据的变异方法
    56. */
    57. let arrProto = Array.prototype;
    58. let arrMethods = Object.create(arrProto);
    59. ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'].forEach((ele) => {
    60. arrMethods[ele] = function () {
    61. arrProto[ele].call(this, ...arguments)
    62. render();
    63. }
    64. })
    65. /**
    66. * $set
    67. */
    68. function $set(who, revise, value) {
    69. if (Array.isArray(who)) {
    70. who.splice(revise, 1, value);
    71. return value;
    72. }
    73. defineReactive(who,revise,value)
    74. return value;
    75. // render();
    76. }
    77. /**
    78. * $delete
    79. */
    80. function $delete(obj ,target){
    81. if(Array.isArray(obj)){
    82. obj.splice(target,0);
    83. return;
    84. }
    85. delete obj[target] ;
    86. return;
    87. }
    88. forIn(obj);
    89. obj.son.name = 123;

    利用Object.defineProperty实现响应式的劣势

    1. 天生就需要进行递归
    2. 监听不到数组不存在的索引的改变
    3. 监听不到数组长度的改变
    4. 监听不到对象的增删