当前位置: 首页 > news >正文

盖州网站建设做毕业设计网站的问题与展望

盖州网站建设,做毕业设计网站的问题与展望,淘宝哪些做网站关键词排名的有用吗,百度seo关键词排名优化教程前言 前面我们实现了基本的数据更新到视图渲染的逻辑,但是这种方式(innerHTML)是极其低效的, 因此,我们相应引入 dom 和 diff 算法, 数据到视图的过程变为: state -> vdom -> dom vNode 层 所谓 vNode, 就是一个表示 dom 结构的轻量对象 {tag, props, children; }为…

前言

前面我们实现了基本的数据更新到视图渲染的逻辑,但是这种方式(innerHTML)是极其低效的, 因此,我们相应引入 dom 和 diff 算法, 数据到视图的过程变为:

state -> vdom -> dom

vNode 层

所谓 vNode, 就是一个表示 dom 结构的轻量对象

{tag, props, children;
}

为了方便创建, 引入创建一个创建节点的方法h

export function h(tag, props, children) {return {tag,props,children,};
}

我们需要修改 render 函数, 让其返回一个创建好的 vNode(vTree)

render(context) {return h('div',{id: 'id-1',class: 'class-1'},[h('p', null, String(context.value)), h('p', null, String(context.value))])},

接下来对返回的 vTree 挂载到真实的节点

let subTree = rootComponent.render(context);
mountElement(subTree, rootContainer);

mountElement 的实现逻辑

  1. 根据标签创建元素
  2. 更新属性
  3. 如果子节点为文本节点,直接创建, 若为数组,则递归创建
export function mountComponent(vnode, container) {const { tag, props, children } = vnode;// taglet ele = document.createElement(tag);// propsfor (const key in props) {if (Object.hasOwnProperty.call(props, key)) {const value = props[key];ele.setAttribute(key, value);}}/* children1. string2. object*/if (typeof children === "string") {const textNode = document.createTextNode(children);ele.appendChild(textNode);} else if (isArray(children)) {children.forEach((vnode) => {mountComponent(vnode, ele);});}container.appendChild(ele);
}function isArray(ele) {return typeof ele.sort === "function";
}

diff 算法

除了第一次挂载需要生成所有节点以外, 新的更新是在旧的基础上"缝缝补补", 这个差量更新的过程交给我们的 diff 算法

我们用一个变量isMounted来将挂载和更新两阶段分开

export default function createApp(rootComponent) {return {mount(rootContainer) {let context = rootComponent.setup();let isMounted = false;let oldSubTree;effectWatch(() => {if (!isMounted) {isMounted = true;let subTree = (oldSubTree = rootComponent.render(context));mountElement(subTree, rootContainer);} else {let newSubTree = rootComponent.render(context);diff(newSubTree, oldSubTree);oldSubTree = newSubTree;}});},};
}

接下来我们就可以处理diff的逻辑了, 需要分别对tag,props,children的变更做处理,

因为 diff 的郭恒要对真实的 dom 节点进行操作, 在 mounted 过程中将 dom 渲染完成后,我们需要将其挂载到对应的 vNode 上

export function mountElement(vNode, container) {// ...let ele = (vNode.el = document.createElement(tag));// ...
}
  1. tag 变化的处理 ,这里用到了原生的replaceWith操作方法
if (newTree.tag !== oldTree.tag) {oldTree.el.replaceWith(document.createElement(newTree.tag));
}
  1. props 节点的处理
