vue 将字符串最后一个字符给替换_基于React和Vue构建了同款应用,来看看哪里不一样...

2023-11-03

作者|Sunil Sandhu

译者|王强

编辑|王文婧

我阅读了很多 React 文档并观看了一些教学视频,它们的确很棒,但我真正想知道的是 React 与 Vue 有何不同。我所说的“不同”并不是它们是否都有虚拟 DOM,或者它们是怎样渲染页面之类的问题。我希望的是有人从代码层面给出解释。我希望能有一篇文章涵盖这样的内容,帮助那些对 Vue 或 React(乃至整个 Web 开发工作)都不熟悉的人更好地理解两者之间的区别。

可惜我找不到现成的答案。因此我意识到我得自己动手解决这个问题才能看清楚两者之间的异同。于是我记录下了整个对比过程,终于完成了这样一篇文章,填补了这方面的空白。

哪个更好看?

我决定尝试构建一款比较典型的 To Do 类应用,允许用户在列表中添加和删除项目。两款应用都是使用默认 CLI 构建的(React 用 create-react-app,Vue 则是 vue-cli)。顺带一提,CLI 的意思是命令行界面。

好了,开头的部分比我想象的还要长,我们可以切入正题了。先来大致看一下两款应用的外观:

React vs Vue。不可移动的对象遇到了不可抗拒的力量!

两个应用程序的 CSS 代码完全相同,但代码所处的位置有所不同。记住这一点,接下来让我们看一下两个应用程序的文件结构:

你会发现它们的结构也几乎相同。唯一的区别是 React 应用有三个 CSS 文件,而 Vue 应用没有任何 CSS 文件。这是因为在 create-react-app 中,每个 React 组件都会附带一个文件来保存其样式,而 Vue CLI 采用了一种 包含式 的方法,具体来说是在组件文件中声明样式。

最后他们俩都达成了同样的目标,也没什么可多说的,因为在 React 或 Vue 中你都不能改变 CSS 的结构。这确实取决于个人喜好。开发人员社区关于 CSS 的结构化方式这个话题有大量的讨论,尤其是 React 这块,因为有许多 CSS-in-JS 解决方案,诸如样式组件和 emotion 等。顺便说一句,CSS-in-JS 就是字面上的意思。虽然这些都很有用,但这里我们只用两边的 CLI 给出的结构。

在进一步深入之前,我们先来看一下典型的 Vue 和 React 组件长什么样:

左边是 React,右边是 Vue。

看过之后我们来深入了解细节吧!

我们如何突变数据?

首先,“突变数据”到底是什么意思呢?听起来是不是有点高深?其实它基本上就是指更改我们已存储的数据。如果我们想将一个人名的值从 John 更改为 Mark,我们就是在“突变“这份数据。这就是 React 和 Vue 之间的关键区别所在。Vue 本质上创建了一个数据对象,可以在其中自由更新数据,而 React 通过所谓的状态 hook 来处理数据突变。

从下面的图片中可以看到两者的设置,然后我们会具体说明:

左边是 React,右边是 Vue。

于是你看到我们将相同的数据传递给了两者,但是各自的结构有所不同。

在 Vue 中,通常会将组件的所有可变数据放置在 data() 函数内,该函数返回一个对象,其中包含你的数据。

在 React 中,至少从 2019 年开始,我们一般会通过一系列 Hooks 处理状态。你可能以前没接触过这种概念,一开始它看起来可能有点奇怪。它的工作机制基本上是这个样子:假设我们要创建一个待办事项列表,我们可能需要创建一个名为 list 的变量,它可能需要一个由字符串或对象组成的数组(比如说给每个 todo 字符串一个 ID 或其他一些东西)。我们需要写的代码是 const [list, setList] = useState([])。这里我们用的就是 React 里面的 Hook,称为 useState。它本质上是让我们能够在组件中保留局部状态。

