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

优秀个人网站设计欣赏沧州建设局网站

优秀个人网站设计欣赏,沧州建设局网站,自己的电脑做服务器 并建网站,做php网站用什么软件源码实现思路#xff08;面试高分回答#xff09; 面试官问我 Vue 的 nextTick 原理是怎么实现的#xff0c;我这样回答#xff1a; 在调用 this.$nextTick(cb) 之前#xff1a; 存在一个 callbacks 数组#xff0c;用于存放所有的 cb 回调函数。存在一个 flushCallbac…源码实现思路面试高分回答 面试官问我 Vue 的 nextTick 原理是怎么实现的我这样回答 在调用 this.$nextTick(cb) 之前 存在一个 callbacks 数组用于存放所有的 cb 回调函数。存在一个 flushCallbacks 函数用于执行 callbacks 数组中的所有回调函数。存在一个 timerFunc 函数用于将 flushCallbacks 函数添加到任务队列中。 当调用 this.nextTick(cb) 时 nextTick 会将 cb 回调函数添加到 callbacks 数组中。判断在当前事件循环中是否是第一次调用 nextTick 如果是第一次调用将执行 timerFunc 函数添加 flushCallbacks 到任务队列。如果不是第一次调用直接下一步。 如果没有传递 cb 回调函数则返回一个 Promise 实例。 根据上述描述对应的流程图如下 #mermaid-svg-g8PjAXvCpMjVZwiP {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-g8PjAXvCpMjVZwiP .error-icon{fill:#552222;}#mermaid-svg-g8PjAXvCpMjVZwiP .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-g8PjAXvCpMjVZwiP .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-g8PjAXvCpMjVZwiP .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-g8PjAXvCpMjVZwiP .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-g8PjAXvCpMjVZwiP .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-g8PjAXvCpMjVZwiP .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-g8PjAXvCpMjVZwiP .marker{fill:#333333;stroke:#333333;}#mermaid-svg-g8PjAXvCpMjVZwiP .marker.cross{stroke:#333333;}#mermaid-svg-g8PjAXvCpMjVZwiP svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-g8PjAXvCpMjVZwiP .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-g8PjAXvCpMjVZwiP .cluster-label text{fill:#333;}#mermaid-svg-g8PjAXvCpMjVZwiP .cluster-label span{color:#333;}#mermaid-svg-g8PjAXvCpMjVZwiP .label text,#mermaid-svg-g8PjAXvCpMjVZwiP span{fill:#333;color:#333;}#mermaid-svg-g8PjAXvCpMjVZwiP .node rect,#mermaid-svg-g8PjAXvCpMjVZwiP .node circle,#mermaid-svg-g8PjAXvCpMjVZwiP .node ellipse,#mermaid-svg-g8PjAXvCpMjVZwiP .node polygon,#mermaid-svg-g8PjAXvCpMjVZwiP .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-g8PjAXvCpMjVZwiP .node .label{text-align:center;}#mermaid-svg-g8PjAXvCpMjVZwiP .node.clickable{cursor:pointer;}#mermaid-svg-g8PjAXvCpMjVZwiP .arrowheadPath{fill:#333333;}#mermaid-svg-g8PjAXvCpMjVZwiP .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-g8PjAXvCpMjVZwiP .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-g8PjAXvCpMjVZwiP .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-g8PjAXvCpMjVZwiP .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-g8PjAXvCpMjVZwiP .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-g8PjAXvCpMjVZwiP .cluster text{fill:#333;}#mermaid-svg-g8PjAXvCpMjVZwiP .cluster span{color:#333;}#mermaid-svg-g8PjAXvCpMjVZwiP div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-g8PjAXvCpMjVZwiP :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是 否 this.$nextTick(callback) 将回调函数 callback 放入到数组 callbacks 中 判断是否是第一次调用 nextTick 执行 timerFunc, 将 flushCallbacks 添加到任务队列 如果没有 cb, 则retrun Promise 结束 如果上面的描述没有很理解。没关系花几分钟跟着我下面来看完下面的源码逐行讲解你一定能够清晰地向别人讲出你的思路 nextTick思路详解 ‍♂‍➡ 1. 核心代码 下面用十几行代码就已经可以基本实现「nextTick」的功能默认浏览器支持「Promise」) // 存储所有的cb回调函数 const callbacks []; /*类似于节流的标记位标记是否处于节流状态。防止重复推送任务*/ let pending false;/*遍历执行数组 callbacks 中的所有存储的cb回调函数*/ function flushCallbacks() {// 重置标记允许下一个 nextTick 调用pending false;/*执行所有cb回调函数*/for (let i 0; i callbacks.length; i) {callbacks[i]();}// 清空回调数组为下一次调用做准备callbacks.length 0; }function nextTick(cb) {// 将回调函数cb添加到 callbacks 数组中callbacks.push(() {cb();});// 第一次使用 nextTick 时pending 为 false下面的代码才会执行if (!pending) {// 改变标记位的值如果有flushCallbacks被推送到任务队列中去则不需要重复推送pending true;// 使用 Promise 机制将 flushCallbacks 推送到任务队列Promise.resolve().then(flushCallbacks);} }如果你想要应付面试官能手写这部分核心原理就已经差不多啦。 如果你想彻底掌握它请继续跟着我来‍♂ 2. nextTick() 返回promise 我们在开发中会使用await this.$nextTick();让其下面的代码全部变成异步代码。 比如写成这样 await this.$nextTick(); ...... ......// 或者 this.$nextTick().then((){...... })核心就是nextTick()如果没有参数则返回一个promise const callbacks []; let pending false;function flushCallbacks() {pending false;for (let i 0; i callbacks.length; i) {callbacks[i]();}callbacks.length 0; }function nextTick(cb) {// 用于存储 Promise 的resolve函数let _resolve;callbacks.push(() {/* ------------------ 新增start ------------------ */// 如果有cb回调函数将cb存储到callbacksif (cb) {cb();} else if (_resolve) {// 如果参数cb不存在则保存promise的的成功回调resolve_resolve();}/* ------------------ 新增end ------------------ */});if (!pending) {pending true;Promise.resolve().then(flushCallbacks);}/* ------------------ 新增start ------------------ */if (!cb) {return new Promise((resolve, reject) {// 保存resolve到callbacks数组中_resolve resolve;});}/* ------------------ 新增end ------------------ */ }「测试一下」 async function testNextTick() {let message 初始消息;nextTick(() {message 更新后的消息;});console.log(传入回调, message); // 输出1: 初始消息// 不传入回调的情况await nextTick(); // nextTick 返回 Promiseconsole.log(未传入回调后, message); // 输出2: 更新后的消息 }// 运行测试 testNextTick();3. 判断浏览器环境 为了防止浏览器不支持 「Promise」「Vue」 选择了多种 API 来实现兼容 「nextTick」 Promise -- MutationObserver -- setImmediate -- setTimeout 「Promise」 (微任务) 如果当前环境支持 「Promise」「Vue」 会使用 Promise.resolve().then(flushCallbacks) 「MutationObserver」 (微任务) 如果不支持 「Promise」支持 「MutationObserver」。「Vue」 会创建一个 「MutationObserver」 实例通过监听文本节点的变化来触发执行回调函数。 「setImmediate」 (宏任务) 如果前两者都不支持支持 「setImmediate」。则setImmediate(flushCallbacks) 注意「setImmediate」 在绝大多数浏览器中不被支持但在 「Node.js」 中是可用的。 「setTimeout」 (宏任务) 如果前面所有的都不支持那你的浏览器一定支持 「setTimeout」 终极方案setTimeout(flushCallbacks, 0) // 存储所有的回调函数 const callbacks []; /* 类似于节流的标记位标记是否处于节流状态。防止重复推送任务 */ let pending false;/* 遍历执行数组 callbacks 中的所有存储的 cb 回调函数 */ function flushCallbacks() {// 重置标记允许下一个 nextTick 调用pending false;/* 执行所有 cb 回调函数 */for (let i 0; i callbacks.length; i) {callbacks[i](); // 依次调用存储的回调函数}// 清空回调数组为下一次调用做准备callbacks.length 0; }// 判断最终支持的 APIPromise / MutationObserver / setImmediate / setTimeout let timerFunc;if (typeof Promise ! undefined) {// 创建一个已resolve的 Promise 实例var p Promise.resolve();// 定义 timerFunc 为使用 Promise 的方式调度 flushCallbackstimerFunc () {// 使用 p.then 方法将 flushCallbacks 推送到微任务队列p.then(flushCallbacks);}; } else if (typeof MutationObserver ! undefined MutationObserver.toString() [object MutationObserverConstructor] ) {/* 新建一个 textNode 的 DOM 对象用 MutationObserver 绑定该 DOM 并指定回调函数。在 DOM 变化的时候则会触发回调该回调会进入主线程比任务队列优先执行即 textNode.data String(counter) 时便会加入该回调 */var counter 1; // 用于切换文本节点的值var observer new MutationObserver(flushCallbacks); // 创建 MutationObserver 实例var textNode document.createTextNode(String(counter)); // 创建文本节点observer.observe(textNode, {characterData: true, // 监听文本节点的变化});// 定义 timerFunc 为使用 MutationObserver 的方式调度 flushCallbackstimerFunc () {counter (counter 1) % 2; // 切换 counter 的值0 或 1textNode.data String(counter); // 更新文本节点以触发观察者}; } else if (typeof setImmediate ! undefined) {/* 使用 setImmediate 将回调推入任务队列尾部 */timerFunc () {setImmediate(flushCallbacks); // 将 flushCallbacks 推送到宏任务队列}; } else {/* 使用 setTimeout 将回调推入任务队列尾部 */timerFunc () {setTimeout(flushCallbacks, 0); // 将 flushCallbacks 推送到宏任务队列}; }function nextTick(cb) {// 用于存储 Promise 的解析函数let _resolve; // 将回调函数 cb 添加到 callbacks 数组中callbacks.push(() {// 如果有 cb 回调函数将 cb 存储到 callbacksif (cb) {cb();} else if (_resolve) {// 如果参数 cb 不存在则保存 Promise 的成功回调 resolve_resolve();}});// 第一次使用 nextTick 时pending 为 false下面的代码才会执行if (!pending) {// 改变标记位的值如果有 nextTickHandler 被推送到任务队列中去则不需要重复推送pending true;// 调用 timerFunc将 flushCallbacks 推送到合适的任务队列timerFunc(flushCallbacks);}// 如果没有 cb 且环境支持 Promise则返回一个 Promiseif (!cb typeof Promise ! undefined) {return new Promise((resolve) {// 保存 resolve 到 callbacks 数组中_resolve resolve;});} }Vue纯源码 上面的代码实现对于 「nextTick」 功能已经非常完整了接下来我将给你展示出 「Vue」 中实现 「nextTick」 的完整源码。无非是加了一些判断变量是否存在的判断。看完上面的讲解我相信聪明的你一定能理解 「Vue」 实现 「nextTick」 的源码了吧 // 存储所有的 cb 回调函数 const callbacks []; /* 类似于节流的标记位标记是否处于节流状态。防止重复推送任务 */ let pending false;/* 遍历执行数组 callbacks 中的所有存储的 cb 回调函数 */ function flushCallbacks() {pending false; // 重置标记允许下一个 nextTick 调用const copies callbacks.slice(0); // 复制当前的 callbacks 数组callbacks.length 0; // 清空 callbacks 数组for (let i 0; i copies.length; i) {copies[i](); // 执行每一个存储的回调函数} } // 判断是否为原生实现的函数 function isNative(Ctor) {// 如Promise.toString() 为 function Promise() { [native code] }return typeof Ctor function /native code/.test(Ctor.toString()); }// 判断最终支持的 APIPromise / MutationObserver / setImmediate / setTimeout let timerFunc;if (typeof Promise ! undefined isNative(Promise)) {const p Promise.resolve(); // 创建一个已解决的 Promise 实例timerFunc () {p.then(flushCallbacks); // 使用 p.then 将 flushCallbacks 推送到微任务队列// 在某些有问题的 UIWebView 中Promise.then 并不会完全失效// 但可能会陷入一种奇怪的状态回调函数被添加到微任务队列中// 但队列并没有被执行直到浏览器需要处理其他工作比如定时器。// 因此我们可以通过添加一个空的定时器来“强制”执行微任务队列。if (isIOS) setTimeout(() {}); // 解决iOS 的bug推迟 空函数 的执行如果不理解建议忽略}; } else if (typeof MutationObserver ! undefined (isNative(MutationObserver) ||MutationObserver.toString() [object MutationObserverConstructor]) ) {let counter 1; // 用于切换文本节点的值const observer new MutationObserver(flushCallbacks); // 创建 MutationObserver 实例const textNode document.createTextNode(String(counter)); // 创建文本节点observer.observe(textNode, {characterData: true, // 监听文本节点的变化});// 定义 timerFunc 为使用 MutationObserver 的方式调度 flushCallbackstimerFunc () {counter (counter 1) % 2; // 切换 counter 的值0 或 1textNode.data String(counter); // 更新文本节点以触发观察者}; } else if (typeof setImmediate ! undefined isNative(setImmediate)) {timerFunc () {setImmediate(flushCallbacks); // 使用 setImmediate 推送到任务队列}; } else {timerFunc () {setTimeout(flushCallbacks, 0); // 使用 setTimeout 推送到宏任务队列}; }function nextTick(cb, ctx) {let _resolve; // 用于存储 Promise 的解析函数// 将回调函数 cb 添加到 callbacks 数组中callbacks.push(() {if (cb) {try {cb.call(ctx); // 执行传入的回调函数} catch (e) {handleError(e, ctx, nextTick); // 错误处理}} else if (_resolve) {_resolve(ctx); // 解析 Promise}});// 第一次使用 nextTick 时pending 为 false下面的代码才会执行if (!pending) {pending true; // 改变标记位的值timerFunc(); // 调用 timerFunc调度 flushCallbacks}// 如果没有 cb 且环境支持 Promise则返回一个 Promiseif (!cb typeof Promise ! undefined) {return new Promise((resolve) {_resolve resolve; // 存储解析函数});} }总结 通过这样分成三步、循序渐进的方式我们深入探讨了 「nextTick」 的原理和实现机制。希望这篇文章能够对你有所帮助让你在前端开发的道路上更加得心应手
http://www.dnsts.com.cn/news/24719.html

