123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. //-----------------数据挟持Observer--------
  2. //-----------------数据渲染Compile---------
  3. //-----------------数据订阅Pubsub----------
  4. class Observer{
  5. constructor(data, sub) {
  6. this.sub = sub
  7. this.data = data
  8. for(let key in data) {
  9. this._listen(data, key, data[key])
  10. }
  11. }
  12. _listen(obj, key, val) {
  13. this.dataProxy = new Proxy(obj, {
  14. get: (t, name) => {
  15. console.log("get===>", name, ":", t[name])
  16. return t[name]
  17. },
  18. set: (t, name, newVal) => {
  19. console.log("set===>", name, ":", newVal)
  20. t[name] = newVal
  21. this.sub.public(name, newVal)
  22. return true
  23. },
  24. })
  25. }
  26. }
  27. class MyVue {
  28. constructor(options) {
  29. const {el, data} = options;
  30. this.el = document.querySelector(el)
  31. // 订阅者注册
  32. this.sub = new Pubsub()
  33. // 数据挟持
  34. const vm = new Observer(data, this.sub)
  35. this.vm = vm.dataProxy
  36. // 数据渲染
  37. this.compile = new Compile(this.el, this.vm, this.sub)
  38. this.flag = this.compile.createFlag()
  39. this.el.appendChild(this.flag)
  40. }
  41. }
  42. class Compile {
  43. constructor(el, vm, sub) {
  44. this.el = el
  45. this.vm = vm
  46. this.sub = sub
  47. }
  48. createFlag() {
  49. let flag = document.createDocumentFragment()
  50. let child;
  51. while(child = this.el.firstChild) {
  52. this.compile(child)
  53. flag.appendChild(child)
  54. }
  55. return flag
  56. }
  57. compile(node) {
  58. switch(node.nodeType){
  59. case 1: // element
  60. const reg = /\{\{(.*)\}\}/;
  61. if(reg.test(node.textContent)) {
  62. let name = RegExp.$1;
  63. node.textContent = this.vm[name]
  64. this.sub.subscribe(name, (newVal) => {
  65. node.textContent = newVal
  66. })
  67. }
  68. let attr = node.attributes
  69. if(attr.hasOwnProperty('x-model')){
  70. let name = attr['x-model'].nodeValue
  71. node.value = this.vm[name]
  72. const self = this
  73. node.addEventListener('input', (e) => {
  74. self.vm[name] = e.target.value
  75. })
  76. this.sub.subscribe(name, (newVal) => {
  77. if(node.value !== newVal)
  78. node.value = newVal
  79. })
  80. }
  81. break;
  82. case 3: // text
  83. break;
  84. default:
  85. console.log("no nodetype")
  86. }
  87. }
  88. }
  89. class Pubsub{
  90. constructor(){
  91. this.subs = {}
  92. }
  93. // 订阅者注册
  94. subscribe(name, func) {
  95. this.subs[name] = this.subs[name] ? this.subs[name] : []
  96. this.subs[name].push(func)
  97. }
  98. // 发布
  99. public(name, args) {
  100. console.log(this.subs[name])
  101. if(!this.subs[name]) return;
  102. this.subs[name].map(func => func(args))
  103. }
  104. }