newTree.el = oldTree.el;
// props, 对比两个对象, 各自遍历一遍,找出各自不同的地方
let { props: newProps } = newTree;
let { props: oldProps } = oldTree;
if (newProps && oldProps) {Object.keys(newProps).forEach((key) => {// 同时存在,意味着需要更新节点let newVal = newProps[key];if (Object.hasOwnProperty.call(oldProps, key)) {let oldVal = oldProps[key];if (newVal !== oldVal) {newTree.el.setAttribute(key, newVal);}} else {// 旧的不存在, 创建newTree.el.setAttribute(key, newVal);}});
}
// 移除已不存在的旧节点
if (oldProps) {Object.keys(oldProps).forEach((key) => {if (!Object.hasOwnProperty.call(newProps, key)) {newTree.el.removeAttribute(key);}});
}

当然, 为了演示, 这里的处理过程比较简单,

  1. children 的处理

chilren 的处理相对比较麻烦,为了简化, 目前根据 children 的类型区分

即: newChildren[string, array] * oldChildren[array, string] = 4 种情况

前三种比较简单

let { children: oldChildren } = oldTree;
let { children: newChildren } = newTree;
if (typeof newChildren === "string") {if (typeof oldChildren === "string") {if (newChildren !== oldChildren) {newTree.el.textContent = newChildren;}} else if (isArray(oldChildren)) {newTree.el.textContent = newChildren;}
} else if (isArray(newChildren)) {if (typeof oldChildren === "string") {newTree.el.textContent = ``;mountElement(newTree, newTree.el);} else if (Array.isArray(oldChildren)) {// ...}
}

下面分析两者都是数组的情况, 为了简化, 只对节点的长度作处理,不处理相同长度内的节点移位操作

// 暴力解法: 只对节点的长度作处理,不处理相同长度内的节点移位操作
const length = Math.min(newChildren.length, oldChildren.length);
// 更新相同长度的部分
for (var index = 0; index < length; index++) {let newTree = newChildren[index];let oldTree = oldChildren[index];diff(newTree, oldTree);
}
// 创建
if (newChildren.length > oldChildren.length) {for (let index = length; index < newChildren.length; index++) {const newVNode = newChildren[index];mountElement(newVNode, newTree.el);}
}
// 删除
if (oldChildren.length > newChildren.length) {for (let index = length; index < oldChildren.length; index++) {const vNode = oldChildren[index];vNode.el.remove(); // 节点移除自身}
}

本文首发于个人 Github前端开发笔记,由于笔者能力有限,文章难免有疏漏之处,欢迎指正

http://www.15wanjia.com/news/175944.html

相关文章:

  • 遵义网站建设公司价格想做个网站要多少钱
  • 运城网站制作备案的网站建设书是什么意思
  • 快速做网站公司报价我想在家办个小型加工厂
  • next.js做纯静态网站17素材网官网
  • 婚纱摄影网络公司网站源码做网站需要什么按钮
  • 中国建设银行龙卡信用卡网站湘潭网站建设网站
  • 企业网站必须备案吗网站建设哪些模板号
  • 互联网信息服务 网站备案百度搜索引擎收录
  • 网站照片加水印做网站用什么字体
  • 食品安全网站建设成全视频免费观看在线看黄
  • 晋城建设局网站装潢公司网站模板
  • 网站绑定别名好吗有哪些网站建设方案
  • 投票活动网站怎么做网站建设推广语
  • 网站建设报价单 文库网站备案后的标识
  • 免费网页制作软件手机版网站优化方案 site ww
  • 绵阳哪个网站做外卖做的好wap视频网站建设难吗?
  • 好的免费个人网站网站开发+.net+开源
  • 深圳移动网站建设公司排名东莞网站建设dgjcwl
  • 德州网站建设商户网站建设公司
  • 2012服务器如何做网站国外大气网站设计
  • 郑州官网网站优化公司搜狗搜索引擎优化论文
  • 网站第三方登录怎么做做网站运营工资多少
  • 七台河北京网站建设深圳网页设计公司建设
  • 视频网站开发防止盗链市场营销主要学什么
  • 做装饰画的行业网站做外汇看新闻在什么网站看
  • 半岛官方网站下载黄冈网站建设设计
  • 网站建设需要懂什么语言网络舆情优化公司
  • 网站字体特效莱芜都市网二手
  • 黄山网站建设找哪家wordpress静态页
  • 国内免费推广网站艺术字logo设计在线生成