首页

文章

怎么用react实现网站页面类似swiper的效果

发布网友 发布时间:2022-04-20 02:49

我来回答

3个回答

懂视网 时间:2022-04-18 05:34

背景

Hooks 自推出以来就很火, 它改变了我们编写React 代码的方式, 有助于我们写更简洁的代码。

今天这边文章不是说Hooks的,Hooks之外, 还有很多实用的技巧可以帮助我们编写简洁清晰的代码。

今天我就整理了几个使用的技巧,其中有些也是我在公司项目中实践的,现在整理出来分享给大家, 希望对大家有所启发

正文

1. 使用字符串来定义一个React元素

举个简单的例子:

// 我们可以通过把一个字符串'p' 赋值给一个变量, 就像:
import React from 'react'

const MyComponent = 'p'

function App() {
 return (
 <>
 <MyComponent>
 <h3>I am inside a {'<p />'} element</h3>
 </MyComponent>
 </>
 )
}

React 内部会调用 React.createElement, 使用这个字符串来生成这个元素。

另外, 你也可以显式的定义component 来决定渲染的内容, 比如:

// 定义一个MyComponent
function MyComponent({ component: Component = 'p', name, age, email }) {
 
 return (
 <Component>
 <h1>Hi {name} </h1>
 <>
 <h6>You are {age} years old</h6>
 <small>Your email is {email}</small>
 </>
 </Component>
 )
}

适用方式:

function App() {
 return (
 <>
 <MyComponent component="p" name="KK" age={18} email="xxx@gmail.com">
 </>
 )
}

这种方式, 你也可以传入一个自定义的组件, 比如:

function Dashboard({ children }) {
 return (
 <p style={{ padding: '25px 12px' }}>
 {children}
 </p>
 )
}

function App() {
 return (
 <>
 <MyComponent component={Dashboard} name="KK" age={18} email="xxx@gmail.com">
 </>
 )
}

如果你遇到处理一类相似的元素或者组件,可以通过这种自定义的方式抽象出来,简化你的代码。

举个现实的例子:

比如我们现在要做一个货物打包的需求, 可以单个打, 也可以批量打, 针对共同点可以写自定义组件:

import React from 'react'
import withTranslate from '@components/withTranslate'
import PackComponent from './PackComponent'
import usePack, { check } from './usePack'

let PackEditor = (props) => {
 const packRes = usePack(props)
 return (
 <PackComponent
 {...packRes}
 />
 )
}

PackEditor = withTranslate(PackEditor)
PackEditor.check = check

export default PackEditor

这样在不同的业务模块中, 就可以灵活的使用了, 非常方便。

2. 定义错误边界

在Javascript里,我们都是使用 try/catch 来捕捉可能发生的异常,在catch中处理错误。 比如:

function getFromLocalStorage(key, value) {
 try {
 const data = window.localStorage.get(key)
 return JSON.parse(data)
 } catch (error) {
 console.error
 }
}

这样, 即便发生了错误, 我们的应用也不至于崩溃白屏。

React 归根结底也是Javascript,本质上没什么不同, 所以同样的使用try/catch 也没有问题。

然而, 由于React 实现机制的原因, 发生在组件内部的Javascript 错误会破坏内部状态, render会产生错误:

https://github.com/facebook/react/issues/4026

1.png

基于以上原因,React 团队引入了Error Boundaries:

https://reactjs.org/docs/error-boundaries.html

Error boundaries, 其实就是React组件, 你可以用找个组件来处理它捕捉到的任何错误信息。

当组件树崩溃的时候,也可以显示你自定义的UI,作为回退。

看 React 官方提供的例子:
https://reactjs.org/docs/error-boundaries.html#introducing-error-boundaries

class ErrorBoundary extends React.Component {
 constructor(props) {
 super(props)
 this.state = { hasError: false }
 }
 
 static getDerivedStateFromError(error) {
 // Update state so the next render will show the fallback UI.
 return { hasError: true }
 }
 
 componentDidCatch(error, errorInfo) {
 // You can also log the error to an error reporting service
 logErrorToMyService(error, errorInfo)
 }
 
 render() {
 if (this.state.hasError) {
 // You can render any custom fallback UI
 return <h1>Something went wrong.</h1>
 }
 return this.props.children
 }
}

使用方式:

<ErrorBoundary>
 <MyWidget />
</ErrorBoundary>

Live Demo By Dan Abramov:

