前端组件化之组件是什么

组件是什么

未引入Virtual DOM前,请看以下代码

// _ => lodash
const compiler = _.template("<h1><%= title %></h1>");

const HelloComponent = (data) => {
  return compiler(data);
};

const init= (data) => {
  const App = document.getElementById("app");
  App.innerHTML = HelloComponent({ title: "Hello!" });
  setTimeout(() => {
      App.innerHTML = HelloComponent({ title: "Hello Again!" });
  }, 2000);
};

init();

从上面代码可以看出,组件是一个输入为模板所需数据和输出为模板字符串的函数,

模板 + 数据 => 模板字符串

引入Virtual DOM后, 请看以下代码

const { h, init } = snabbdom;
// init 方法用来创建 patch 函数
const patch = init([]);

const HelloComponent = (props) => {
  const vnode = h("h1", props.title);
  return vnode;
};
const load = () => {
  const App = document.getElementById("app");
  // 组件的产出是 VNode
  const prevVnode = HelloComponent({ title: "Hello!" });
  // 将 VNode 渲染成真实 DOM,增加了前后节点的对比后,才会渲染内容
  patch(App, prevVnode);

  // 两秒之后重渲染
  setTimeout(() => {
    // 数据变更,产出新的 VNode
    const nextVnode = HelloComponent({ title: "Hello Again!" });
    // 通过对比新旧 VNode,高效的渲染真实 DOM
    patch(prevVnode, nextVnode);
  }, 2000);
};
load()

从上面代码可以看出,组件是一个输入为数据和输出为* Virtual DOM*的函数

模板 + 数据 => Virtual DOM

让人不禁会问,为什么要引入Virtual DOM?这样只需对产出的vnode格式做统一规定,即可通过patch挂载函数实现在不同端的渲染了。

组件的挂载

请看如下代码

// MyComponent 组件
class MyComponent {
  render(data) {
    // render 函数产出 VNode
    return {
      tag: "div",
      text: data.text
    };
  }
}

// VNode
const componentVnode = {
  tag: MyComponent
};

const App = document.getElementById("app")

function render(container, vnode) {
  if (typeof vnode.tag === "string") {
    // html 标签
    mountElement(container,vnode);
  } else {
    // 组件
    mountComponent(container,vnode);
  }
}

function mountComponent(container,vnode) {
  // 创建组件实例
  const instance = new vnode.tag()
  instance.$vnode = instance.render({text: '组件div'})
  // 挂载
  mountElement(container, instance.$vnode);
}

function mountElement(container, vnode) {
  // 创建元素
  const el = document.createElement(vnode.tag);
  el.innerText = vnode.text
  // 将元素添加到容器
  container.appendChild(el);
}

render(App, componentVnode);
render(App, {tag: 'div', text: '普通div'});

先是声名了一个组件类MyComponent ,利用单例模式生成新的组件,然后即可挂载

参考原文链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值