React碰到v-if

最近在重构公司老项目,由于本人以前的技术栈是vue, 换工作后发现现在公司的技术栈是react, 所以重构的过程是及其痛苦。加之项目又是几年前的老项目,不敢大改,比葫芦画瓢比比皆是。本文就介绍下遇到的一个常用的痛点。欢迎大佬指正。

废话不多说,直接上一段代码。

import React from 'react'

const App = () => {
  const record = {
    toKe: true, // 贝壳首页
    toSecondHand: true, // 二手房
    toFang: true, // 新房
  }
  return (
    <div style={{width: 600, margin: '50px auto'}}>
      <ul>
        <li>
          <h3>react常规写法</h3>
          {
            record.toKe
            ? <a style={{padding: 20}} href="https://bj.ke.com">贝壳首页</a>
            : null
          }
          {
            record.toSecondHand
            ? <a style={{padding: 20}} href="https://bj.ke.com/ershoufang/">二手房</a>
            : null
          }
          {
            record.toFang
            ? <a style={{padding: 20}} href="https://bj.fang.ke.com/loupan/">新房</a>
            : null
          }
        </li>
      </ul>
    </div>
  )
}
export default App

如上述代码,我们在项目中会遇到很多这样的写法, 细看一下没什么问题,可是当在重构老项目的时候,你会发现这个代码结构是多么痛苦,特别是如下的结构。

{
    record.toFang && record.toKe && record.toSecondHand
    && <div>
       <a style={{padding: 20}} href="https://bj.ke.com">贝壳首页</a>
       <a style={{padding: 20}} href="https://bj.ke.com/ershoufang/">二手房</a>
       <a style={{padding: 20}} href="https://bj.fang.ke.com/loupan/">新房</a>
   </div>
}

虽然代码逻辑没问题,但人生就是这样,有时候出场顺序真的很重要。突然就想起vue的v-if了。
没错,回归主题,就是:react中模拟vuev-if

先上代码

import React from 'react'
import Hidden from './Hidden'
const App = () => {
  const record = {
    toKe: true, // 贝壳首页
    toSecondHand: true, // 二手房
    toFang: true, // 新房
  }
  return (
    <div style={{width: 600, margin: '50px auto'}}>
      <ul>
        <li>
          <h3>react模拟实现vue中v-if指令</h3>
          <Hidden visible={record.toKe} tag='span'>
            <a href="https://bj.ke.com">贝壳首页</a>
          </Hidden>
          <Hidden visible={record.toSecondHand} tag='span' style={{padding: 20}}>
            <a href="https://bj.ke.com/ershoufang/">二手房</a>
          </Hidden>
          <Hidden visible={record.toFang} tag='p'>
            <a href="https://bj.fang.ke.com/loupan/">新房</a>
          </Hidden>
        </li>
      </ul>
    </div>
  )
}
export default App

简单就是封装Hidden组件,通过visible去控制是否渲染。

相信聪明的你一定知道怎么去封装Hidden

笔者刚开始是这么写的

import React, { Component } from 'react'

export default class Hidden extends Component {
  render() {
    const { visible, children } = this.props
    const content = visible ? children : null
    return (
      <div>
       { content }
      </div>
    )
  }
}

如此简单,但笔者审查元素的时候发现,每个Hidden下的children莫名被嵌套了一层div
如下
图片描述

原来的横着排列的元素,一下子竖着排列了。这可不太好,本来给我套个div,我都可以勉强接收,现在连我布局都给我变了。
怎么办?笔者突然想到使用vue-router中的router-link时,标签是可以通过tag去替换默认标签的。
那我们再给它个tag呗,连带自定义属性。

import React, { Component } from 'react'

export default class Hidden extends Component {
  render() {
    const { visible, children, tag = 'div', ...rest } = this.props
    const content = visible ? children : null
    return (
      React.createElement(tag, rest, content)
    )
    // return (
    // 尝试用这种方法去实现,发现不符合react的规则,所以使用最原始的渲染方法
    // React.createElement
    //  `<`${tag}`>` + { content } + `</`${tag}`>` 
    // )
  }
}

问题:笔者的初衷是模拟vue的v-if, 所以对传入的children并没做太多处理,不建议做多做封装。有兴趣的同学可以自己玩。