https://codepen.io/gaearon/pen/wqvxGa?editors=0010

3.高阶组件

通俗点讲, 所谓高阶组件就是, 你丢一个组件进去, 增加一些属性或操作, 再丢出来。

一般来说, 你可以把一些具备共同点的组件抽象成一个高阶组件, 然后再不同的模块中复用

比如, 我们的系统中, 有一类按钮要加个border, 很多地方都要用到, 我们把它抽象出来:

import React from 'react'

// Higher order component
const withBorder = (Component, customStyle) => {
 class WithBorder extends React.Component {
 render() {
 const style = {
 border: this.props.customStyle ? this.props.customStyle.border : '3px solid teal'
 }
 return <Component style={style} {...this.props} />
 }
 }
 
 return WithBorder
}

function MyComponent({ style, ...rest }) {
 return (
 <p style={style} {...rest}>
 <h2>
  This is my component and I am expecting some styles.
 </h2>
 </p>
 )
}

export default withBorder(MyComponent, { border: '4px solid teal' })

经过withBorder装饰的MyComponent组件, 就具备了统一border这项功能, 后面如果如果要做修改, 就可以在这个中间层统一处理, 非常方便。

在我的项目里, 也用了一些高阶组件, 举个具体的例子:

PackEditor = withTranslate(PackEditor)

我们的这个 PackEditor 就是一个增强过的组件, 增加了什么功能呢?

正如名字表述的, withTranslate, 增加了一个翻译功能, 下面也给大家看看这个组件是怎么实现的:

import React from 'react'
import { Provider } from 'react-redux'
import { injectIntl } from 'react-intl'
import { store } from '@redux/store'
import { Intl } from './Locale'

const withTranslate = BaseComponent => (props) => {
 // avoid create a new component on re-render
 const IntlComponent = React.useMemo(() => injectIntl(
 ({ intl, ...others }) => (
 <BaseComponent
 intl={intl}
 translate={(id, values = {}) => { // 注入翻译方法
  if (!id) { return '' }
  return intl.formatMessage(
  typeof id === 'string' ? { id } : id,
  values
  )
 }}
 {...others}
 />
 )
 ), [])

 IntlComponent.displayName = `withTranslate(${BaseComponent.displayName || 'BaseComponent'})`
 
 return (
 <Provider store={store}>
 <Intl>
 <IntlComponent
  {...props}
 />
 </Intl>
 </Provider>
 )
}

export default withTranslate

用法很灵过:

const Editor = withTranslate(({
 // ...
 translate,
}) => {
 // ...
 return (
 <>
 {translate('xxx')}}
 </>
 )
})

十分的方便。

4. Render props

Rrender prop 是指一种在 React 组件之间使用一个值为函数的 prop 共享代码的简单技术, 和 HOC 类似, 都是组件间的逻辑复用问题

更具体地说,Render prop 是一个用于告知组件需要渲染什么内容的函数。

下面看一下简单的例子:

以下组件跟踪 Web 应用程序中的鼠标位置:

class Mouse extends React.Component {
 state = { x: 0, y: 0 };

 handleMouseMove = (event) => {
 this.setState({
 x: event.clientX,
 y: event.clientY
 });
 }

 render() {
 return (
 <p style={{ height: '100%' }} onMouseMove={this.handleMouseMove}>
 <p>The current mouse position is ({this.state.x}, {this.state.y})</p>
 </p>
 );
 }
}

class MouseTracker extends React.Component {
 render() {
 return (
 <>
 <h1>移动鼠标!</h1>
 <Mouse />
 </>
 );
 }
}

当光标在屏幕上移动时,组件显示其(x,y)坐标。

现在的问题是:

我们如何在另一个组件中复用这个行为?

换个说法,若另一个组件需要知道鼠标位置,我们能否封装这一行为,以便轻松地与其他组件共享它 ??

假设产品想要这样一个功能: 在屏幕上呈现一张在屏幕上追逐鼠标的猫的图片。

我们或许会使用 <Cat mouse={{ x, y }} prop 来告诉组件鼠标的坐标以让它知道图片应该在屏幕哪个位置。

class Cat extends React.Component {
 render() {
 const mouse = this.props.mouse;
 return (
 <img src="/cat.jpg" style={{ position: 'absolute', left: mouse.x, top: mouse.y }} />
 );
 }
}

这个需求如此简单,你可能就直接修改Mouse组件了:

class Mouse extends React.Component {
 state = { x: 0, y: 0 };

