“这是我参与更文挑战的第2天,活动详情查看: 更文挑战”
前言
Vue提供了一些列的指令,帮助我们快速开发组件,如最常用的v-model
、v-show
、v-if
、v-for
,这些指令的功能在React中是如何提供的。
1、React中的v-model
在Vue中的v-model
的作用是实现数据双向绑定。这里要特别注意,Vue和React都是单向数据流的,数据双向绑定和数据流是两个独立的概念。
因为在Vue中v-model
只能在表单元素<input>
、<textarea>
、<select>
和组件Components上使用,故分表单元素和组件两种使用场景来介绍React中的v-model
。
1.1 表单元素的v-model
在React中是用受控组件的概念来实现表单元素上的v-model
。
那什么是受控组件呢?我是这么理解的。在表单元素<input>
、<textarea>
和 <select>
中通常是自己维护数据,并根据用户输入来更新数据。假如我们用React的state来替换这个数据会怎样呢?例如:
import React from 'react';
export default class Input extends React.Component {
constructor(props) {
super(props);
this.state={
value:'请输入内容',
}
}
render() {
return (
<input type="text" value={this.state.value}/>
);
}
}
会发现Input输入框无法输入内容了,这是因为<input/>
标签的value
属性是可读写的,当我们在Input输入框输入内容时其实是在改变value
的值。
这是因为this.state.value
在React类组件中只能通过this.setState()
来修改。那么在<input/>
标签的value
属性被this.state.value
赋值后,在Input输入框输入内容时,js内部无法修改this.state.value
,导致无法修改value
的值,从而造成Input输入框无法输入内容。
相当于Input输入框被this.state.value
这个state给控制了,React将这种类型的Input输入框称为受控组件。
那如何恢复Input输入框的输入功能呢?这要借助React的合成事件onChange
来监听Input输入框的输入,获取输入值,再用this.setState()
来把输入值赋值给this.state.value
,间接来改变value
的值。
import React from 'react';
export default class Input extends React.Component {
constructor(props) {
super(props);
this.state = {
value: '请输入内容',
}
this.handleChange = this.handleChange.bind(this);
}
handleChange(e) {
this.setState({ value: e.target.value });
}
render() {
return (
<>
<input
type="text"
value={this.state.value}
onChange={this.handleChange}
/>
<span>{this.state.value}</span>
</>
);
}
}
this.state.value
和Input输入框绑定在一起,随着Input输入框输入内容的改变,this.state.value
也会跟着改变,当this.state.value
改变时,Input输入框的内容也会改变,这就是数据双向绑定。
以上实现的是不是和v-modle
的功能一模一样。下面来看一下函数组件如何实现v-modle
。
import { useState } from "react";
export default function Index() {
const [value, setValue] = useState('请输入内容');
const handleChange = (e) => {
setValue(e.target.value)
}
return (
<>
<input type="text" value={value} onChange={handleChange} />
<span>{value}</span>
</>
);
}
1.2 React组件的v-model
Vue组件的v-model
是个语法糖,本质上是利用名为value的prop和名为input的事件。
例如在组件上使用v-model="info"
时,其实是把info
数据传递给value
,当info
数据改变时组件的value
也跟着改变。
双向数据绑定要求组件的value
改变时info
数据也得跟着改变,可以在组件的value
改变时执行this.$emit('input',data)
,触发名为 input 的事件,该事件绑定函数(data) => { this.info = data}
,其中data
是value
改变后的值,执行后就实现了双向数据绑定。
那么在React中也可以按这个思路来实现v-model
。
import React from 'react';
export default class HelloWorld extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<>
<div>{this.props.value}</div>
<button
onClick={this.props.onChange.bind(this, '子组件改变info的值')}
>
子组件改变info的值
</button>
</>
);
}
}
import React from 'react';
import HelloWorld from './HelloWorld';
export default class Input extends React.Component {
constructor(props) {
super(props);
this.state = {
info: '父组件改变info的值',
}
this.handleChange = this.handleChange.bind(this);
}
handleChange(data) {
this.setState({ info: data });
}
render() {
return (
<>
<button
onClick={() =>{this.setState({info:'父组件改变info的值'})}}
>
父组件改变info的值
</button>
<HelloWorld
value={this.state.info}
onChange={this.handleChange}
>
</HelloWorld>
</>
);
}
}
函数组件的写法:
export default function HelloWorld(props) {
const { value, onChange } = props
return (
<>
<div>{value}</div>
<button
onClick={() => { onChange('子组件改变info的值') }}
>
子组件改变info的值
</button>
</>
);
}
import { useState } from 'react';
import HelloWorld from './HelloWorld';
export default function Input() {
const [info, setInfo] = useState('父组件改变info的值');
const handleChange = (data) => {
setInfo(data)
}
return (
<>
<button
onClick={() => { setInfo('父组件改变info的值') }}
>
父组件改变info的值
</button>
<HelloWorld
value={info}
onChange={handleChange}
>
</HelloWorld>
</>
);
}
2、React中的v-show
Vue的v-show
本质是设置所添加指令的元素的css属性display
的值,当v-show="true"
时,把display
设为block
,当v-show='false'
设为none
。
React中这样实现v-show
,分类组件和函数组件来介绍。
类组件的写法:
import React from 'react';
export default class Index extends React.Component {
constructor(props) {
super(props);
this.state = {
show: true
}
}
render() {
return (
<div
style={{ 'display': this.state.show ? 'block' : 'none' }}
>
hello world
</div>
);
}
}
函数组件的写法:
import { useState } from "react";
export default function Index() {
const [show, setShow] = useState(false);
return (
<div
style={{ 'display': show ? 'block' : 'none' }}
>
hello world
</div>
)
}
React中实现的v-show
比Vue中更灵活,假如元素的css属性display
的值为flex
,使用v-show
会导致样式错乱,而在React可以这样解决。
<div
style={{ 'display': show ? 'flex' : 'none' }}
>
hello world
</div>
3、React中的v-if和v-else
Vue中用v-if
和v-else
来控制元素是否被渲染。
在JSX语法中,JavaScript 表达式可以被包裹在{}
中作为子元素,另外函数也可以被包裹在{}
中作为子元素,该函数执行后必须返回React元素。同时在JSX语法中false
、null
、undefined
、true
是合法的子元素,但它们并不会被渲染,故可以依据此特性来决定是否要渲染其他的 React 元素,来实现React中的v-if
和v-else
。
类组件的写法:
- 用JavaScript表达式包裹在
{}
中来实现:
import React from 'react';
export default class Index extends React.Component {
constructor(props) {
super(props);
this.state = {
show: false
}
}
render() {
return (
<React.Fragment>
{this.state.show ? <div>hello world</div> : <div>hello React</div>}
</React.Fragment>
);
}
}
React组件返回的元素和Vue一样必须有个根元素,所以用<React.Fragment>
来包裹,<React.Fragment>
不会在DOM中渲染出额外的元素,跟Vue中的<template>
元素一样。
- 用函数包裹在
{}
中来实现:
import React from 'react';
export default class Index extends React.Component {
constructor(props) {
super(props);
this.state = {
show: false
}
}
render() {
return (
<React.Fragment>
{
(() => {
if (this.state.show) {
return (
<div>hello world</div>
)
} else {
return (
<div>hello world</div>
)
}
})()
}
</React.Fragment>
);
}
}
函数组件的写法:
- 用JavaScript表达式包裹在
{}
中来实现:
import { useState } from "react";
export default function Index() {
const [show, setShow] = useState(false);
return (
<>
{show ? <div>hello world</div> : <div>hello React</div>}
</>
)
}
其中<></>
相当<React.Fragment></React.Fragment>
。
- 用函数包裹在
{}
中来实现:
import { useState } from "react";
export default function Index() {
const [show, setShow] = useState(false);
const Title = () => {
if (show) {
return (
<div>hello world</div>
)
} else {
return (
<div>hello React</div>
)
}
}
return (
<>
{Title()}
</>
)
}
4、React中的v-for
在Vue中用v-for
来渲染列表形式的组件,在Reacr中可以用map()
函数来实现,但是要注意在map()
方法中的元素需要设置key
属性,否值会引起警告错误。
类组件的写法:
import React from 'react';
export default class Index extends React.Component {
constructor(props) {
super(props);
this.state = {
list: ['小明', '小红', '小东']
}
}
render() {
return (
<React.Fragment>
{this.state.list.map((item, index) => {
return (
<div key={index}>{item}</div>
)
})}
</React.Fragment>
);
}
}
当数组类型的数据中每一项没有唯一性id
的时候,可以使用索引index
作为key
,如果数据的顺序可能会变化,不要使用索引index
作为key
,因为这样做会导致性能变差,还可能引起组件状态的问题,此时可以要求服务端给每项数据添加一个唯一值key
,或者用随机数作为key
。
函数组件的写法:
import { useState } from "react";
export default function Index() {
const [list, setList] = useState(['小明', '小红', '小东']);
return (
<>
{list.map((item, index) => {
return (
<div key={index}>{item}</div>
)
})}
</>
)
}
小结
本文介绍了Vue开发中常用的指令在React中是如何实现的。读完本文,你应该会按原先用Vue开发一些复杂组件的UI界面及UI交互的思路去用React来开发一些复杂组件的UI界面及UI交互。然而组件的业务交互一般是在组件的生命周期钩子函数中去处理的,比如从服务端请求数据等等。所以下一篇文章将介绍React组件的生命周期。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!