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

烟台cms建站模板用pycharm做网站

烟台cms建站模板,用pycharm做网站,包头做网站公司哪家好,游戏网页设计教程渲染器与响应式系统的结合 本节#xff0c;我们暂时将渲染器限定在 DOM 平台。既然渲染器用来渲染真实 DOM 元素#xff0c;那么严格来说#xff0c;下面的函数就是一个合格的渲染器: // 渲染器#xff1a; function renderer(domString, container) {container.innerHTM…渲染器与响应式系统的结合 本节我们暂时将渲染器限定在 DOM 平台。既然渲染器用来渲染真实 DOM 元素那么严格来说下面的函数就是一个合格的渲染器: // 渲染器 function renderer(domString, container) {container.innerHTML domString }使用渲染器 renderer(h1Hello/h1, document.getElementById(app))如果页面中存在 id 为 app 的 DOM 元素那么上面的代码就会将 hello 插入到该 DOM 元素内。 当然我们不仅可以渲染静态的字符串还可以渲染动态拼接的 HTML 内容如下所示: let count 1 renderer(h1${count}/h1, document.getElementById(app))这样最终渲染出来的内容将会是 1。注意上面这段 代码中的变量 count如果它是一个响应式数据会怎么样呢?这让 我们联想到副作用函数和响应式数据。 利用响应系统我们可以让整 个渲染过程自动化: const count ref(1)effect(() {renderer(h1${count.value}/h1,document.getElementById(app))})count.value在这段代码中我们首先定义了一个响应式数据 count它是一 个 ref然后在副作用函数内调用 renderer 函数执行渲染。副作用 函数执行完毕后会与响应式数据建立响应联系。当我们修改 count.value 的值时副作用函数会重新执行完成重新渲染。所以 上面的代码运行完毕后最终渲染到页面的内容是 h12/h1。 这就是响应系统和渲染器之间的关系。我们利用响应系统的能 力自动调用渲染器完成页面的渲染和更新。这个过程与渲染器的具 体实现无关在上面给出的渲染器的实现中仅仅设置了元素的 innerHTML 内容。 渲染器的每本概念 renderer 渲染器 render渲染 渲染器的作用是把虚拟 DOM 渲染为特定平台上的真实元素。在浏览器平台上渲染器会把虚拟 DOM 渲染为真实 DOM 元素。 渲染器把虚拟 DOM 节点渲染为真实 DOM 节点的过程叫作 挂载mount。 Vue.js 组件中的 mounted 钩子就会在挂载完成时触发。这就意味着在 mounted 钩子中可以访问真实DOM 元素。 那么渲染器把真实 DOM 挂载到哪里呢?其实渲染器并不知道应该把真实 DOM 挂载到哪里因此渲染器通常需要接收一个挂载点作为参数用来指定具体的挂载位置。这里的“挂载点”其实就是一个DOM 元素渲染器会把该 DOM 元素作为容器元素并把内容渲染到其中。我们通常用英文 container 来表达容器。 // createRenderer创建渲染器 function createRenderer() {// render渲染函数// vnode真实dom// container具体的挂载位置function render(vnode, container) {}return render }有了渲染器我们就可以用它来执行渲染任务了如下面的代码所示: // createRenderer 函数创建 一个渲染器 const renderer createRenderer()// 首次渲染 // renderer.render 函数执行渲染 renderer.render(vnode, document.querySelector(#app))渲染器除了要执行挂载动作外还要执行更新动作。例如 const renderer createRenderer()// 首次渲染 renderer.render(oldVNode, document.querySelector(#app))// 第二次渲染 renderer.render(newVNode, document.querySelector(#app))如上面的代码所示由于首次渲染时已经把 oldVNode 渲染到 container 内了所以当再次调用 renderer.render 函数并尝试 渲染 newVNode 时就不能简单地执行挂载动作了。在这种情况下 渲染器会使用 newVNode 与上一次渲染的 oldVNode 进行比较试图 找到并更新变更点。这个过程叫作“打补丁”(或更新)英文通常用patch来表达。但实际上挂载动作本身也可以看作一种特殊的打补 丁它的特殊之处在于旧的 vnode 是不存在的。所以我们不必过于纠 结“挂载”和“打补丁”这两个概念 。代码示例如下: function createRenderer() {function render(vnode, container) {if (vnode) {// 新 vnode 存在将其与旧 vnode 一起传递给 patch 函数进行打补patch(container._vnode, vnode, container)} else {// 旧 vnode 存在且新 vnode 不存在说明是卸载(unmount)操作if (container._vnode) {unmount(container._vnode)}}// 把 vnode 存储到 container._vnode 下即后续渲染中的旧 vnodecontainer._vnode vnode} }上面这段代码给出了 render 函数的基本实现.我们可以配合下 面的代码分析其执行流程从而更好地理解 render 函数的实现思路。假设我们连续三次调用 renderer.render 函数来执行渲染: const renderer createRenderer()// 首次渲染 renderer.render(vnode1, document.querySelector(#app))// 第二次渲染 renderer.render(vnode2, document.querySelector(#app)) // 第三次渲染 renderer.render(null, document.querySelector(#app))在首次渲染时渲染器会将 vnode1 渲染为真实 DOM。渲染完成 后vnode1 会存储到容器元素的 container._vnode 属性 中它会在后续渲染中作为旧 vnode 使用。在第二次渲染时旧 vnode 存在此时渲染器会把 vnode2 作为 新 vnode并将新旧 vnode 一同传递给 patch 函数进行打补 丁。在第三次渲染时新 vnode 的值为 null即什么都不渲染。但 此时容器中渲染的是 vnode2 所描述的内容所以渲染器需要清 空容器。从上面的代码中可以看出我们使用unmount 卸载节点。 另外在上面给出的代码中我们注意到 patch 函数的签名如 下: patch(container._vnode, vnode, container)patch 函数是整个渲染器的 核心入口它承载了最重要的渲染逻辑我们会花费大量篇幅来详细 讲解它但这里仍有必要对它做一些初步的解释。 patch 函数至少接 收三个参数: 第一个参数 n1:旧 vnode第二个参数 n2:新 vnode。第三个参数 container:容器。 function patch(n1, n2, container) {}在首次渲染时容器元素的 container._vnode 属性是不存在的即 undefined。这意味着在首次渲染时传递给 patch 函数的第一个参数 n1 也是 undefined。这时patch 函数会执行挂载动作它会忽略 n1并直接将 n2 所描述的内容渲染到容器中。从这一点可以看出patch 函数不仅可以用来完成打补丁也可以用来执行挂载。 自定义渲染器 渲染器不仅能够把虚拟 DOM 渲染为浏览器平台上的真实 DOM。通过将渲染器设计为可配置的“通用”渲染器即可实现渲染到任意目标平台上。本节我们将以浏览器作为渲染的目标平台编写一个渲染器在这个过程中看看哪些内容是可以抽象的然后通过抽象将浏览器特定的 API 抽离这样就可以使得渲染器的核心不依赖于浏览器。在此基础上我们再为那些被抽离的 API提供可配置的接口即可实现渲染器的跨平台能力。 案例 对于这样一个 vnode我们可以使用 render 函数渲染它如下面的代码所示: const vnode {type: h1,children: hello } // 创建一个渲染器 const renderer createRenderer()// 调用 render 函数渲染该 vnode renderer.render(vnode, document.querySelector(#app))为了完成渲染工作我们需要补充 patch 函数: function patch(n1, n2, container) {// 如果 n1 不存在意味着挂载则调用 mountElement 函数完成挂载if(!n1) {mountElement(n2, container)} else {// n1 存在意味着打补丁暂时省略} }在上面这段代码中第一个参数 n1 代表旧 vnode第二个参数 n2 代表新 vnode。当 n1 不存在时意味着没有旧 vnode此时只需 要执行挂载即可。这里我们调用 mountElement 完成挂载它的实现 如下: function mountElement(vnode, container) {// 创建dom元素const el document.createElement(vnode.type)// 处理子节点如果子节点是字符串代表元素具有文本节点if (typeof vnode.children string) {// 因此只需要设置元素的 textContent 属性即可el.textContent vnode.children}// 将元素添加到容器中container.appendChild(el) }挂载一个普通标签元素的工作已经完成。接下来我们分析这段 代码存在的问题。我们的目标是设计一个不依赖于浏览器平台的通用 渲染器但很明显mountElement 函数内调用了大量依赖于浏览器 的 API例如 document.createElement、el.textContent 以 及 appendChild 等。想要设计通用渲染器第一步要做的就是将这 些浏览器特有的 API 抽离。怎么做呢?我们可以将这些操作 DOM 的 API 作为配置项该配置项可以作为 createRenderer 函数的参数 如下面的代码所示: // 在创建 renderer 时传入配置项 const renderer createRenderer({// 用于创建元素createElement(tag) {return document.createElement(tag)},// 用于设置元素的文本节点setElementText(el.taxt) {el.textContent text},// 用于在给定的 parent 下添加指定元素insert(el, parent, anchor null) {parent.insertBefore(el, anchor)} })可以看到我们把用于操作 DOM 的 API 封装为一个对象并把 它传递给createRenderer 函数。这样在 mountElement 等函数 内就可以通过配置项来取得操作 DOM 的 API 了: function createRenderer(options) {// 通过 options 得到操作 DOM 的 APIconst { createElement, setElementText, insert } optionsfunction mountElement(vnode, container) {}function patch(v1, v2, container) {}function render(vnode, container) {}return {render}}接着我们就可以使用从配置项中取得的 API 重新实现 mountElement 函数: function mountElement(vnode, container) {// 调用 createElement 函数创建元素const el createElement(vnode.type)// 处理子节点如果子节点是字符串代表元素具有文本节点if (typeof vnode.children string) {// 调用 setElementText 设置元素的文本节点setElementText(el, vnode.children)}// 调用 insert 函数将元素插入到容器内insert(el, container) }如上面的代码所示重构后的 mountElement 函数在功能上没有 任何变化。不同的是它不再直接依赖于浏览器的特有 API 了。这意 味着只要传入不同的配置项就能够完成非浏览器环境下的渲染工 作。为了展示这一点我们可以实现一个用来打印渲染器操作流程的 自定义渲染器如下面的代码所示: // 在创建 renderer 时传入配置项 const renderer createRenderer({// 用于创建元素createElement(tag) {console.log(创建元素 ${tag})return document.createElement(tag)},// 用于设置元素的文本节点setElementText(el.taxt) {console.log(设置${JSON.stringify(el)}的文本内容${text})el.textContent text},// 用于在给定的 parent 下添加指定元素insert(el, parent, anchor null) {console.log(将${JSON.stringify(el)}添加到${JSON.stringify(parent)})parent.children el} })这样我们就实现了一个自定义渲染器可以用下面这段代码来检测它的能力: const vnode {type: h1,children: hello }const container { type: root } renderer.render(vnode, container)在浏览器中的运行结果如下 现在我们对自定义渲染器有了更深刻的认识了。自定义渲染器并不是“黑魔法”它只是通过抽象的手段让核心代码不再依赖平台特有的 API再通过支持个性化配置的能力来实现跨平台。
http://www.tj-hxxt.cn/news/227281.html