另外,你可能已经注意到我们在 useState() 内部传入了一个空数组 []。放在其中的是我们希望 list 最初设置的内容,这里我们希望是一个空数组。但从上图可以看到,我们在数组内传入了一些数据,这些数据最后成了 list 的初始化数据。想知道 setList 是做什么的?稍后会进一步说明!

如何在应用程序中引用可变数据?

假设我们有一些数据名为 name,被分配了“Sunil”值。

在 Vue 中,这部分内容位于 data() 对象内部,写成 name: ‘Sunil'。在我们的应用程序中,我们将调用 this.name 来引用它。我们还可以调用 this.name = 'John'来更新它,把我的名字改为 John。

在 React 中,由于我们使用 useState() 创建了较小的状态,因此很可能已经用 const [name, setName] = useState('Sunil') 创建了一些东西。在应用程序中,我们将简单地调用 name 来引用同一段数据。这里的主要区别在于我们不能简单地写上 name = 'John',因为 React 有一些限制来预防这种简单且无所顾忌的突变。在 React 中,我们要写成 setName('John')。这里用到了 setName。在 const [name, setName] = useState('Sunil') 中,它创建两个变量,一个变量变为 const name = 'Sunil',而第二个 const setName 被分配了一个函数,该函数使 name 可以用新值重新创建。

实际上,React 和 Vue 在这里做的是同样的事情,也就是创建可以更新的数据。Vue 本质上会在每次更新一条数据时默认结合它自己的 name 和 setName 版本。简单来说,React 要求你使用内部值调用 setName() 来更新状态,而如果你曾尝试更新数据对象内部的值,Vue 就会假设你要这么做。那么为什么 React 会费劲地将值与函数分开,还要使用 useState() 呢?这里引用 Revanth Kumar 的解释:

“这是因为当状态改变时,React 希望重新运行某些生命周期 hooks。当你调用 useState 函数时,它将知道状态已更改。如果你直接改变状态,React 将不得不做更多的工作来跟踪更改以及要运行的生命周期 hooks 等。因此为了简单起见,React 使用 useState。”

Bean 最懂了。

现在我们已经搞明白了数据突变,接下来看看在两个 To Do 应用中添加新项目的方法。

如何创建新的待办事项?

React:

const createNewToDoItem = () => { const newId = Math.max.apply(null, list.map((t) => t.id)) + 1 const newToDo = { id: newId, text: toDo }; setList([...list, newToDo]); setToDo("");};

在 React 中,我们的输入字段有一个名为 value 的属性。每次通过 onChange 事件侦听器更改它的值时,都会自动更新此值。JSX(基本上是 HTML 的变体)如下所示:

每次更改值时,它都会更新状态。handleInput 函数如下所示:

const handleInput = (e) => { setToDo(e.target.value);};

现在,每当用户按下页面上的 + 按钮添加新项目时,都会触发 createNewToDoItem 函数。我们再来看一下这个函数,搞清楚具体发生了什么:

const createNewToDoItem = () => { const newId = Math.max.apply(null, list.map((t) => t.id)) + 1 const newToDo = { id: newId, text: toDo }; setList([...list, newToDo]); setToDo("");};

本质上,newId 函数是在创建一个新 ID,该 ID 将提供给我们的新 toDo 项目。newToDo 变量是一个对象,有一个 id 键,其值由 newID 确定。它还有一个 text 键,其值由 toDo 确定。这个 toDo 就是输入值更改时要更新的那个 toDo。

setList 函数到此为止,然后我们传入一个包含整个 list 以及新创建的 newToDo 的数组。

你可能觉得…list 看起来很奇怪:开头的三个点称为散布运算符,负责将 list 中的所有值作为单独的项目传递,而不是简单地把所有项目打包在一起作为数组传递。感觉有些糊涂吗?那我强烈建议你仔细阅读散布运算符的相关介绍,因为它很有用!

最后我们运行 setToDo() 并传入一个空字符串。这样我们的输入值为空,可以输入新的 toDo 了。

Vue:

createNewToDoItem() { const newId = Math.max.apply(null, this.list.map(t => t.id)) + 1; this.list.push({ id: newId, text: this.todo }); this.todo = "";}

