手写promis(1)

目录

前言

核心功能--构造函数 

核心功能--状态及原因

then方法

成功和失败回调

异步及多次调用

异步任务--核心api

Promise.then:

queueMicrotask:

MutationObserver:

setImmediate:

setTimeout:

异步任务---函数封装


前言

Promise(承诺)是一种用于处理异步操作的JavaScript编程技术。它是一种代表一个尚未完成的操作的对象,该操作可能会在将来的某个时刻完成或失败。Promise提供了一种更结构化和可维护的方式来处理异步代码,特别是在处理网络请求、文件I/O、定时器等操作时非常有用。

Promise对象有三种状态:

  1. Pending(进行中):初始状态,表示操作尚未完成或失败。
  2. Fulfilled(已完成):表示操作成功完成。
  3. Rejected(已失败):表示操作失败。

Promise对象具有两个重要的方法:

  1. then(): 用于注册回调函数,当Promise状态变为Fulfilled时执行。
  2. catch(): 用于注册回调函数,当Promise状态变为Rejected时执行。

使用Promise,可以更清晰地定义异步操作的工作流程,避免了回调地狱(Callback Hell)的问题,使代码更易于理解和维护。以下是一个简单的Promise示例:

const myPromise = new Promise((resolve, reject) => {// 异步操作setTimeout(() => {const randomValue = Math.random();if (randomValue > 0.5) {resolve("操作成功");} else {reject("操作失败");}}, 1000);
});myPromise.then(result => {console.log(result); // 在操作成功时执行}).catch(error => {console.error(error); // 在操作失败时执行});

这个示例创建了一个Promise对象,模拟了一个异步操作,并根据随机值决定是成功还是失败。通过.then().catch()方法,我们可以分别处理成功和失败的情况。这使得异步代码的处理更加结构化和可控。

手写原来步骤

核心功能--构造函数 

  1. 定义类(Define the class): 这里定义了一个名为MyPromise的类,用于创建自定义Promise对象。

  2. 添加构造函数(Add a constructor): 在构造函数中,通过constructor方法定义了一个新的MyPromise对象。当创建MyPromise对象时,会执行构造函数。构造函数接受一个函数func作为参数,这个函数在创建MyPromise对象时传入。

  3. 定义resolve/reject(Define resolve and reject functions): 在构造函数中,定义了resolvereject函数,它们分别用于处理Promise的成功和失败情况。resolve函数用于处理成功情况,它接受一个参数result,表示成功的原因。reject函数用于处理失败情况,它也接受一个参数result,表示失败的原因。

  4. 执行回调函数(Execute the callback function): 最后,构造函数中调用了传入的func函数,这个函数接受resolvereject作为参数。这意味着在创建MyPromise对象时,会执行传入的回调函数,并在适当的时候调用resolvereject函数来处理异步操作的结果

/*** 构造函数* 1. 定义类* 2. 添加构造函数* 3. 定义reslove/reject* 4. 执行回调函数*///1.定义类
class MyPromise {// 2.添加构造函数 new时会执行 constructor 传入回调函数constructor(func) {// 3.func 接受两个行参 成功回调(成功原因),失败回调(失败原因)// resolve:<Function>(result:<any>)  reject:<Function>(result:<any>) const resolve = (result) => {console.log('resolve执行了--', result);}const reject = (result) => {console.log('reject执行了--', result);}// 4. 执行回调函数func(resolve, reject)}
}// 测试代码
const p = new MyPromise((resolve, reject) => {console.log('执行回调函数');// resolve('success')reject('error')
})

核心功能--状态及原因

  1. 添加实例属性状态(pending / fulfilled / rejected)(默认为等待)

  2. 添加实例属性原因(默认为undefined)

  3. 调整resolve函数和reject函数 resolvereject函数改变状态和保存原因,这是Promise的核心功能之一。

  4. 添加状态检查:在resolvereject函数中,添加状态检查来确保状态只能从pending改变一次。这可以防止状态被多次改变。
/*** 状态及原因* 1. 添加状态 pending / fulfilled / rejected* 2. 添加原因* 3. 调整reslove/reject* 4. 状态不可逆*///通过变量保存状态,方便使用
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'class MyPromise {// 1. 添加实例属性 状态(pending / fulfilled / rejected)(默认为等待)state = PENDING// 2. 添加实例属性 原因(默认为undefined)result = undefinedconstructor(func) {// this 箭头函数this-->上级作用域(构造函数)-->  实例 // 3. 调整reslove pending-- > fulfilled 添加原因const resolve = (result) => {// 4. 状态不可逆if (this.state == PENDING) {this.state = FULFILLEDthis.result = result}}// 3. reject pending-- > rejected 添加原因const reject = (result) => {if (this.state == PENDING) {this.state = REJECTEDthis.result = result}}func(resolve, reject)}
}// 测试代码
const p = new MyPromise((resolve, reject) => {resolve('success')// reject('error')
})

then方法

成功和失败回调

  1. 添加实例方法(then)
  2. 参数判断(参考文档)

如果是个函数 执行回调函数 

如果 onFulfilled 不是一个函数,则内部会被替换为一个恒等函数((x) => x),它只是简单地将兑现值向前传递。

如果 onRejected 不是一个函数,则内部会被替换为一个抛出器函数((x) => { throw x; }),它会抛出它收到的拒绝原因。

3.判断状态执行成功回调函数or失败回调函数(实例化完成后状态已经确定)

/*** 成功和失败回调* 1. 添加实例方法* 2. 参数判断(参考文档)*  2.1. 执行成功回调*  2.2. 执行失败回调*///通过变量保存状态,方便使用
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'class MyPromise {state = PENDINGresult = undefinedconstructor(func) {const resolve = (result) => {if (this.state == PENDING) {this.state = FULFILLEDthis.result = result}}const reject = (result) => {if (this.state == PENDING) {this.state = REJECTEDthis.result = result}}func(resolve, reject)}// 添加实例方法then(onFulfilled, onRejected) {// 参数判断  如果 onFulfilled 不是一个函数,则内部会被替换为一个恒等函数((x) => x),它只是简单地将兑现值向前传递。onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : x => x// 参数判断  如果 onRejected 不是一个函数,则内部会被替换为一个抛出器函数((x) => { throw x; }),它会抛出它收到的拒绝原因。onRejected = typeof onRejected === 'function' ? onRejected : (x) => { throw x }// 执行成功回调or执行失败回调(状态实例化完成就立即调用了,所以可以执行返回结果--》异步暂时不考虑)if (this.state === FULFILLED) {onFulfilled(this.result)} else if (this.state === REJECTED) {onRejected(this.result)}}
}// 测试代码
const p = new MyPromise((resolve, reject) => {// resolve('success')reject('error')
})
// p.then((result) => {
//     console.log('成功回调', result)
// }, err => {
//     console.log('失败回调', err);
// })
p.then((result) => {console.log('成功回调', result)
})

