zoukankan      html  css  js  c++  java
  • 手写Vue (1) 编译文本

    1. 当我们初始化数据后 就可以进行将数据进行挂载 

     首先先判断 配置是否有 el  如果有 el  再进行挂载

     if (vm.$options.el) {
        vm.$mount();
      }

    2.  $mount  这个方法中 我们首先要获取到   获取当前挂载的节点

    let vm = this;
      let el = vm.$options.el
      el = vm.$el = query(el)  // 获取当前挂载的节点

    3.  获取当前挂载的节点 有两种情况 

    el: '#app',ru
    el: document.getElementById('app;);

    所以我们要判断el 是否是一个字符串 如果是字符串 的话  通过  document.querySelector 获取元素 否则直接返回

    function query(el) {
      if (typeof el === 'string') {
        return document.querySelector(el);
      }
      return el
    }

    4. 添加   渲染watchder

    observe/watch.js   传入一系列参数 

    let id = 0;
    class Watcher {
      // watch 有唯一标识
      constructor(vm, exprOrfn, cb = () => { }, opts = {}) {
        // exprOrfn 表达式  cb 回调
        this.vm = vm;
        this.exprOrfn = exprOrfn;
        if (typeof exprOrfn == 'function') {
          // getter 就是  Watcher 传入的第2个函数
          this.getter = exprOrfn;
        }
        this.cb = cb;
        this.opts = opts;
        this.id = id++;
        this.get()
      }
      get() {
      }
    }
    export default Watcher;

    5. 在index.js  引入  watch.js 

    import Watcher from './observe/watch'
    Vue.prototype.$mount = function () {
      let vm = this;
      let el = vm.$options.el
      el = vm.$el = query(el)  // 获取当前挂载的节点
      let updateComponent = () => {
        vm.$update()
        // console.log('数据更新')
      }
      // 渲染watchder
      new Watcher(vm, updateComponent)
    }

    6.  updateComponent  是一个函数 里面有一个   $update 方法 

    在这个方法中主要做的操作 是 创建一个 文档碎片 循环的将 el 上挂载的节点依次 遍历 复制到文档碎片里面 

    Vue.prototype.$update = function () {
      let vm = this;
      let el = vm.$el
      console.log(el)// 拿到节点
      // 需要匹配{{}}
      let node = document.createDocumentFragment();
      let firstChild;
      while (firstChild = el.firstChild) {
        node.appendChild(firstChild)
      }
      // console.log(node)  // 获取到文档碎片
      el.appendChild(node)
    }
    let node = document.createDocumentFragment();  创建文档碎片
    循环添加到文档碎片里面
    while (firstChild = el.firstChild) {
        node.appendChild(firstChild)
     }

    7. 测试

    8. 获取到 node 节点后 我们需要进行 编译 

    compiler(node, vm)

    9.编译 的时候要判断 node  节点的类型 

    function compiler(node, vm) {
      let childNodes = node.childNodes;
      ([...childNodes]).forEach(child => {
        // 1  元素  3  文本
        if (child.nodeType == 1) {
          // console.log('2020')
          compiler(child, vm)  //编译孩子节点
        } else if (child.nodeType == 3) {
          // console.log('111')
          util.compilerText(child, vm)
        }
      });
    }

    如果是元素 编译 里面 的孩子节点 

    compiler(child, vm)  //编译孩子节点

    如果是文本  编写一个 方法 

    util.compilerText(child, vm)

    10.  compilerText 编译文本的方法 

      compilerText(node, vm) {  //编译文本
        // 匹配正则
        node.textContent = node.textContent.replace(defaultRe, function (...args) {
          console.log(args, 'test')
          return util.getValue(vm, args[1])
        })
      }
    defaultRe 代表 正则
      const defaultRe = /{{((?:.| ? )+?)}}/
     
    测试正则:
     "{{xxx}}".match(/{{((?:.|
    ?
    )+?)}}/);
     (2)["{{xxx}}", "xxx", index: 0, input: "{{xxx}}", groups: undefined]
    const util = {

    通过正则我们 可以拿到 {{ }} 里面的东西  再通过   util.getValue 获取值

     util.getValue 方法

      getValue(vm, expr) {
        console.log(vm, expr)
        let keys = expr.split('.');
        return keys.reduce((arr, current) => {
          arr = arr[current]  // vm.school.name
          return arr
        }, vm)
      },
    keys.reduce 是为了防止  vm.school.name 这种表述情况 
    reduce 可以将上传的结果 作为传入参数 

    const util = {
      getValue(vm, expr) {
        console.log(vm, expr)
        let keys = expr.split('.');
        return keys.reduce((arr, current) => {
          arr = arr[current]  // vm.school.name
          return arr
        }, vm)
      },
      compilerText(node, vm) {  //编译文本
        // 匹配正则
        node.textContent = node.textContent.replace(defaultRe, function (...args) {
          console.log(args, 'test')
          return util.getValue(vm, args[1])
        })
      }
    }

    码云 地址 :

    https://gitee.com/guangzhou110/vue_principle



     
  • 相关阅读:
    模块
    Queue(队列)
    Stack(栈)
    Vector(容器)
    位图像素的颜色
    大数处理之三(除法)
    大数处理之二(幂运算)
    浮点数(double)的优势
    大数处理之一(加法和乘法)
    Depth-First Search
  • 原文地址:https://www.cnblogs.com/guangzhou11/p/12670072.html
Copyright © 2011-2022 走看看