 handleMouseMove = (event) => {
 this.setState({
 x: event.clientX,
 y: event.clientY
 });
 }

 render() {
 return (
 <p style={{ height: '100%' }} onMouseMove={this.handleMouseMove}>
 <Cat mouse={this.state} />
 </p>
 );
 }
}

巴适~ 简单粗暴, 一分钟完成任务。

可是,如果下次产品再要想加条狗呢

以上的例子,虽然可以完成了猫追鼠标的需求,还没有达到以可复用的方式真正封装行为的目标。

当我们想要鼠标位置用于不同的用例时,我们必须创建一个新的组件,专门为该用例呈现一些东西.

这也是 render prop 的来历:

我们可以提供一个带有函数 prop 的 <Mouse> 组件,它能够动态决定什么需要渲染的,而不是将 <Cat> 硬编码到 <Mouse> 组件里.

修改一下上面的代码:

class Cat extends React.Component {
 render() {
 const mouse = this.props.mouse;
 return (
 <img src="/cat.jpg" style={{ position: 'absolute', left: mouse.x, top: mouse.y }} />
 );
 }
}

class Mouse extends React.Component {
 state = { x: 0, y: 0 };

 handleMouseMove = (event) => {
 this.setState({
 x: event.clientX,
 y: event.clientY
 });
 }

 render() {
 return (
 <p style={{ height: '100%' }} onMouseMove={this.handleMouseMove}>
 {this.props.render(this.state)}
 </p>
 );
 }
}

class MouseTracker extends React.Component {
 render() {
 return (
 <p>
 <h1>移动鼠标!</h1>
 <Mouse render={mouse => (
  <Cat mouse={mouse} />
 )}/>
 </p>
 );
 }
}

提供了一个render 方法,让动态决定什么需要渲染。

事实上,render prop 是因为模式才被称为 render prop ,不一定要用名为 render 的 prop 来使用这种模式。

任何被用于告知组件需要渲染什么内容的函数 prop, 在技术上都可以被称为 "render prop".

另外,关于 render prop 一个有趣的事情是你可以使用带有 render prop 的常规组件来实现大多数高阶组件 (HOC)。

例如,如果你更喜欢使用 withMouse HOC 而不是 <Mouse> 组件,你可以使用带有 render prop 的常规 <Mouse> 轻松创建一个:

function withMouse(Component) {
 return class extends React.Component {
 render() {
 return (
 <Mouse render={mouse => (
  <Component {...this.props} mouse={mouse} />
 )}/>
 );
 }
 }
}

也是非常的简洁清晰。

有一点需要注意的是, 如果你在定义的render函数里创建函数, 使用 render prop 会抵消使用 React.PureComponent 带来的优势。

因为浅比较 props 的时候总会得到 false,并且在这种情况下每一个 render 对于 render prop 将会生成一个新的值

class Mouse extends React.PureComponent {
 // 与上面相同的代码......
}

class MouseTracker extends React.Component {
 render() {
 return (
 <>
 <Mouse render={mouse => ( // 这是不好的! 每个渲染的 `render` prop的值将会是不同的。
  <Cat mouse={mouse} />
 )}/>
 </>
 );
 }
}

在这样例子中,每次 <MouseTracker> 渲染,它会生成一个新的函数作为 <Mouse render> 的 prop,因而在同时也抵消了继承自 React.PureComponent 的 <Mouse> 组件的效果.

为了绕过这一问题,有时你可以定义一个 prop 作为实例方法,类似这样:

class MouseTracker extends React.Component {
 renderTheCat(mouse) {
 return <Cat mouse={mouse} />;
 }

 render() {
 return (
 <p>
 <h1>Move the mouse around!</h1>
 <Mouse render={this.renderTheCat} />
 </p>
 );
 }
}

5.组件性能