在 Vue 中,我们的 input 字段有一个称为 v-model 的句柄。这使我们能够执行称为 双向绑定 的操作。下面来看一下 input 字段,搞清楚到底发生了什么:

V-Model 将这个字段的输入与我们在数据对象 toDoItem 中的键相关联。页面加载后,我们必须将 toDoItem 设置为空字符串,例如:todo:''。如果其中已经有一些数据,例如 todo: ‘add some text here’,则我们的输入字段将加载输入字段内已有的 add some text here。那么输入字段为空时,无论我们在输入字段中键入什么文本都将绑定到 todo 的值。这实际上是双向绑定(输入字段可以更新数据对象,反过来数据对象也可以更新输入字段)。

回顾一下前面的 createNewToDoItem**()代码块,可以看到,我们将todo的内容推送到list数组中,然后将todo** 更新为空字符串。

我们还使用了与 React 示例中相同的 newId() 函数。

如何从列表中删除项目?

React:

const deleteItem = (item) => { setList(list.filter((todo) => todo !== item));};

因为 deleteItem() 函数位于 ToDo.js 内,我可以很容易地在 ToDoItem.js 里引用它,首先将 deleteItem**()函数作为** 的 prop,如下所示:

这里首先将该函数传递下去,使其能被子级访问。然后在 ToDoItem 组件内执行以下操作:

 deleteItem(item)}> - 

我要引用位于父组件内的函数,只需引用 props.deleteItem。你可能发现在代码示例中,我们只写了 deleteItem,而不是 props.deleteItem。这是因为我们使用了一种称为 解构 的技术,该技术允许我们获取 props 对象的一部分并将其分配给变量。因此在我们的ToDoItem.js 文件中有以下内容:

const ToDoItem = (props) => { const { item, deleteItem } = props;}

这为我们创建了两个变量,其中一个称为 item,它被赋予与 props.item 相同的值,而 deleteItem 则根据 props.deleteItem 赋值。我们也可以简单地使用 props.item 和 props.deleteItem 来避免解构的操作,但我认为这里值得单独介绍一下!

Vue:

onDeleteItem(item){ this.list = this.list.filter(todo => todo !== item);}

Vue 需要的方法稍微有一些不同。这里我们必须做三件事:

首先,在我们要调用函数的元素上:

-

然后我们必须在子组件(在本例中为 ToDoItem.vue)中创建一个 emit 函数作为方法,如下所示:

deleteItem(item) { this.$emit('delete', item)}

与此同时你会发现,当我们在 ToDo.vue 中添加 ToDoItem.vue 时,我们实际上引用了一个 函数

这就是所谓的自定义事件侦听器。它会侦听使用字符串“delete”触发 emit 的所有情况。如果听到此消息,它将触发一个名为 onDeleteItem 的函数。此函数位于 ToDo.vue 内部,而不是在 ToDoItem.vue 中。如前所述,此函数仅过 滤 data 对象 内的 todo 数组 即可删除单击的项目。

在这里还需注意的是,在 Vue 示例中,我可以简单地将 $emit 部分写在 @click 监听器中,如下所示:

-

这样就能把步骤从 3 步减少到 2 步,选哪个完全取决于个人喜好。

简而言之,React 中的子组件可以通过 props 来访问父函数(前提是你要向下传递 props,这是相当标准的做法,其他 React 工作中也非常常见);而在 Vue 中,你需要从子级发射事件,这些事件通常会在父组件内部回收。

怎样传递事件侦听器?

React:

针对简单事件(例如单击事件)的事件侦听器很好做。下面是为创建新的 ToDo 项目的按钮创建 click 事件的示例:

+
.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

