逻辑 -> 数据 <—>视图

    1. /**
    2. * 1. 数据 -> 响应式数据 Object.defineProperty Proxy
    3. * 2. input -> input/keyup -> 事件处理函数的绑定 -> 改变数据
    4. * 3. 相关的DOM & 数据 => 绑定在一起
    5. * 操作数据的某个属性 -> 对应DOM就改变
    6. * {
    7. * 'name': [span节点]
    8. * }
    9. *
    10. *
    11. *
    12. */
    13. const reg_var = /\{\{(.*?)\}\}/;
    14. // eslint-disable-next-line
    15. class MVVM {
    16. constructor(el, data){
    17. this.el = document.querySelector(el);
    18. // this._data = data;
    19. this.data = data;
    20. this.domPool = {};//dom池
    21. this.init();
    22. }
    23. init(){
    24. this.initData();
    25. this.initDom();
    26. }
    27. initData(){
    28. const _this = this;
    29. // this.data = {};
    30. // for(const key in this._data){
    31. // if(typeof key === 'object'){
    32. // //递归
    33. // }
    34. // Object.defineProperty(this.data, key, {
    35. // get(){
    36. // console.log("获取数据: ", key, _this._data[key]);
    37. // return _this._data[key];
    38. // },
    39. // set(newValue){
    40. // if(newValue===_this._data[key]){
    41. // return;
    42. // }
    43. // console.log("设置数据: ", key, _this._data[key]);
    44. // _this.domPool[key].innerText = newValue;
    45. // _this._data[key] = newValue;
    46. // }
    47. // });
    48. // }
    49. //Proxy写法
    50. this.data = new Proxy(this.data, {
    51. get(target, key){
    52. return Reflect.get(target, key);
    53. },
    54. set(target, key, value){
    55. _this.domPool[key].innerText = value;
    56. return Reflect.set(target, key, value);
    57. }
    58. })
    59. }
    60. initDom(){
    61. this.bindDom(this.el);//这应该先执行
    62. console.log("看看dom池子:",this.domPool);
    63. this.bindInput(this.el);
    64. }
    65. //数据与DOM节点绑定--解析出{{name}}绑定到对应节点上
    66. bindDom(el){
    67. if(!el){
    68. return;
    69. }
    70. const childNodes = el.childNodes;
    71. // console.log("el.childNodes: ", childNodes);
    72. childNodes.forEach(item => {
    73. //如果是文本节点
    74. if(item.nodeType===3){
    75. const _value = item.nodeValue;
    76. // console.log(_value);
    77. if(_value.trim().length){
    78. let _isValid = reg_var.test(_value);//捕获组&懒惰模式
    79. if(_isValid){
    80. const _key = _value.match(reg_var)[1].trim();
    81. console.log("匹配到的属性:", _key);
    82. this.domPool[_key] = item.parentNode;//其实应该是个set集合,这里简化为1v1了
    83. //再设置DOM
    84. item.parentNode.innerText = this.data[_key] || undefined;
    85. }
    86. }
    87. }
    88. item.childNodes && this.bindDom(item);//递归
    89. });
    90. }
    91. //input--绑定事件处理函数
    92. bindInput(el){
    93. if(!el){
    94. return;
    95. }
    96. const _allInputs = el.querySelectorAll('input');
    97. _allInputs.forEach(input=>{
    98. const _vModel = input.getAttribute('v-model');
    99. if(_vModel){
    100. input.addEventListener('keyup', this.handleInput.bind(this, _vModel, input));
    101. }
    102. })
    103. }
    104. handleInput(key, input){
    105. const _value = input.value;
    106. this.data[key] = _value;
    107. }
    108. setData(key, value){
    109. this.data[key] = value;
    110. }
    111. }