vue完全编程方式与react在书写和运用上的异同

在构建html元素时,vue倾向于模板方式,而react则完全使用javascript的编程能力,但vue也具备完全编程的能力(与react一样使用JSX和createElement渲染函数)。所以,当vue使用完全编程方式时,与react可以说是大同小异。

学习react的时候,有一个核心思想:组件就是函数,元素就是值。这对于vue来说也是完全适用的,唯一的区别在于两者的限制和使用条件不同。

目录

  • JSX
  • 元素渲染
  • 组件定义
  • 组件传值
  • 内容分发
  • 数据响应
  • 事件处理

JSX

JSX是JavaScript的一个扩展语法,本质是createElement渲染函数的语法糖。react和vue在JSX语法上几乎一致,区别在于属性值的传入上。

react的JSX语法更接近 JavaScript 而不是 HTML,所以 React DOM 使用 camelCase(小驼峰命名)来定义属性的名称,而不使用 HTML 属性名称的命名约定。
例如,JSX 里的 class 变成了 className,而 tabindex 则变为 tabIndex

vue的JSX则使用了一个Babel 插件使其更贴近HTML模板语法,vue对大小写不敏感(实际上vue会将所有属性值转换为小写)。
例如,tabIndex会转化成tabindexclassName会转化为classname

特例,对于属性class,react应写成className,vue应写成class

react引入了Fragments使得react可以有多个根元素,vue没有此功能,只能是单一根元素

元素渲染

react的文档中提到了

元素是构成 React 应用的最小砖块。

const element = <h1>Hello, world</h1> // 定义元素...
render () {return <div>{element}</div> // 使用元素
}

react将元素当作值来对待,你可以直接使用,也可以先赋值给某个变量,然后再使用。
这一点在vue的文档中虽然没有明确提到,但依然适用,vue也可以先将元素赋值给某个变量,然后在适当的位置使用该变量。