相关文章:

  • 深圳网站制作搜行者seo郑州企业自助建站
  • 企业网站倾向于wordpress网站公告模板代码
  • 酒业公司网站模板建设红外测温仪网站
  • 垦利网站定制开发商延期交房可以退房吗?
  • 金山企业型网站建设网站项目签约
  • 网站开发行业信息网优秀的学校网站欣赏
  • 做一个网站需要花费多少钱夺宝网站还可以做吗
  • 服务器建网站网页内容
  • 小说素材网站推进网站建设
  • 网站建设的公司有哪些重庆最近的新闻大事10条
  • 浙江建设职业技术学院门户网站51找呀模板网
  • 怎么做网站编程网络服务商机构
  • html网页设计结课作业保定seo企业网站
  • 网站职业培训机构河北商城网站搭建多少钱
  • 光速网络网站做金融的免费发帖的网站有哪些
  • 可以做微信推文的网站建筑建设网站
  • 无锡网站制作推荐广州网站建设很棒 乐云践新
  • 高邮市建设局网站公众号文章排版
  • 招商网站开发文档wordpress创建分类目录
  • 邢台做网站推广价格东营网络营销
  • 搭建网站平台有前途吗建设网站的和服务器
  • 宁波企业网站设计教师个人网站建设
  • 免费做网站公司ydwzjs网站记录ip 修改
  • 哪里可以买链接网站常德做网站
  • 宿州集团网站建设网站建设排名优化技巧
  • 创意江苏网站建设中国十大贸易公司排名
  • 临桂建设局安全股网站企业建设网站优势
  • 网站建设初期的工作计划网站建设公司客户来源渠道
  • 南通网站优化推广网站建设现在主要做些什么
  • 摄影网站难做吗网站推广指标包括( )。