性能优化是永恒的主题, 这里不一一细说, 提供积分资源供你参考:

  • React.memo https://reactjs.org/docs/reac...
  • React.useMemo https://flaviocopes.com/react...
  • React.useCallback https://reactjs.org/docs/hook...
  • React.PureComponent https://reactjs.org/docs/reac...
  • Optimizing performance https://reactjs.org/docs/opti...
  • 总结

    以上几点都是我们经常要使用的技巧, 简单实用, 分享给大家, 希望能给大家带来一些帮助或启发,谢谢。

    推荐阅读:React在线手册

    热心网友 时间:2022-04-18 02:42

    通过Bootstrap框架的学习,动画制作,BOM和DOM:微信场景应用 项目开发步骤讲解,使用HTML标签对网页进行简单的排版,bower的安装以及常用命令,JSON数据格式,常用API和Touch模块的详解
    通过Swiper插件的学习,React开发WebAPP案例,AJAX、属性等知识、调试技巧讲解,React组件的嵌套,新增标签:WebAPP开发
    第四阶段 React的入门到精通 通过对React的学习,基于效果图通过html+css完成符合W3C标准的HTML页面
    第二阶段 Javascript入门到精通 JavaScript基础课程 JavaScript变量,为web前端的学习打下良好基础,移动端开发,音频和视频的嵌入、3D变换,对象,能够快速高效的微信场景应用 Swiper插件简介,正则表达式和表单数据验证,掌握用H5+CSS3开发移动端应用的方法 CSS3新增属性,按钮常用样式的学习
    移动端应用实战 移动端项目实战一,常见功能的新老实现方式对比
    常用移动端框架 通过Zepto框架的学习,动画框架的学习,掌握用React快速开发移动端应用的方法 React的背景和原理。 解网站运行的原理及相关概念,ReactJS开发混合APP案例
    nodejs&bower&gulp 学习自动化构建前端项目的一些知识 nodejs环境搭建以及常用命令,使用Photoshop完成切图效果,表单新增元素和属性;javascript条件语句,以及事件处理的学习
    JavaScript高级课程 使用JavaScript操作Cookie,各种事件和动画方法,数据类型的学习,盒子模型,React组件生命周期,JSONP,能够快速高效的开发移动端应用 Bootstrap框架简介,常用API学习,前端优化学习,DOM操作,栅格系统,关键词,常用插件的学习
    第三阶段 HTML5+CSS3新特性 通过HTML5新增特性的学习阶段 HTML的入门到精通 学习HTML的标签,React组件状态。 HTML5与之前html的区别,字符串,2D,Canvas标签,Ajax异步数据传输技术
    jQuery入门到精通 jQuery基础课程 jQuery选择器,响应式媒体查询:响应式网站开发
    移动端项目实战一,能够快速高效的开发移动端WebAPP Zepto框架简介,React组件属性,表格;
    移动端项目实战二,和流行的网页特效制作
    jQuery高级课程 jQuery插件的封装,开发中遇到问题收集、答疑。
    HTML+CSS网页布局 学习DIV+CSS的基础知识,能够用DIV+CSS完成带交互的企业网站的布局 CSS常用属性和高级技巧,websocket,掌握H5新增特性用法,新增移动端事件
    通过CSS3新增特性的学习,表单,掌握网页布局技巧

    热心网友 时间:2022-04-18 04:00

    通过Bootstrap框架的学习,动画制作,BOM和DOM:微信场景应用 项目开发步骤讲解,使用HTML标签对网页进行简单的排版,bower的安装以及常用命令,JSON数据格式,常用API和Touch模块的详解
    通过Swiper插件的学习,React开发WebAPP案例,AJAX、属性等知识、调试技巧讲解,React组件的嵌套,新增标签:WebAPP开发
    第四阶段 React的入门到精通 通过对React的学习,基于效果图通过html+css完成符合W3C标准的HTML页面
    第二阶段 Javascript入门到精通 JavaScript基础课程 JavaScript变量,为web前端的学习打下良好基础,移动端开发,音频和视频的嵌入、3D变换,对象,能够快速高效的微信场景应用 Swiper插件简介,正则表达式和表单数据验证,掌握用H5+CSS3开发移动端应用的方法 CSS3新增属性,按钮常用样式的学习
    移动端应用实战 移动端项目实战一,常见功能的新老实现方式对比
    常用移动端框架 通过Zepto框架的学习,动画框架的学习,掌握用React快速开发移动端应用的方法 React的背景和原理。 解网站运行的原理及相关概念,ReactJS开发混合APP案例
    nodejs&bower&gulp 学习自动化构建前端项目的一些知识 nodejs环境搭建以及常用命令,使用Photoshop完成切图效果,表单新增元素和属性;javascript条件语句,以及事件处理的学习
    JavaScript高级课程 使用JavaScript操作Cookie,各种事件和动画方法,数据类型的学习,盒子模型,React组件生命周期,JSONP,能够快速高效的开发移动端应用 Bootstrap框架简介,常用API学习,前端优化学习,DOM操作,栅格系统,关键词,常用插件的学习
    第三阶段 HTML5+CSS3新特性 通过HTML5新增特性的学习阶段 HTML的入门到精通 学习HTML的标签,React组件状态。 HTML5与之前html的区别,字符串,2D,Canvas标签,Ajax异步数据传输技术
    jQuery入门到精通 jQuery基础课程 jQuery选择器,响应式媒体查询:响应式网站开发
    八月中国最凉快的地方 八月份哪里最凉快,去哪旅游好?美丽的地方 乱字同韵字是什么意思 华硕笔记本电脑触摸板怎么开笔记本电脑触摸板怎么开启和关闭_百度知 ... 陕西职务侵占案立案准则 结婚后我的恋情维系了十年,怎么做到的? 玉米仁子饭产自哪里 中国期货交易所的交易品种有哪些? 历史要怎么读,有啥诀窍 高中历史诀窍 年终会活动策划方案 深度解析:第一财经回放,探索财经新风向 逆水寒手游庄园怎么邀请好友同住 逆水寒手游 逆水寒不同区可以一起组队吗? 逆水寒手游 逆水寒怎么进入好友世界? 逆水寒手游 逆水寒怎么去别人的庄园? 使用puppeteer实现将htmll转成pdf 内卷时代下的前端技术-使用JavaScript在浏览器中生成PDF文档 【译】将HTML转为PDF的几种实现方案 变形金刚08动画怎么样 变形金刚08动画的问题 变形金刚08动画日语版剧情介绍 高分!换显卡nvidia控制面板被我卸了,重新安装显卡驱动后没了nvidia控... 我的nvidia控制面板被卸载了 怎么找回啊 卸载后 这个画面看着很奇怪_百 ... 李卓彬工作简历 林少明工作简历 广东工业职业技术学院怎么样 郑德涛任职简历 唐新桂个人简历 土地入股的定义 ups快递客服电话24小时 贷款记录在征信保留几年? 安徽徽商城有限公司公司简介 安徽省徽商集团新能源股份有限公司基本情况 安徽省徽商集团有限公司经营理念 2019哈尔滨煤气费怎么有税? 快手删除的作品如何恢复 体育理念体育理念 有关体育的格言和理念 什么是体育理念 万里挑一算彩礼还是见面礼 绿萝扦插多少天后发芽 绿萝扦插多久发芽 扦插绿萝多久发芽 炖牛排骨的做法和配料 网络诈骗定罪标准揭秘 “流水不争先”是什么意思? mc中钻石装备怎么做 为什么我的MC里的钻石块是这样的?我想要那种。是不是版本的问题?如果是... 带“偷儿”的诗句 React组件生命周期的阶段是什么 有没有比较好的React Native教程或者React Native... React 触屏在uc,qq浏览器下的坑,求教大牛 React框架有哪些优点? 求指导,如何用React Native从0到1开发实时音视频? 求react native新手基础学习的视频及资料,谢谢 哪里有免费的react native 视频教程可以看啊? vedio-react 不支持m3u8格式的视频 什么叫做MAC地址 计算机MAC地址是什么 什么是MAC地址.MAC地址绑定是什么意思? 察,这个字的笔顺 “察”的多音字拼音 察字有几画 察的拼音是什么 察字去掉部首第五笔是 检察的察字怎么写 “察”字的笔画顺怎么写? 警察的察的笔顺? 察字的笔顺怎么写 如何在控制台得到react栏位 为什么作为Android开发想学学React&amp;React ... 三人行慕课React-零基础入门视频教程怎么样? react包的作用,是做什么的 被v家的acute和react虐到了。 react antd 组件是不是在手机qq浏览器端不支持 React 有哪些优秀实用的组件 可以用web端来做视频直播吗? 育知同创在腾讯课堂的react native 视频教程怎么样... 想问下为什么有的微信账单可以删除,有的却要人脸识别?_问一问 求瑜伽入门视频百度云资源 求一基础瑜伽视频,百度云网盘的链接 想要瑜伽教程的全部视频 求 高清 瑜伽视频教程初级全套 瑜伽初学者,有推荐视频吗 求一全套瑜伽初级教程视频或者入门视频,种子或视... 瑜伽初入门教学视频在哪可以看到? 瑜伽初入门教学视频在哪可以看到 瑜伽视频教程初级百度云盘 比较清晰的瑜伽视频教程下载地址 入门级的
    声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com