两者在使用时的区别在于:

  • react可以在任意位置(组件内和组件外)定义元素并使用
  • vue只能在组件内定义元素(只要是组件内,任意位置都可以,render函数内,data数据或者其他位置),在组件外定义则会报错(h is not defined

报错原因:网上找到的一个说法是vue中组件外没有上下文联系,找不到渲染函数。
思来想去只能归结于两者的渲染机制不同(没有依据,瞎猜的😜:react可能是先赋值后渲染,vue可能是先渲染后赋值)

组件定义

react定义组件有两种方式,函数组件和class组件,两者在一定条件下可以相互转换,函数式组件是无状态组件,没有state状态和生命周期

// 函数组件
cosnt MyComponent = props => {return <div>{props.title}</div>
}// class组件
class MyComponent extends React.Component {static defaultProps = {} // 设置默认传入值constructor(props) {super()this.state = {} // 设置状态值}... // 其他组件函数:自定义方法,生命周期方法...render() {return <div>{this.props.title}</div>}
}

vue文档给出的组件定义只有一种方式(如下),函数式组件(无状态)是在普通组件的基础上添加functional标记

Vue.component('my-component', {props: {title:String},...render () {return <div>{this.title}</div>}
})

实际上,上诉方式是官方给出的一种完整使用(组件定义和全局注册),在实际项目中通常组件定义和注册都是分开的(即组件的局部注册)。

而react没有组件注册这一说法,只有定义和使用,vue实际上也可以和react一样,直接定义并使用,前提是使用JSX语法,如果使用createElement渲染函数和模板方式,仍然需要进行组件注册。

vue定义组件方式如下

// 函数式组件
const MyComponent = {functional: true, // 函数式组件标记,props: {title:String},  // 设置传入值// 为了弥补缺少的实例,提供第二个参数作为上下文render(h, context) {return <div>{this.props.title}</div>}
}
// 函数式组件的变种写法 -- 函数方式,对照了react的函数组件的写法
// vue官方文档中没有提到这种写法,但这种写法依然生效
// 与react函数式组件的不同之处在于,react函数式组件的传入值是props,vue函数组件传入值是context上下文
cosnt MyComponent = context => {return <div>{context.props.title}</div>
}// 普通组件
const MyComponent = {props: {title:String},  // 设置传入值data () { return { user: '' } }, // 数据computed: {}, // 计算属性watch: {}, // 监听属性methods: {}, // 自定义方法... // 其他生命周期方法,钩子函数等...render() {return <div>{this.props.title}</div>}
}

从上面react和vue的代码片段中可以看出,react定义组件用的是class对象,vue定义组件用的是Object对象,两者的区别在于:

  • class对象方法之间不需要分隔符,Object对象的属性之间需要逗号,分隔
  • 对于传入值,两者都是使用的props,react只能定义默认值,vue则可以限制传入类型并进行数据验证(react要实现类型验证需要引入prop-types
  • 对于状态值,react将状态值放入class对象的属性值state里,并在constructor构造函数中完成数据初始化,vue则将状态值放入data方法的返回值中
  • 对于自定义方法,react可直接书写在class对象下,vue则必需放入methods字段中
  • 数据监听,react在生命周期方法componentDidUpdate中监听数据变化,vue则提供了更为方便的computedwatch

组件传值

react和vue的组件传值都是通过组件属性进行传递的。

  • react,不管是函数式组件还是普通组件,将组件的所有属性都当作prop传入;
  • vue,对于函数式组件
    • 版本2.3.0之前,如果一个函数式组件想要接收 prop,则 props 选项是必须的;
    • 版本2.3.0或以上,如果定义了props选项,则只能接收定义的prop
    • 版本2.3.0或以上,如果省略 props 选项,组件上所有的 attribute 都会被自动隐式解析为 prop
  • vue,对于普通组件
    • 特殊属性class、style,直接挂载到组件根元素上,与组件内的class和style叠加合并;
    • 组件上的属性如果在props中的定义了,则作为prop传入;
    • 对于没有声明的属性,默认自动挂载到组件根元素上,并覆盖原来的属性值(可通过设置inheritAttrs属性开关此功能,默认开启);

内容分发

说完组件传值,那就不得不说组件的内容分发,这是一种特殊的组件传值(其本质还是组件传值)。
在vue中,内容分发使用的是插槽slot,react则称为组件组合,并且react特意强调了

React 中没有“槽”这一概念的限制,你可以将任何东西作为 props 进行传递

最常见的就是如下以子节点(children)方式

<MyComponent>hello world</MyComponent>
  • react提供了一个特殊的children prop用来接收分发内容,
  • vue函数式组件即可以通过children来接收内容,也可以通过slots().default方式,
  • vue普通组件只能通过$slots.default的方式分发

vue函数式组件和普通组件对插槽slot使用的区别主要式因为函数式组件没有实列this,而是使用上下文context,详见vue函数式组件
vue的插槽分为普通插槽slots和作用域插槽scopedSlots,作用域插槽可以完全替代普通插槽,建议使用使用scopedSlots

简单的示列如下

// react 函数式组件
const MyComponent = props => {return <div>{props.children}</div>
}
// react class组件
class MyComponent extends React.Component {render() {return <div>{this.props.children}</div>}
}// vue 函数式组件
const MyComponent = context => {// children方式分发const { children } = contextreturn <div>{children}</div>// 通过插槽方式分发// const { slots } = context// return <div>{slots().default}</div>
}
// vue 普通组件
const MyComponent = {render () {return <div>{this.$scopedSlots.default()}</div>}
}

多内容分发

  • react只需要传入对应的prop即可
  • vue使用slotsscopedSlots进行分发
// react
...render () {return (<div><header>{props.header}</header><main>{props.children}</main><footer>{props.footer}</footer></div>)}
...
// react使用
<MyComponentheader='hello world'chilren={<p>Lorem ipsum dolor sit amet</p>}footer='this is footer'
/>// vue
...render () {return (<div><header>{this.$scopedSlots.header()}</header><main>{this.$scopedSlots.default()}</main><footer>{this.$scopedSlots.footer()}</footer></div>)}
...
// vue使用
<MyComponentscopedSlots={{    header: props => `hello, world`,default: props => <p>Lorem ipsum dolor sit amet</p>,footer: props => 'this is footer'}}
/>

对于内容分发,react显得十分灵活及简便,vue在使用上相对有部分限制,vue可以使用作用域插槽,react只能通过其他方式实现类似功能。vue插槽的JSX使用方式

实际上,如果vue不使用插槽方式,改用props也可以和react一样实现内容分发

// vue 使用 props 实现了内容分发,定义和使用方式和 react 几乎一样
const MyComponent = {props: ['header', 'children', 'footer'],render () {return (<div><header>{this.header}</header><main>{this.children}</main><footer>{this.footer}</footer></div>)}
}export default {render () {return (<MyComponentheader='hello, world'children={<p>Lorem ipsum dolor sit amet</p>}footer={'this is footer'}/>)}
}

数据响应

响应式数据更新方式是vue与react的一个重要区别之一

  • vue的数据加入到响应式系统中,直接操作数据会同步更新视图
  • react必需使用setState方法更新数据以便实现视图的同步更新

事件处理

react的事件处理为了在回调中使用 this,必须为该方法绑定this(在构造函数中绑定或在事件处理程序传递参数),vue则不需要这个绑定过程。

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

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

相关文章

Solr 配置文件之schema.xml

schema.xml这个配置文件的根本目的是为了通过配置告诉Solr怎样建立索引。solr的数据结构例如以下&#xff1a;document&#xff1a;一个文档、一条记录 field&#xff1a;域、属性solr通过搜索某个或某些field&#xff0c;返回若干个符合条件的document。或者按搜索的score排序…

wget整站抓取、网站抓取功能;下载整个网站;下载网站到本地

wget -r -p -np -k -E http://www.xxx.com 抓取整站 wget -l 1 -p -np -k http://www.xxx.com 抓取第一级 -r 递归抓取-k 抓取之后修正链接&#xff0c;适合本地浏览 http://blog.sina.com.cn/s/blog_669fb0c3010137bq.html wget -m -e robotsoff -k -E "http://…

Git标签tag及tag远程同步

Git给某个历史版本打上标签&#xff0c;这样我们可以快速的众多历史版本中找到自己需要的版本&#xff0c;一般打标签的版本都是发布版本&#xff0c;例如v1.0.0 标签操作 创建标签 # 轻量标签 git tag tagname eg: git tag v1.4# 附注标签 git tag -a tagname -m tag descr…

妙用SQL Server聚合函数和子查询迭代求和

先看看下面的表和其中的数据&#xff1a;t_product该表有两个字段&#xff1a;xh和price&#xff0c; 其中xh是主索引字段&#xff0c;现在要得到如下的查询结果&#xff1a;从上面的查询结果可以看出&#xff0c;totalprice字段值的规则是从第1条记录到当前记录的price之和。如…

记一次.NET某工控图片上传CPU爆高分析

一&#xff1a;背景 1.讲故事今天给大家带来一个入门级的 CPU 爆高案例&#xff0c;前段时间有位朋友找到我&#xff0c;说他的程序间歇性的 CPU 爆高&#xff0c;不知道是啥情况&#xff0c;让我帮忙看下&#xff0c;既然找到我&#xff0c;那就用 WinDbg 看一下。二&#xff…

微信小程序项目实践准备工作

微信小程序项目实践准备工作一、了解微信小程序产品定位及功能介绍微信小程序是一种全新的连接用户与服务的方式&#xff0c;它可以在微信内被便捷地获取和传播&#xff0c;同时具有出色的使用体验。简单的说&#xff0c;小程序是微信附属产品&#xff0c;需要依赖微信&#xf…

VSCode 用户自定义片段 snippet 基本语法说明

先上一个官方模板&#xff1a; "Print to console": {"prefix": "log","body": ["console.log($1);","$2"],"description": "Log output to console" }prefix 前缀&#xff0c;emmet 触发条…

Python集合和函数

深浅拷贝&#xff1a;.copy()方法&#xff0c;浅拷贝值拷贝一层。列表中的列表和字典会深拷贝&#xff0c;其他类型会浅拷贝。列表中的列表和字典会随着副本的修改而改变&#xff0c;其他类型不会随着副本的改变为改变。ab不是复制&#xff0c;是两个变量共享同一内存空间&…

从 WinDbg 角度理解 .NET7 的AOT玩法

一&#xff1a;背景 1.讲故事前几天 B 站上有位朋友让我从高级调试的角度来解读下 .NET7 新出来的 AOT&#xff0c;毕竟这东西是新的&#xff0c;所以这一篇我就简单摸索一下。二&#xff1a;AOT 的几个问题 1. 如何在 .NET7 中开启 AOT 功能在 .NET7 中开启 AOT 非常方便&…

.NET Core C#系列之XiaoFeng.ToCast万能类型转换器

数据类型相互转换如&#xff1a;字符串转整型&#xff0c;字符串转日期首先要引用 XiaoFeng命名空间下边三个扩展方法 就是类型转换的方法最常用的就是 ToCast<T>方法/// <summary> /// 类型相互转换 /// </summary> /// <typeparam name"T">…

利用 Git OpenSSH 查看/生成 本机 ssh 公钥

查看本机公钥 本机公钥文件一般用户目录下的.ssh文件夹&#xff0c;文件夹下有三个文件&#xff0c;分别是 id_rsa 私钥密码id_rsa.pub 公钥内容known_hosts 允许的host地址 使用文本编辑器查看文件id_rsa.pub文件即可 或者使用cat命令查看 # 任意位置打开 Git bash cd ~/.…

高斯消元法

有点线代的知识&#xff1a; const double EPS 1e-8; typedef vector<double> vec; typedef vector<vec> mat; //Ax b vec gauss_jordan(const mat &A, const vec &b) {int n A.size();mat B(n,vec(n1)); //定义大小for(int i0;i < n;i)for(int j0…

判断对象是否存在某个属性

JavaScript判断对象是否存在某个属性或者方法&#xff0c;常用方法有两种hasOwnProperty和in hasOwnProperty是Object原型对象上的一个方法&#xff0c;用来判断对象自身属性中是否具有指定的属性。 这个方法可以用来检测一个对象是否含有特定的自身属性&#xff1b;和 in 运…

【PPT】适配器模式 和 桥接模式

【PPT】适配器模式 和 桥接模式目录【PPT】适配器模式 和 桥接模式一、PPT 截图1.0、封面和目录1.1、设计模式概述1.2、结构型模式特点1.3、适配器模式1.4、桥接模式二、参考资料及 PPT 获取方法独立观察员 2022 年 11 月 15 日为之前公司准备的分享PPT&#xff0c;后来没用上。…

Flask 【第七篇】Flask中的wtforms使用

一、简单介绍flask中的wtforms WTForms是一个支持多个web框架的form组件&#xff0c;主要用于对用户请求数据进行验证。 安装&#xff1a; pip3 install wtforms 二、简单使用wtforms组件 1、用户登录 具体代码&#xff1a; from flask import Flask,render_template,request,…

CSS自定义滚动条样式

css通过滚动条伪类来修改滚动条样式&#xff0c;伪类名称如下 ::-webkit-scrollbar 滚动条整体部分 ::-webkit-scrollbar-track 滚动条轨道&#xff08;里面装有滑块 thumb&#xff09; ::-webkit-scrollbar-thumb 滚动条滑块 ::-webkit-scrollbar-button 滚动条轨道两端按钮 …

为了避免内存攻击,美国国家安全局提倡Rust、C#、Go、Java、Ruby 和 Swift,但将 C 和 C++ 置于一边...

本文翻译自两篇文章&#xff0c;第一篇是对美国国家安全局在“软件内存安全”网络安全信息表的解读&#xff0c;第二篇是普及什么是内存安全&#xff0c;为什么它很重要&#xff1f;第一篇 为了避免内存攻击&#xff0c;美国国家安全局提倡Rust、C#、Go、Java、Ruby 和 Swift&a…

自学python(一)

一、入门仪式 学习一门新语言必不可少的一件事&#xff1a; print("Hello world!")二、基础知识 1、注释&#xff1a; 单行注释&#xff1a; 1 print("Hello world!") #输出Hello world! 多行注释&#xff1a; 这是多行注释 这是多行注释 这是多行注释…

.NET周报【11月第2期 2022-11-15】

国内文章统一的开发平台.NET 7正式发布https://www.cnblogs.com/shanyou/archive/2022/11/09/16871945.html在 2020 年规划的.NET 5功能终于在.NET 7 完成了&#xff0c;为微软和社区一起为多年来将不同的开发产品统一起来的努力加冕&#xff0c;未来只有一个.NET, 回顾.NET 20…

如何像使用AspNetCore中的Controllers 和 Actions一样处理MQTT消息

在物联网项目中&#xff0c; 处理MQTT的topic时费工费力&#xff0c; 代码一团乱&#xff0c; 什么才是最好的姿势&#xff1f;这里面我们极力介绍 MQTTnet.AspNetCore.Routing 项目&#xff0c;MQTTnet AspNetCore Routing 是https://github.com/Atlas-LiftTech/MQTTnet.AspN…