中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

怎樣可以做網(wǎng)站培訓(xùn)機(jī)構(gòu)網(wǎng)站制作

怎樣可以做網(wǎng)站,培訓(xùn)機(jī)構(gòu)網(wǎng)站制作,企業(yè)網(wǎng)站可以做游戲類網(wǎng)站么,jsp網(wǎng)站開發(fā)關(guān)鍵技術(shù)前言 前面我們實現(xiàn)了基本的數(shù)據(jù)更新到視圖渲染的邏輯,但是這種方式(innerHTML)是極其低效的, 因此,我們相應(yīng)引入 dom 和 diff 算法, 數(shù)據(jù)到視圖的過程變?yōu)? state -> vdom -> dom vNode 層 所謂 vNode, 就是一個表示 dom 結(jié)構(gòu)的輕量對象 {tag, props, children; }為…

前言

前面我們實現(xiàn)了基本的數(shù)據(jù)更新到視圖渲染的邏輯,但是這種方式(innerHTML)是極其低效的, 因此,我們相應(yīng)引入 dom 和 diff 算法, 數(shù)據(jù)到視圖的過程變?yōu)?

state -> vdom -> dom

vNode 層

所謂 vNode, 就是一個表示 dom 結(jié)構(gòu)的輕量對象

{tag, props, children;
}

為了方便創(chuàng)建, 引入創(chuàng)建一個創(chuàng)建節(jié)點的方法h

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

我們需要修改 render 函數(shù), 讓其返回一個創(chuàng)建好的 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 掛載到真實的節(jié)點

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

mountElement 的實現(xiàn)邏輯

  1. 根據(jù)標(biāo)簽創(chuàng)建元素
  2. 更新屬性
  3. 如果子節(jié)點為文本節(jié)點,直接創(chuàng)建, 若為數(shù)組,則遞歸創(chuàng)建
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 算法

除了第一次掛載需要生成所有節(jié)點以外, 新的更新是在舊的基礎(chǔ)上"縫縫補(bǔ)補(bǔ)", 這個差量更新的過程交給我們的 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 節(jié)點進(jìn)行操作, 在 mounted 過程中將 dom 渲染完成后,我們需要將其掛載到對應(yīng)的 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 節(jié)點的處理
newTree.el = oldTree.el;
// props, 對比兩個對象, 各自遍歷一遍,找出各自不同的地方
let { props: newProps } = newTree;
let { props: oldProps } = oldTree;
if (newProps && oldProps) {Object.keys(newProps).forEach((key) => {// 同時存在,意味著需要更新節(jié)點let newVal = newProps[key];if (Object.hasOwnProperty.call(oldProps, key)) {let oldVal = oldProps[key];if (newVal !== oldVal) {newTree.el.setAttribute(key, newVal);}} else {// 舊的不存在, 創(chuàng)建newTree.el.setAttribute(key, newVal);}});
}
// 移除已不存在的舊節(jié)點
if (oldProps) {Object.keys(oldProps).forEach((key) => {if (!Object.hasOwnProperty.call(newProps, key)) {newTree.el.removeAttribute(key);}});
}

當(dāng)然, 為了演示, 這里的處理過程比較簡單,

  1. children 的處理

chilren 的處理相對比較麻煩,為了簡化, 目前根據(jù) children 的類型區(qū)分

即: 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)) {// ...}
}

下面分析兩者都是數(shù)組的情況, 為了簡化, 只對節(jié)點的長度作處理,不處理相同長度內(nèi)的節(jié)點移位操作

// 暴力解法: 只對節(jié)點的長度作處理,不處理相同長度內(nèi)的節(jié)點移位操作
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);
}
// 創(chuàng)建
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(); // 節(jié)點移除自身}
}

本文首發(fā)于個人 Github前端開發(fā)筆記,由于筆者能力有限,文章難免有疏漏之處,歡迎指正

http://www.risenshineclean.com/news/21766.html

相關(guān)文章:

  • 商城網(wǎng)站 報價 方案優(yōu)化建站
  • 公司門戶網(wǎng)站該怎么做seo建站營銷
  • 企業(yè)網(wǎng)站功能模塊長春做網(wǎng)站推廣的公司
  • 營銷型網(wǎng)站建設(shè)教學(xué)淘寶優(yōu)秀軟文范例100字
  • 億瑪酷網(wǎng)站建設(shè)域名注冊新網(wǎng)
  • 網(wǎng)絡(luò)營銷中自建網(wǎng)站平臺推廣方式
  • 鞍山建設(shè)局的網(wǎng)站seo快速排名系統(tǒng)
  • 專門做微信推送的網(wǎng)站廣東疫情動態(tài)人民日報
  • wordpress 多語言切換東莞seo排名外包
  • 做鉆石的網(wǎng)站如何推廣我的網(wǎng)站
  • quercus wordpress長沙網(wǎng)站優(yōu)化價格
  • 網(wǎng)站的做公司鄭州seo建站
  • 怎么讓百度搜索靠前北京seo工程師
  • .net網(wǎng)站設(shè)計seo技術(shù)優(yōu)化
  • 壽光網(wǎng)站建設(shè)湖南有實力seo優(yōu)化哪家好
  • 石家莊網(wǎng)站制作費用搜索大全引擎入口
  • 東城建站推廣競價排名的弊端
  • 北京網(wǎng)站開發(fā)網(wǎng)站建設(shè)seo引擎搜索
  • 網(wǎng)絡(luò)管理系統(tǒng)設(shè)備seo優(yōu)化公司信
  • 廣州市品牌網(wǎng)站建設(shè)公司蘇州網(wǎng)絡(luò)推廣seo服務(wù)
  • WordPress錯誤返回寧波谷歌seo推廣
  • 企業(yè)的建站方式競價排名是什么意思
  • 張家港網(wǎng)站制作公司優(yōu)化大師電視版
  • 網(wǎng)頁模板網(wǎng)站生成免費建站的網(wǎng)站有哪些
  • 網(wǎng)站開發(fā)非常之旅開發(fā)網(wǎng)站用什么軟件
  • 河南錦路路橋建設(shè)有限公司網(wǎng)站高端網(wǎng)站建設(shè)定制
  • 做漫畫網(wǎng)站空間多大文案短句干凈治愈
  • 我國市級政府網(wǎng)站建設(shè)分析平面設(shè)計
  • 網(wǎng)站建設(shè)企業(yè)蛋糕怎么做公司網(wǎng)頁
  • 黃金做空網(wǎng)站長沙本地推廣聯(lián)系電話