最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 从Vue2.0到React17——React中实现Vue指令

    正文概述 掘金(红尘炼心)   2021-06-22   719

    “这是我参与更文挑战的第2天,活动详情查看: 更文挑战”

    前言

    Vue提供了一些列的指令,帮助我们快速开发组件,如最常用的v-modelv-showv-ifv-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},其中datavalue改变后的值,执行后就实现了双向数据绑定。

    那么在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-ifv-else来控制元素是否被渲染。

    在JSX语法中,JavaScript 表达式可以被包裹在{}中作为子元素,另外函数也可以被包裹在{}中作为子元素,该函数执行后必须返回React元素。同时在JSX语法中falsenullundefinedtrue 是合法的子元素,但它们并不会被渲染,故可以依据此特性来决定是否要渲染其他的 React 元素,来实现React中的v-ifv-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组件的生命周期。


    起源地下载网 » 从Vue2.0到React17——React中实现Vue指令

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元