异步及多次调用

  1. 定义实例属性,添加#为类内部使用标识
  2. 如果then执行后状态为pending存储异步时成功回调与失败回调
  3. 定时器两秒后 resolve执行 取出成功回调函数放入成功原因

  4. 定时器两秒后 reject执行 取出失败回调函数放入失败原因

/*** then-异步及多次调用* 1. 定义实例属性* 2. 保存回调函数* 3. 调用成功回调* 4. 调用失败回调*///通过变量保存状态,方便使用
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'class MyPromise {state = PENDINGresult = undefined// 定义实例属性 #外部不能访问 保存回调#handlers = []//[{onFulfilled,onRejected}...]constructor(func) {const resolve = (result) => {if (this.state == PENDING) {this.state = FULFILLEDthis.result = result// 3.定时器两秒后 resolve执行 取出成功回调函数放入成功原因this.#handlers.forEach(({ onFulfilled }) => {onFulfilled(this.result)})}}const reject = (result) => {if (this.state == PENDING) {this.state = REJECTEDthis.result = result// 4.定时器两秒后 reject执行 取出失败回调函数放入失败原因this.#handlers.forEach(({ onRejected }) => {onRejected(this.result)})}}func(resolve, reject)}then(onFulfilled, onRejected) {onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : x => xonRejected = typeof onRejected === 'function' ? onRejected : (x) => { throw x }if (this.state === FULFILLED) {onFulfilled(this.result)} else if (this.state === REJECTED) {onRejected(this.result)} else if (this.state === PENDING) {// 2. 代表状态还没有发生过改变,保存回调函数this.#handlers.push({onFulfilled, onRejected})}}
}// 测试代码
const p = new MyPromise((resolve, reject) => {setTimeout(() => {// resolve('success')reject('error')}, 2000);
})
p.then((result) => {console.log('成功回调', result)
}, err => {console.log('失败回调', err);
})
p.then((result) => {console.log('成功回调', result)
})

异步任务--核心api

 * Vue Promise.then, MutationObserver,setImmediate,setTimeout

 * 我们选用 queueMicrotask MutationObserver setTimeout

  • Promise.then,手写promise 不考虑这个
  • queueMicrotask:node11,新式浏览器(不包括ie11)
  • MutationObserver node不支持 ie11支持
  • setImmediate:ie10,11支持 edge:(12-18)支持(不考虑)
  • setTimeout:node,浏览器全支持

Promise.then:

  • 兼容性: 几乎所有现代浏览器和Node.js都支持Promise。
  • 用法: Promise是一种用于处理异步操作的机制,通过.then()方法可以注册回调函数来处理异步任务的完成或失败。例如:
const myPromise = new Promise((resolve, reject) => {// 异步操作if (/* 操作成功 */) {resolve(result);} else {reject(error);}
});myPromise.then((result) => {// 处理成功的情况},(error) => {// 处理失败的情况}
);

queueMicrotask:

Window 或 Worker 接口的 queueMicrotask() 方法,将微任务加入队列以在控制返回浏览器的事件循环之前的安全时间执行。

微任务是一个简短的函数,它将在当前任务完成其工作后运行,并且在执行上下文的控制权返回到浏览器的事件循环之前没有其他代码等待运行时运行。

它让你的代码在运行时不会干扰任何可能具有更高优先级的代码的运行,但在浏览器重新获得对执行上下文的控制之前,这可能取决于你需要完成的工作。你可以在我们的微任务指南中了解更多关于如何使用微任务以及选择这样做的原因。

微任务的重要性在于它能够以特定顺序异步执行任务。查看在 JavaScript 中通过 queueMicrotask() 使用微任务的详情。

微任务对于需要执行最后阶段的任务或其他在渲染之前的任务的库和框架特别有用。

参数

当浏览器引擎确定可以安全调用你的代码时执行的 function。微任务(microtask)的执行顺序在所有进行中的任务(pending task)完成之后,在对浏览器的事件循环产生控制(yielding control to the browser's event loop)之前。

返回值

无 undefined

  • 兼容性: 支持新式浏览器,但不包括IE11。
  • 用法: queueMicrotask用于将微任务排入微任务队列中,通常在Promise处理中使用,以确保微任务在宏任务之后执行。示例:
queueMicrotask(() => {// 这里执行微任务
});

MutationObserver:

MutationObserver 接口提供了监视对 DOM 树所做更改的能力。它被设计为旧的 Mutation Events 功能的替代品,该功能是 DOM3 Events 规范的一部分。

构造函数

MutationObserver()

创建并返回一个新的 MutationObserver 它会在指定的 DOM 发生变化时被调用。

方法

disconnect()

阻止 MutationObserver 实例继续接收的通知,直到再次调用其 observe() 方法,该观察者对象包含的回调函数都不会再被调用。

observe()

配置 MutationObserver 在 DOM 更改匹配给定选项时,通过其回调函数开始接收通知。

takeRecords()

从 MutationObserver 的通知队列中删除所有待处理的通知,并将它们返回到 MutationRecord 对象的新 Array 中。

  • 兼容性: 在大多数现代浏览器中支持,但Node.js不支持,而IE11也支持。
  • 用法: MutationObserver用于监视DOM树的变化,并在发生变化时触发回调函数。这通常用于监听DOM元素的变化。示例:
// 选择需要观察变动的节点
const targetNode = document.getElementById("some-id");// 观察器的配置(需要观察什么变动)
const config = { attributes: true, childList: true, subtree: true };// 当观察到变动时执行的回调函数
const callback = function (mutationsList, observer) {// Use traditional 'for loops' for IE 11for (let mutation of mutationsList) {if (mutation.type === "childList") {console.log("A child node has been added or removed.");} else if (mutation.type === "attributes") {console.log("The " + mutation.attributeName + " attribute was modified.");}}
};// 创建一个观察器实例并传入回调函数
const observer = new MutationObserver(callback);// 以上述配置开始观察目标节点
observer.observe(targetNode, config);// 之后,可停止观察
observer.disconnect();

setImmediate:

setImmediate参数设置:第一个参数是需要执行的方法,第二个参数到第n个参数是传入方法中的参数。

setImmediate表示立即执行,它是宏任务,回调函数会被放置到事件循环的check阶段。
在应用中如果大量的计算型任务,它是不适合放在主线程中执行的,因为计算任务会阻塞主线程,主线程一旦被阻塞,其他任务就需要等待,
可以通过setImmediate方法将任务放入事件循环中的check阶段,因为代码在这一个阶段执行不会阻塞主线程,也不会阻塞事件循环
 

  • 兼容性: 主要支持IE10和IE11,以及一些较旧版本的Edge浏览器。
  • 用法: setImmediate用于将函数排入宏任务队列,以便在当前任务完成后立即执行。示例:
function sleep(delay) {var start = new Date().getTime()while (new Date().getTime() - start < delay) {continue}console.log('ok')
}console.log('start')
setImmediate(sleep, 2000)
console.log('end')

先打印出start,然后再打印end,最后等待2000ms后打印ok。 

setTimeout:

  • 兼容性: 在Node.js和几乎所有现代浏览器中都支持。
  • 用法: setTimeout用于在一定时间后将函数排入宏任务队列。它是处理异步操作的常用方法。示例:
setTimeout(() => {// 这里执行宏任务
}, 1000);

异步任务---函数封装

  •  1.定义函数
  •  2.调用核心api(queueMicrotask,MutationObserver,setTimeout)
  •  3.使用封装的函数

 在then方法中使用无论promse是啥状态都需要直接或者间接的执行回调函数

/*** 异步任务--函数封装* 1.定义函数* 2.调用核心api(queueMicrotask,MutationObserver,setTimeout)* 3.使用封装的函数*///1.定义函数
function runAsyncTask(callback) {//  2.调用核心api(queueMicrotask,MutationObserver,setTimeout)if (typeof queueMicrotask === "function") {queueMicrotask(callback);} else if (typeof MutationObserver == "function") {const obs = new MutationObserver(callback);const divNode = document.createElement("div");obs.observe(divNode, { childList: true });divNode.innerHTML = "贾公子";} else {setTimeout(callback, 0);}
}const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";class MyPromise {state = PENDING;result = undefined;#handlers = [];constructor(func) {const resolve = (result) => {if (this.state == PENDING) {this.state = FULFILLED;this.result = result;this.#handlers.forEach(({ onFulfilled }) => {onFulfilled(this.result);});}};const reject = (result) => {if (this.state == PENDING) {this.state = REJECTED;this.result = result;this.#handlers.forEach(({ onRejected }) => {onRejected(this.result);});}};func(resolve, reject);}then(onFulfilled, onRejected) {onFulfilled = typeof onFulfilled === "function" ? onFulfilled : (x) => x;onRejected =typeof onRejected === "function"? onRejected: (x) => {throw x;};// 3.使用封装的函数if (this.state === FULFILLED) {runAsyncTask(() => {onFulfilled(this.result);});} else if (this.state === REJECTED) {runAsyncTask(() => {onRejected(this.result);});} else if (this.state === PENDING) {this.#handlers.push({// 成功或者失败后调用 onFulfilled// onFulfilled 执行之后调用runAsyncTask(传入:promise传入的回调)//runAsyncTask内部执行了回调 onFulfilledonFulfilled: () => {runAsyncTask(() => {onFulfilled(this.result);});},onRejected: () => {runAsyncTask(() => {onRejected(this.result);});},});}}
}// 测试代码
console.log("TOP");
const p = new MyPromise((resolve, reject) => {// resolve("success");reject("error");
});
p.then((result) => {console.log("成功回调", result);},(err) => {console.log("失败回调", err);}
);
console.log("BOTTOM");

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/150421.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GEM5 Garnet DVFS / NoC DVFS教程:ruby.clk_domain ruby.voltage_domain

简介 gem5中的 NoC部分是Garnet实现的&#xff0c;但是Garnet并没有单独的时钟域&#xff0c;而是保持ruby一致&#xff0c;要做noc的DVFS&#xff0c;便是要改ruby的 改电压 #这里只是生成一个随便变量名&#xff0c;存一下值。改是和频率一起的 userssaved_voltage_domain…

⑩⑥ 【MySQL】详解 触发器TRIGGER,协助 确保数据的完整性,日志记录,数据校验等操作。

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ 触发器 ⑩⑥ 【MySQL】触发器详解1. 什么是触发…

java:IDEA中的Scratches and Consoles

背景 IntelliJ IDEA中的Scratches and Consoles是一种临时的文件编辑环境&#xff0c;用于写一些文本内容或者代码片段。 其中&#xff0c;Scratch files拥有完整的运行和debug功能&#xff0c;这些文件需要指定编程语言类型并且指定后缀。 举例&#xff1a;调接口 可以看到…

定时关机软件哪个好?定时关机软件大盘点

在生活和工作中&#xff0c;我们可以使用定时关机软件来定时关闭电脑&#xff0c;以实现对电脑的控制。那么&#xff0c;定时关机软件哪个好呢&#xff1f;下面我们就来了解一下。 定时关机软件的作用 定时关机软件可以帮助用户在预设的时间自动关闭电脑。这对于那些需要在特…

网站被攻击怎么办?

网站被大流量攻击会造成服务器资源耗尽&#xff0c;一直到宕机崩溃&#xff0c;网站无法访问甚至被机房停用&#xff0c;时间长就导致网站排名下降&#xff0c;所以必需及时处理。下面跟大家分享服务器被大流量攻击怎么办&#xff1f;服务器攻击防护如何做&#xff1f; 一、服…

【Vue渲染】 条件渲染 | v-if | v-show | 列表渲染 | v-for

目录 前言 v-if和v-show的区别和联系 v-show和v-if如何选择 条件渲染|v-if|v-show v-if v-if v-else v-if v-else-if v-else template v-show 列表渲染|v-for v-for 前言 本文介绍Vue渲染&#xff0c;包含条件渲染v-if和v-show的区别和联系以及列表渲染v-for v-if和…

Android Studio 写一个Java调用c++ 的demo

前提条件&#xff1a; 本地已经配置好了ndk环境,如果没有配置好&#xff0c;建议参考macos 配置ndk环境-CSDN博客 这篇链接。 新建一个Empty Project 比如我这里的Project的名字是HelloJNI&#xff0c;包名是com.example.hellojni 然后在src目录下&#xff0c;右键选择Add C …

JVM虚拟机:通过日志学习PS+PO垃圾回收器

我们刚才设置参数的时候看到了-XXPrintGCDetails表示输出详细的GC处理日志&#xff0c;那么我们如何理解这个日志呢&#xff1f;日志是有规则的&#xff0c;我们需要按照这个规则来理解日志中的内容&#xff0c;它有两个格式&#xff0c;一个格式是GC的格式&#xff08;新生代&…

二叉树题目:二叉树的最近公共祖先

文章目录 题目标题和出处难度题目描述要求示例数据范围 解法一思路和算法代码复杂度分析 解法二思路和算法代码复杂度分析 题目 标题和出处 标题&#xff1a;二叉树的最近公共祖先 出处&#xff1a;236. 二叉树的最近公共祖先 难度 5 级 题目描述 要求 给定一个二叉树&…

Redis 的集群模式实现高可用

来源&#xff1a;Redis高可用&#xff1a;武林秘籍存在集群里&#xff0c;那稳了~ (qq.com) 1. 引言 前面我们已经聊过 Redis 的主从同步&#xff08;复制&#xff09;和哨兵机制&#xff0c;这期我们来聊 Redis 的集群模式。 但是在超大规模的互联网应用中&#xff0c;业务规…

2023年Java核心技术大会(Core Java Week 2023)-核心PPT资料下载

一、峰会简介 人工智能在22年、23年的再次爆发让Python成为编程语言里最大的赢家&#xff1b;云原生的持续普及令Go、Rust等新生的语言有了进一步叫板传统技术体系的资本与底气。我们必须承认在近几年里&#xff0c;Java阵营的确受到了前所未有的挑战&#xff0c;出现了更多更…

机器视觉系统选型-定光照强度

同一个外形结构的光源&#xff0c;光照强度受如下影响&#xff1a; 单颗灯珠的亮度灯珠排列的数量和密度漫射板/防护板的材质&#xff08;透明、半透明、全漫射&#xff09; 在合理范围内提升光照强度&#xff0c;可降低对相机曝光时长的要求 外形结构尺寸相同的两款光源&am…

Mac电脑VSCode配置PHP开发环境

1.安装 PHP 首先&#xff0c;打开终端&#xff0c;安装 Homebrew&#xff0c;输入如下命令&#xff1a; $ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" 安装了 Homebrew 之后&#xff0c;你可以使用下面的…

基于C++实现循环赛日程表(分治算法)

一、问题描叙 设有n2^k个运动员&#xff0c;要进行网球循环赛。现在要设计一个满足以下要求的比赛日程表 每个选手必须与其他n-1个选手各赛一场每个选手一天只能赛一次循环赛一共进行n-1天 二、问题分析 按此要求可将比赛日程表设计成n行n-1列的表&#xff0c;在表中第 i 行…

uniapp中使用render.js进行openers、arcgis等地图操作

uniapp中使用render.js进行openers、arcgis等地图操作 一、为啥需要render.js render.js主要作用于APP上&#xff0c;因为Uniapp本质为vuejshtml进行开发&#xff0c;整个技术栈还是H5&#xff0c;对DOM元素进行操作。而APP中没用Dom元素这个概念。因此利用render.js这个视图层…

NX二次开发UF_CAM_ask_cam_preferences 函数介绍

文章作者&#xff1a;里海 来源网站&#xff1a;里海NX二次开发3000例专栏 UF_CAM_ask_cam_preferences Defined in: uf_cam.h int UF_CAM_ask_cam_preferences(UF_CAM_preferences_p_t prefs ) overview 概述 This function provides the current settings of the CAM pre…

【Linux】安全审计-audit

文章目录 一、audit简介二、开启auditd服务三、相关文件四、审计规则五、审计日志查询及分析附录1&#xff1a;auditctl -h附录2&#xff1a;systemcall 类型 参考文章&#xff1a; 1、安全-linux audit审计使用入门 2、audit详细使用配置 3、Linux-有哪些常见的System Call&a…

优步让一切人工智能化

优步(Uber)的商业模式建立在对数据的颠覆性使用上--通过将双方智能手机的位置数据关联起来&#xff0c;将出租车司机与乘客配对。这意味着&#xff0c;它可以比传统出租车公司更快地安排司机去接乘客&#xff0c;极大地冲击了传统出租车公司的业务。 优步自成立以来&#xff0…

【Linux】-进程间通信-命名管道文件(没有关系的进程间进行通信),以及写一个日志模板

&#x1f496;作者&#xff1a;小树苗渴望变成参天大树&#x1f388; &#x1f389;作者宣言&#xff1a;认真写好每一篇博客&#x1f4a4; &#x1f38a;作者gitee:gitee✨ &#x1f49e;作者专栏&#xff1a;C语言,数据结构初阶,Linux,C 动态规划算法&#x1f384; 如 果 你 …

Vue3.0和2.0语法不同分析

前言&#xff1a;本篇文章只做VUE3.0和VUE2.0语法上的不同分析&#xff0c;不做性能和源码架构等的分析。 一、VUE3.0和VUE2.0代码结构不同 VUE3.0代码实例 <template><div><span>count is {{ count }}</span><span>plusOne is {{ plusOne }}…