相关文章:

  • 寺庙网站模板网站在工信部备案
  • 分销网站开发合同企业电话名录
  • 婚恋网站建设方案网页制作学校
  • 模板网站和定制网站影响排名网站是用什么语言写的
  • 免费做爰小说网站WordPress源码路由
  • 安徽华强建设集团网站中国最牛的央企排名
  • 做汉字词卡的网站购物类网站开发
  • 电子商务网站建设与维护 论文WordPress前端发布文章
  • 免费网站建站百度wordpress 环保主题
  • 做外贸网站商城门户网站排行榜
  • 深圳建网站兴田德润专业企业网站建设 西宁
  • 一个网站的建设方案ic设计公司排名
  • 凡科网站怎么做链接头像logo江苏专业做网站
  • 用ps做网站主页制作一个网站需要什么
  • 做网站保证效果做网站的
  • 最好的建设网站网站开发后如何维护
  • 网站引导页动态效果怎么做川畅科技网站设计
  • 专业制作网站公司做电子请帖网站有哪些
  • 刷leetcode对网站开发有用吗常见的o2o平台有哪些
  • 自建网站需要备案吗模板和网站的区别
  • 怎么在自己做的网站上发视频教程中国建材人才网
  • 商丘网站公司优化公司内部流程
  • 学生求职网站的需求分析怎么做网页微信版登录
  • 邮箱网站怎么做装修公司网站源码php
  • 北京做网站公司电话seo软文推广工具
  • 扬州外贸网站seowordpress博客头图怎么改
  • 医院网站建设 费用做暧暧视频免费视频中国网站
  • 一个简单的网站怎么做的太原网站公司
  • 网网站设计网网站构建培训
  • 单位网站设计流程步骤网站建设需要的客户资料