vue 将字符串最后一个字符给替换_基于React和Vue构建了同款应用,来看看哪里不一样... 的相关文章

  • iview—Table表格render 渲染

    1 序号 2 if判断 a标签 3 if判断 Input输入 4 renderHeader自定义列头的点击事件 render的Input点击事件 nativeOn click 5 正常列 6 按钮Button 7 复选框Checkbox 8
  • VSCode 远程开发:WLS 2 + ZeroTier 内网穿透

    前置条件 两台 Win 10 主机 其中一台 记为本地机 远程访问另一台主机 记为远程机 的 WSL 本地机安装好 VSCode 两台主机不在一个局域网内 且均无公网 IP 后续需要在两台主机上配置内网穿透 如果两台主机可相互 ping 通
  • Java 数据库编程 ResultSet 的 使用方法

    结果集 ResultSet 是数据中查询结果返回的一种对象 可以说结果集是一个存储查询结果的对象 但是结果集并不仅仅具有存储的功能 他同时还具有操纵数据的功能 可能完成对数据的更新等 结果集读取数据的方法主要是getXXX 他的参数可以使整
  • C++ string替换指定字符

    string自带replace 方法并没有实现这一功能 需要借助
  • git commit时权限被否定问题解决

    今天在提交博客时 git commit m 时出现了一些问题 问题如下 could not open git COMMIT EDITMSG Permission denied 意思大概就是无法打开 git COMMIT EDITMSG 权限
  • Java8 HashMap底层原理

    一 树集结构 1 1二叉查找树 二叉查找树 BST 具备什么特性呢 1 左子树上所有结点的值均小于或等于它的根结点的值 2 右子树上所有结点的值均大于或等于它的根结点的值 3 左 右子树也分别为二叉排序树 查找效率 二叉查找树查找的最大次数
  • Macbook配置工作环境

    Xcode 在App Store中搜索Xcode 下载安装 安装包大概6G 无需配置 直接App Store中安装即可 速度取决于网速 iterm2 mac下较好用的终端 下载地址 使用和配置文档参照 https iterm2 com in
  • Docker+Linux_Centos(内核:3.10.0-957.1.3.el7.x86_64)安装

    前言声明 如果您有更好的技术与作者分享 或者商业合作 请访问作者个人网站 http www esqabc com view message html 留言给作者 如果该案例触犯您的专利 请在这里 http www esqabc com vi
  • DBSCAN算法研究(2)--matlab代码实现

    DBSCAN聚类算法三部分 1 DBSCAN原理 流程 参数设置 优缺点以及算法 http blog csdn net zhouxianen1987 article details 68945844 2 matlab代码实现 blog ht
  • Python、Java的一些区别

    共同点 二者都是面向对象的编程语言 二者都是解释型语言 说明 解释型语言释义 程序不需要编译 而是在运行时一句一句翻译成机器语言 每运行一次都要翻译一次 所以效率相比较低 不同点 Python是弱类型语言 而Java是强类型语言 说明 强类
  • Vue 父组件中触发子组件的方法

    Vue 父组件中触发子组件的方法 使用场景 在父组件点击子组件时 触发子组件的初始化方法 方式一 子组件中使用 ref 属性
  • arch linux windows,使用ArchWSL在微软Windows WSL上运行Arch Linux系统

    本文教您在微软Windows WSL上运行Arch Linux系统的方法 ArchWSL使ArchLinux作为WSL实例 支持多次安装 本文操作步骤为 安装用于Linux的Windows子系统 前往GitHub下载ArchWSL 解压缩下
  • 哈夫曼树实现文件的压缩与解压缩

    利用哈夫曼树实现文件的压缩与解压缩 压缩 1 统计出文件中相同字符出现的次数 2 获取哈夫曼编码 次数作为权值构建哈夫曼树 3 重新编码 写回压缩文件 保存头文件 源文件后缀 编码信息的行数 每个字符的权 保存编码 解压缩 1 获取原文件后
  • 超详细Shell学习教程第三篇

    1 1shell脚本创建 下面讲解创建shell脚本 并赋予脚本可执行权限 写一个脚本实现创建文件夹 如果文件夹不存在 mkdir sh if d html then mkdir html elif d html1 then mkdir h
  • 比较快速排序和归并排序

    虽然归并排序和快速排序的时间复杂度都为O nlogn 但实际上快速排序的速度会比归并排序快2 3倍 原因如下 1 归并排序在执行时 需要一个额外的temp数组去拷贝原数组的数据 会大量占用程序的空间 2 快速排序再运行时 实际上是直接再原数
  • 信息安全之SQL注入攻击

    目录 一 简介 二 案例 1 案例1 SQL恶意填入 2 案例2 危险字符注入 三 预防 1 过滤特殊字符 2 严格使用参数绑定 3 合理使用框架防注入机制 一 简介 SQL注入是注入式攻击中的常见类型 SQL注入式攻击是未将代码与数据进行
  • 【计蒜客——复赛A题】贝壳找房函数最值

    题意 对于结构 f x ax b 这样的一次函数 我们要做的就是 对 fi fj x ai ajx bj bi 这样的可换序嵌套函数求它的最大值f f f f x 接下来先分享一下令我忧伤的WA让大家快乐一下 include
  • mobx操作详解

    在操作mobx之前首先你得先了解一下mobx是用来干嘛的 mobx官网 https cn mobx js org 其次拥有自己得一个react mobx项目 前几天发了一次项目创建流程 1 src 创建store js用来存放数据 impo
  • 用crt远程linux提示密码错误,SecureCRT ssh连接一直提示密码错误

    遇到在密码正确的情况下ssh密码不对 最后一种是我遇到的问题上面的是网上大家遇到的总结一下 我的问题是selinux没有关闭 被改动了配置 1 权限问题 ssh目录 以及 home 当前用户 需要700权限 参考以下操作调整 sudo ch