{
    record.toFang && record.toKe && record.toSecondHand
    && <span>
       <a style={{padding: 20}} href="https://bj.ke.com">贝壳首页</a>
       <a style={{padding: 20}} href="https://bj.ke.com/ershoufang/">二手房</a>
       <a style={{padding: 20}} href="https://bj.fang.ke.com/loupan/">新房</a>
    </span>
}
<Hidden 
   visible={record.toFang && record.toKe && record.toSecondHand} 
   tag='span'>
   <a href="https://bj.ke.com">贝壳首页</a>
   <a style={{padding: 20}} href="https://bj.ke.com/ershoufang/">二手房</a>
   <a style={{padding: 20}} href="https://bj.fang.ke.com/loupan/">新房</a>
</Hidden>

其实感觉也没多大用处hhhh

好了,讲解完毕。

<think>好的,用户现在想了解如何在React中实现类似Vue的v-if和v-else功能。我需要先回忆一下React的条件渲染方法,并结合用户提供的引用内容来组织答案。 首先,用户提供的引用[1]和[3]提到了React的条件渲染方法,比如使用JSX中的逻辑与、三元表达式等。需要将这些方法详细说明,并且对比Vue的v-if和v-else。 用户可能已经知道Vue的模板语法,所以在React中需要转换思维,使用JavaScript表达式来实现条件渲染。比如,Vue中的v-if对应React中的条件判断,而v-show可能对应的是条件性的样式控制,比如display属性。 需要分步骤讲解不同的实现方式,比如使用逻辑与运算符、三元表达式、立即执行函数、组件封装等。同时,还要提到条件渲染中的“else”部分如何处理,比如通过变量或者三元运算符。 另外,用户可能关心性能问题,比如Vue的v-if和v-show的区别,在React中如何模拟这两种行为。v-if是条件性地渲染元素,而v-show是通过CSS控制显示隐藏。在React中,可以通过条件渲染来实现v-if,而使用style或className来控制显示隐藏来模拟v-show。 还需要注意代码示例的正确性,确保语法正确,比如使用花括号包裹JavaScript表达式,正确使用state和props等。同时,可能需要提到在类组件和函数组件中的不同实现方式,但用户提供的引用中主要使用了函数组件的useState,所以可能重点放在函数组件上。 最后,生成的相关问题需要涵盖常见的疑问点,比如动态条件、性能优化、与v-show的对比、封装可复用组件等。这样用户可以有进一步的学习路径。 总结回答的结构:先介绍React条件渲染的基本概念,然后分点列出不同的实现方法,每种方法给出示例代码,并对比Vue的语法。最后解答可能的相关问题,如动态条件处理、性能优化等。</think>在 React 中实现类似 Vue 的 `v-if` 和 `v-else` 条件渲染,可以通过以下 4 种常用方法实现: ### 一、基础实现方案 #### 1. 逻辑与运算符(&&) ```jsx function AuthButton() { const [isLogin] = useState(false); return ( <div> {isLogin && <button>退出登录</button>} {!isLogin && <button>立即登录</button>} </div> ); } ``` 此方案通过 JavaScript 布尔运算直接控制元素渲染,类似 Vue 中连续的 `v-if` 判断[^1]。 #### 2. 三元表达式 ```jsx {isVIP ? ( <GoldenMemberCard /> ) : ( <NormalMemberCard /> )} ``` 这是 React 中最接近 Vue `v-if/v-else` 的语法结构,支持完整的条件分支[^3]。 ### 二、进阶实现方案 #### 3. 立即执行函数 ```jsx function Notification() { const [type] = useState('success'); return ( <div> {(() => { if (type === 'success') return <SuccessIcon />; if (type === 'warning') return <WarningIcon />; return <DefaultIcon />; })()} </div> ); } ``` 这种写法适用于多条件分支场景,类似 Vue 的 `v-if/v-else-if/v-else` 链式判断[^2]。 #### 4. 组件封装 ```jsx const Conditional = ({ when, children }) => when && children; function App() { const [show] = useState(true); return ( <Conditional when={show}> <Dashboard /> </Conditional> ); } ``` 通过自定义组件实现声明式条件渲染,使模板更清晰。 ### 三、与 Vue 的特性对比 | Vue 特性 | React 实现方案 | 特点对比 | |--------------|----------------------------|---------------------------| | `v-if` | `{condition && <Element/>}` | 完全相同的 DOM 销毁/重建逻辑 | | `v-else` | 三元表达式 | 需要显式编写分支代码 | | `v-show` | 动态 className/style | React 需要手动控制样式 | ### 四、最佳实践建议 1. **简单条件**优先使用 `&&` 或三元表达式 2. **复杂分支**推荐使用立即执行函数 3. **高频切换**的场景建议用 CSS 控制显示隐藏(模拟 `v-show`): ```jsx <div style={{ display: isShow ? 'block' : 'none' }} /> ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值