第一步完成深度观察

class Vue { constructor (options) { this.$el = options.el; this.$options = options;   this.$data = options.data; if (this.$el) { new Observer(this.$data)    }   }
}   class Observer {    constructor(data) { this.observe(data)  }   observe (obj) { if (obj && typeof obj === 'object') {  for (const key in obj) {    this.defineReactive(obj, key, obj[key]) }   }   }   defineReactive (obj, key, value) {  this.observe(value) Object.defineProperty(obj, key, {   get () {    return value    },  set: (newValue) => {    if (value !== newValue) { value = newValue   this.observe(newValue)  }   }   })  }
}

第二步将DOM放到内存中

class Vue {    constructor (options) { this.$el = options.el; this.$options = options;   this.$data = options.data; if (this.$el) { new Observer(this.$data)    new Compiler(this.$el, this)    }   }
}   class Compiler {    constructor (el, vm) {  this.vm = vm;  this.el = this.isElementNode(el) ? el : document.querySelector(el);    let fragment = this.nodeFragment(this.el); this.compile(fragment)  this.el.appendChild(fragment)   }   compile (node) {    console.log(node, '分析DOM节点')  }   nodeFragment (node) {   let fragment = document.createDocumentFragment()   let firstChild; while (firstChild = node.firstChild) { fragment.appendChild(firstChild)    }   return fragment }   isElementNode (node) {  return node.nodeType === 1;  }
}

第三步分析模板里面的内容