随机推荐

  • 机器学习入门先知

    选择机器学习的原因 如果你已经读到了硕士还在做普通的编程开发 不涉及高等数学知识 那么感觉这个知识是不是浪费了 会有不甘心的 和大学生 培训出来的童鞋有什么差别呢 所以 为了知识不浪费 拿高薪 做高级程序员 机器学习是个很好的跳板 机器学习
  • CRMEB电商商城系统腾讯云ECS服务器安装配置搭建教程文档

    一 推荐使用宝塔Linux面板 简单好用 二 放行服务器端口 详细步骤 1 登录腾讯云服务器 点击右上角 控制台 2 我的资源 点击进入云服务器 3 进入实例列表 选择您要安装的服务器 点击更多 4 选择重装系统 5 如果您的服务器有数据
  • thinkphp5 ajax如何返回json

    刚用thinkphp5 不知道怎么返回json 参考这个文章 收藏一下 thinkphp5 ajax如何返回json 使用thinkphp框架开发 不知道如何返回JSON字符串 ajax无法调用 有两种方式可以返回 1 若是数据库实体 可以
  • react的深度解析: 状态提升

    在react中是单向数据流的设计 即 只有父组件可以传递数据给子组件 而没有子组件传递数据给父组件的概念 以正确的技术说明 是 拥有者组件 可以设置 被拥有者组件 中的资料 也就是主人与仆人的关系 那么子组件要传递数据给父组件该如何沟通呢
  • 微信小程序开发-001 注册以及开发工具的安装与绑定

    学习目标 快速入门小程序开发 学习内容 1 申请帐号 2 登录 小程序后台 3 获取自己的APP ID 4 下载微信开发者工具 5 开发者工具的使用 学习时间 2022 2 17 学习产出 1 申请帐号 进入小程序注册页 根据指引填写信息和
  • 刷脸支付与我们的生活越来越密不可分

    随着支付宝 微信刷脸支付产品的迭代升级 以及补贴政策的加码 越来越多的刷脸支付进入了这个风口 移动支付革命刷脸支付为创业者提供新机遇 从蜻蜓 青蛙到蓝鲸 从支付宝微信到银联 官方 服务商 加盟的刷脸支付代理以及商户 支撑起这场支付革命 给刷
  • 带你“手撕代码”,了解基本原理实现

    文章目录 前言 常见的 手撕代码 都是高频题哦 curry 柯里化 compose 函数组合 pipe 函数管道 throttle 函数节流 debounce 函数防抖 formatMoney 千分位 deepClone 深拷贝 模拟ins
  • IAR和KEIL调试工具栏的debug快捷键

    IAR Reset复位 Break停止运行 Step Over逐步运行 F10 Step Into跳入运行 F11 Step Out跳出运行 F11 Go全速运行 F5 Stop Debugging停止调试 Ctrl Shift D Mak
  • Python 常用第三方包介绍及相关使用方法汇总

    转自 https www cnblogs com wf linux archive 2018 08 01 9400354 html
  • tesseract-ocr3.02字符识别过程操作步骤

    1 从http code google com p tesseract ocr downloads list下载tesseract ocr 3 02 vs2008 tesseract ocr 3 02 chi sim tar tessera
  • Scrapy中selenium的使用

    场景1 项目中有多个爬虫时 将driver对象的初始化放在各个spider中 usr bin env python coding UTF 8 author carry time 2019 6 19 15 56 desc import scr
  • c语言输出26个小写英文字母,c语言题。 按顺序打印输出26个英文字母,

    includeint main int i for i 0 i lt 26 i printf c i A for i 0 i lt 26 i printf c i a return 0 扩展资料 ASCII American Standar
  • C++分文件编写类

    C 分文件编写类 分文件编写函数 分文件编写类 C 快捷键 其编写模式就是之前的分文件编写函数 分文件编写函数 头 函数 主函数调用 分文件编写类 头 声明 类中的函数定义 调用 C 快捷键 Alt Enther快速转到代码段的位置
  • vue.js 使用axios实现下载功能

    本文主要来源于知乎一个回答 这里红色部分做了自己的处理 虽然自己的少 可是很有用的几句代码哦 只好回答一下axios如何拦截get请求并下载文件的了 Ajax无法下载文件的原因 浏览器的GET frame a 和POST form 请求具有
  • 联想小新触摸板驱动_联想lenovo笔记本触摸板驱动-联想触摸驱动 win7版下载16.2.5.0 官方版-西西软件下载...

    联想笔记本win下的触摸驱动 Fn F8组合键 笔者笔记本是联想的 可通过此法关闭触控板 如遇到个别笔记本电脑通过此方法不能关闭触摸板 另外个别笔记本也提供了关闭触摸板的快捷键 详细信息需要提供具体型号核实 笔记本上的触摸板怎么锁定 在打字
  • Mysql 主从从级联复制

    需求 三个服务器A gt B gt C级联主从 版本 数据库 mysql 5 6 64bit binary install 操作系统 redhat 6 4 x86 64bit Master 192 168 0 186 gt 主节点 slav
  • javascript 连接 mqtt

    javascript 连接 mqtt mqtt 服务需支持websocket连接 基于 mqttws31 js 及 MqttX js var mqttOpts id 123456789 host d iyanhong com port 90
  • vue中全局配置sass变量或者方法

    1 vue cli3 0中 在vue config js文件中设置如下代码 module exports css loaderOptions 给 sass loader 传递选项 sass 是 src 的别名 所以这里假设你有 src va
  • Mysql - 配置Mysql主从复制-keepalived高可用-读写分离集群

    目录 高可用 为什么需要高可用呢 高可用的主要作用 keepalived是什么 它用在哪里 什么是VRRP协议 它的作用是什么 搭建一个基于keepalived的高可用Mysql主从复制读写分离集群 一 项目中的IP地址配置表 二 项目拓扑
  • vue 将字符串最后一个字符给替换_基于React和Vue构建了同款应用,来看看哪里不一样...

    作者 Sunil Sandhu 译者 王强 编辑 王文婧 我阅读了很多 React 文档并观看了一些教学视频 它们的确很棒 但我真正想知道的是 React 与 Vue 有何不同 我所说的 不同 并不是它们是否都有虚拟 DOM 或者它们是怎样