let CompileUtil = {   text (node, expr, vm) { let handler = this.updater['text']   let content = expr.replace(/\{\{(.+?)\}\}/, (...args) => {    return this.getValue(args[1], vm)   })  handler(node, content)  },  getValue(expr, vm) {    return expr.split('.').reduce((data, current) => {    return data[current]    }, vm.$data)    },  updater: {  text (node, value) {    node.textContent = value   }   }
}   class Compiler {    constructor (el, vm) {  this.vm = vm;  this.el = this.isElementNode(el) ? el : document.querySelector(el);    let fragment = this.nodeFragment(this.el); this.compile(fragment)  this.el.appendChild(fragment)   }   compile (node) {    let nodeList = node.childNodes;    Array.from(nodeList, child => { if (this.isElementNode(child)) {    this.compileElement(child)  this.compile(child) } else {    this.compileText(child) }   })  }   compileElement (node) { // 分析元素节点   }   compileText (node) {    // 分析文本节点   // 1. 小胡子语法里面要替换成我们想要的内容    let content = node.textContent;    if (/\{\{(.+?)\}\}/.test(content)) {   CompileUtil.text(node, content, this.vm)    }   }   nodeFragment (node) {   let fragment = document.createDocumentFragment()   let firstChild; while (firstChild = node.firstChild) { fragment.appendChild(firstChild)    }   return fragment }   isElementNode (node) {  return node.nodeType === 1;  }
}

第三步观察者模式进行绑定

class Dep {    constructor() { this.subs = [] }   addSub(watcher) {   this.subs.push(watcher) }   notify() {  this.subs.forEach(watcher => watcher.update())  }
}   class Watcher { constructor(vm, expr, cb) { this.vm = vm;  this.expr = expr;  this.cb = cb;  this.oldVale = this.get()  }   get () {    Dep.target = this; // 取值操作 let value = CompileUtil.getValue(this.expr, this.vm)   Dep.target = null; return value    }   update () { let newValue = CompileUtil.getValue(this.expr, this.vm)    if (newValue !== this.oldVale) {  // 当比较两个值不相等的情况下执行回调    this.cb(this.newValue)  }   }
}   class Vue { constructor(options) {  this.$el = options.el; this.$options = options;   this.$data = options.data; if (this.$el) { new Observer(this.$data)    new Compiler(this.$el, this)    }   }
}   class Observer {    constructor(data) { this.observe(data)  }   observe(obj) {  if (obj && typeof obj === 'object') {  for (const key in obj) {    this.defineReactive(obj, key, obj[key]) }   }   }   defineReactive(obj, key, value) {   this.observe(value) let dep = new Dep()    Object.defineProperty(obj, key, {   get() { Dep.target && dep.addSub(Dep.target)    return value    },  set: (newValue) => {    if (value !== newValue) { value = newValue   this.observe(newValue)  dep.notify()    }   }   })  }
}   let CompileUtil = {    text(node, expr, vm) {  let handler = this.updater['text']   let content = expr.replace(/\{\{(.+?)\}\}/, (...args) => {    new Watcher(vm, args[1], () => {    // 处理函数 handler(node, this.getContentValue(vm, expr))   })  return this.getValue(args[1], vm)   })  handler(node, content)  },  getContentValue (vm, expr) {    return expr.replace(/\{\{(.+?)\}\}/, (...args) => {    return this.getValue(args[1], vm)   })  },  getValue(expr, vm) {    return expr.split('.').reduce((data, current) => {    return data[current]    }, vm.$data)    },  updater: {  text(node, value) { node.textContent = value   }   }
}   class Compiler {    constructor(el, vm) {   this.vm = vm;  this.el = this.isElementNode(el) ? el : document.querySelector(el);    let fragment = this.nodeFragment(this.el); this.compile(fragment)  this.el.appendChild(fragment)   }   compile(node) { let nodeList = node.childNodes;    Array.from(nodeList, child => { if (this.isElementNode(child)) {    this.compileElement(child)  this.compile(child) } else {    this.compileText(child) }   })  }   compileElement(node) {  // 分析元素节点   }   compileText(node) { // 分析文本节点   // 1. 小胡子语法里面要替换成我们想要的内容    let content = node.textContent;    if (/\{\{(.+?)\}\}/.test(content)) {   CompileUtil.text(node, content, this.vm)    }   }   nodeFragment(node) {    let fragment = document.createDocumentFragment()   let firstChild; while (firstChild = node.firstChild) { fragment.appendChild(firstChild)    }   return fragment }   isElementNode(node) {   return node.nodeType === 1;  }
}

分分钟写出Vue原理相关推荐

  1. 狗屁不通文章生成器登顶GitHub热榜,分分钟写出万字形式主义大作

    前言 GitHub 被誉为全球最大的同性交友网站,--,陪伴我们已经走过 10+ 年时间,它托管了大量的软件代码,同时也承载了程序员无尽的欢乐. 上周给大家分享了一篇10个让你笑的合不拢嘴的Githu ...

  2. 100个标题模板,让你分分钟写出10万+爆文!

    什么样的标题才能吸引读者,这是每一位编辑都必须面对的问题. 网上有各种各样的理论教程,也是很多老司机的经验之谈. 但是真的把这些技巧融汇贯通,需要慢慢的积累经验. 而对于大多数新上路的自媒体运营者来说 ...

  3. 他写出了 Vue,却做不对这十道 Vue 笔试题

    有十道关于 Vue 的选择题,在群里引出了一众社区知名人士竞折腰,最后钓出了 Evan You 本人亲自挑战-- 然后他自己也做错了(其中的某两道). 鲁迅会做错鲁迅文选的阅读理解?有截图为证: 所以 ...

  4. [vue] 写出你知道的表单修饰符和事件修饰符

    [vue] 写出你知道的表单修饰符和事件修饰符 事件修饰符.stop .prevent .capture .self .once .passive 表单修饰符.number .lazy .trim 个 ...

  5. [vue] 写出多种定义组件模板的方法

    [vue] 写出多种定义组件模板的方法 1.字符串 2.模板字面量 3.<script type="x-template"></script> 4.文件组件 ...

  6. 【视频联动】编译原理:写出布尔表达式A or (B and not(C or D)) 的四元式序列。说明:按照控制语句中的布尔表达式翻译

    编译原理:写出布尔表达式A or (B and not(C or D))  的四元式序列.说明:按照控制语句中的布尔表达式翻译 这里是总结的知识点.如果有问题可以下方留言提问,视频已经放到Bilibi ...

  7. 基于vue与element-ui写出的关于搜索框搜索关键字,下方关键字高亮的demo

    这是一个基于vue与element-ui写出的关于搜索框搜索关键字,下方关键字高亮的demo 希望对大家有所帮助 效果如下: <template><!-- 测试 -->< ...

  8. 编译原理习题两则(龙书,写出语言的正则定义)

    3.3.5.3 注释,即 /* 和 */ 之间的串,且串中没有不在双引号(")中的 */. 注:假设双引号是匹配的. 思路:从空串开始写,写出整体框架后,通过分类讨论的方法不断进行扩充构造. ...

  9. 【编译原理】写出下列文法对应定义的是什么语言?

    1.文法G(Z):Z->aZb|ab定义的是什么样的语言? 答:L(G)={ an bn | n≥1} 2.写出文法G(Z):Z->AB A->aBb|ab B-cB|b 定义的是什 ...

最新文章

  1. 控件的呈现方法(Rendering)的内核
  2. 单v100 GPU,4小时搜索到一个鲁棒的网络结构
  3. FckEditor-未能映射路径/UserFiles/image/
  4. [Mysql]过大sql文件导入过慢问题解决
  5. “假一赔十”的4k 120Hz电视能买吗?研究完我服了,水是真的深
  6. Java虚拟机学习(1):体系结构 内存模型
  7. malloc 初始化_你真的了解 NSObject 对象的初始化吗?
  8. 批量调整word表格根据窗口调整内容
  9. sringboot security基本用法
  10. [2017.11.11特辑]以一个光棍节表白案例浅谈ECMAScript6模块化的使用方法
  11. python log函数_Python log10() 函数
  12. stl标准模板库_C ++标准模板库(STL)中的array :: fill()
  13. MySQL命令窗口出现中文乱码的解决方法
  14. rn webview加载本地静态html,React Native - Webview 加载本地文件
  15. Spring使用Cache、整合Ehcache
  16. LVM 逻辑卷管理精讲
  17. C# 使用 NPOI操作excle文件(读取与新建重写)
  18. 简单粗暴日文键盘布局改为其他语言键盘布局
  19. Sinew探索金融衍生品领域,增强金融市场流动性
  20. 亚马逊云科技的IoT+AI能力覆盖边缘与云,在云端提供稳定的云服务支持

热门文章

  1. 终于有人对语音技术来了次彻头彻尾的批判!
  2. 15 年经验专家解读 IIoT 的挑战及应对思路!
  3. 世界500强的科技从业者,依旧逃不出买房难的宿命
  4. 5G 套餐最快本月开售;谷歌被指骗取人脸数据;Calibre 4.0 发布 | 极客头条
  5. 阿里开源物联网操作系统 AliOS Things 3.0 发布,集成平头哥 AI 芯片架构!
  6. 今日七夕!不取标题,只想娶你
  7. 知乎披露会员业务未来布局,融合社区内容深耕垂直领域
  8. AI 补代码神器诞生,百度网盘克星诞生,Google 取消中国搜索引擎项目! | 开发者周刊...
  9. 2019 年备受争议的 Facebook 能否走出去年的阴影?| 畅言
  10. 程序员惨遭辞退竟只因提了些代码修改意见?