热门搜索 :
宠物故事
您的当前位置:首页正文

和我一起实战react之JSX_html/css

2023-11-28 来源:微宠网

JSX

我们知道React使用一颗DOM对象树来描述文档,如果它是普通的对象,会是怎样?

var element = { tagName: 'div', props: { id: 'div', className: 'container' }, children: [ { tagName: 'div', props: { id: 'div1', className: 'header' }, children: [...{element}] }, { tagName: 'div', props: { id: 'div2', className: 'content' }, children: [...{element}] }, { tagName: 'div', props: { id: 'div3', className: 'footer' }, children: [...{element}] } ]}

对应的 HTML:

 

JSX给予的方式正好相反,通过书写这样类似 HTML结构,通过transformer工具将其转换成了对象,且让我们看一个不借助 JSX的写法实现上面的结构。

React.createElement( 'div', { className: 'container'}, React.createElement( 'div', { className: 'header'} ), React.createElement( 'div', { className: 'content'} ), React.createElement( 'div', { className: 'footer'} ));
开始使用JSX

在今后的编程实践中期望大家使用JSX来书写React组件

利用JSX我们现在可以像写 HTML一样来书写React组件,某些情况下在属性中你还需要注意 JavaScript的保留字,比如class属性要写成className,for需要写成htmlFor。 JSX对于大小写是敏感的,小写属于HTML标签,大写则是React组件。

使用 JSX书写一个简单的组件:

import React from 'react';import { render } from 'react-dom';function Hello (props){ const { className, children } = props; return ( { children } );}render(( Hello World ),document.getElementById('app'))
表达式

在 JSX中 {}用来表示一个 JavaScript表达式,你可以在这里进行求值逻辑或者赋值,赋值且可看上述的Hello例子,只需要 { children }。

且看我们已经实现的 Dialog根据不同的 type类型来呈现不同的子组件。

好的写法是将逻辑判断写在return之前(good):

import Alert from './Alert';import Confirm from './Confirm';class Dialog extends React.Component { render (){ const { type } = this.props; const Component = type === 'alert' ? Alert : Confirm; return ( 
); }}

当然你也可以直接将表达式写在return里面(这个写法非常不好 bad):

import Alert from './Alert';import Confirm from './Confirm';class Dialog extends React.Component { render (){ const { type } = this.props; return ( 
{ type === 'alert' ? : }
); }}
注释

在 JSX里的注视和 JavaScript一样,比如 //, /**/,唯一的要求是需要使用 {}包括起来。

{/**/}
spread attributes

在Dialog的例子中可以看见大量的 ...符号,这是属于ES2015规范中的操作符,在React组件中的 {...this.props},可以将 props的属性设置为 React Component的属性。

HTML转义和自定义属性

为了防止XSS攻击,React组件会将需要显示到DOM的字符串进行转义,如果实在有这样的需求,可以有如下的几种方式解决:

  • 使用UTF-8的字符集
  • 使用对应字符的Unicode编码
  • 使用数组组装
  • 使用原始HTML
  • {['First ', ·, ' Second']}

    如果你在JSX中使用了不存在于HTML规范的属性,这个属性是会被忽略的,你需要使用 data-方式来自定义属性。

    关于支持的标签,属性,以及可访问性属性前缀的列表:

  • React支持的标签,属性
  • 可访问性属性前缀列表
  • 小编还为您整理了以下内容,可能对您也有帮助:

    React-JSX中如何实现Class与Style的动态绑定(附实例)

    本篇文章给大家带来的内容是关于React-JSX中如何实现Class与Style的动态绑定(附实例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

    摘要:操作元素的 class 列表和内联样式是数据绑定的一个常见需求,频繁操作dom元素会降低javascript性能,为了实现高性能js,动态绑定class和style是高素养程序员的必选。本文以React-JSX语法为基础,结合其它框架的实现方法,介绍如何实现ClassName 与 Style 的动态绑定。

    注:本文实例都已经过验证,错误的请广大道友批评指正

    绑定 HTML Class对象语法我们可以传给 className 一个对象,以动态地切换 class:

    注:使用类似vue、小程序等对象语法是不支持的

    错误例子:

    render(){

    return <p className={ 'box-color':this.state.isError }>hello world</p>

    }可以实现的语法如下:

    1、使用逻辑运算符css文件

    .box-color {

    color:red;

    }js文件

    render(){

    return <p className={ this.state.isError && 'box-color' }>hello world</p>

    }2、使用三元运算符css文件

    .box-show {

    display: block;

    }

    .box-hide {

    display: none;

    }render(){

    return <p className={ this.state.isShow ? 'box-show' : 'box-hide' }>hello world</p>

    }3、使用函数绑定的数据对象也不必内联定义在模板里:可以定义一个函数,类似vue中的computed钩子函数

    js文件

    getIsError() {

    return this.state.isError ? 'box-color' : '';

    }

    render(){

    return <p className={ this.getIsError() }>hello world</p>

    }注:下面这种对象变量写法是不支持的,也不会报错,控制台className显示为[object object],无效。

    const classObj = {

    'box-show': this.state.isShow,

    'box-color': this.state.isError

    }

    render(){

    return <p className={ classObj }>hello world</p>

    }一般在项目逻辑比较复杂的场景中使用函数绑定方法,使用过多会使得视图层和逻辑层交杂混乱,难以阅读和维护,建议使用逻辑运算符和三元运算符方法动态绑定Class。

    数组语法React-JSX语法不支持className数组语法,尝试样例:

    css文件

    .box-hide {

    display: none;

    }

    .box-color {

    color:red;

    }js文件

    this.state = {isShow: false}

    render(){

    return <p className={ this.state.isShow ? 'box-color' : [ 'box-color', 'box-hide'] }>hello world</p>

    }控制台显示结果(无效,中间多了个逗号):

    <p class="box-color, box-hide">hello world</p>注:既然不支持数组语法,你只能将“box-color”中的样式复用到“box-hide”中,使用三元运算符来表示,这样无形中增加了css代码量。

    绑定内联样式对象语法style对象语法比clasName对象更加直观,处理的功能更加简单,逻辑运算符方法和函数绑定方法可以参考className的实现,下面只介绍三元运算符的使用:

    三元运算符类似Vue的vue-if、微信小程序的wx-if指令,可以用style三元运算符动态实现

    js文件

    render(){

    return <p style={ this.state.isShow ? {display: 'inline-block'} : { display: 'none'} }>hello world</p>

    }数组语法React-JSX语法也不支持style数组语法,尝试样例:

    js文件

    render(){

    return <p style={ this.state.isShow ? {color: 'red'} : [{color: 'red'}, {display: 'inline-block'}] }></p>

    }控制台显示结果(无效):

    <p></p>总之,为了高质量的完成项目需求,应付越来越复杂的业务场景,那种大量操作dom元素,随意命名一个样式变量,然后绑定到class和style的做法是不提倡的。

    相关文章推荐:

    html实现一个简单的注册页面(附代码)

    link标签链接CSS和@import加载有什么区别?

    如何在 React 中运用 CSS

    我来写例子吧;然后把我webpack.config.js配置信息。

    react的css开发,一般采用模块化的形式进行。一般react中css可以分为三部分,

    快发环境给予node.js、模块化构建用webpack.

    第一:全局部分:比如base.css(用来通用的css,如:.clearfix、.mt10、.mt05之类的)。这个文件可以直接在入口文件如(index.html)中直接用<link href>的形式直接引入

    第二:通用部分:比如我可以把整个webapp需要用到的按钮样式作为一个样式写到一个文件里如:common/button.css,写法的话遵循模块化开发的方式进行(composes);

    贴端代码如下:

    .btn {

    height: 35px;

    line-height: 35px;

    border-radius: 2px;

    display: inline-block;

    text-align: center;

    user-select: none;

    text-align: center;

    box-sizing: border-box;

    font-size: 14px;

    }

    .btn-primary {

    composes : btn;

    border: 1px solid #E0E0E0;

    background-image: -webkit-linear-gradient(top, #f9f9f9, #e7e9eb);

    background-repeat: repeat-x;

    color: #333;

    }

    .btn-blue {

    composes : btn;

    border: 1px solid #0B62BD;

    background-image: -webkit-linear-gradient(top, #0e7bef, #0d73da);

    background-repeat: repeat-x;

    color: #fff;

    }

    第二:组件内的css:比如我们写了一个confirm的通用组件,那么

    comfirm组件的目下应该包含两个文件comfirm.js 和 comfirm.css

    在comfirm.js中用var Styles = require('./confirm.css');的形式进行引用。

    在render的时候进行调用调用形式:<button className={Styles['btn-primary']}>基础按钮</button>

    写组件完成后,比如我在一个编辑页面中需要用到confirm组件,那么就可以直接requre。

    confirm.css如何开发呢?一般采用composes的方式进行(比如我confirm组件中有用到button,那么就可以引用通用的button),然后可以基于composes后的进行修改,比如颜色等等。贴一段代码如下:

    .btn-cancel{

    composes : btn-primary from '../style/button.css';

    width:100px;

    margin-right: 10px;

    }

    .btn-confirm{

    composes : btn-blue from '../style/button.css';

    width:100px;

    margin-left: 10px;

    }

    第三:就是行内样式了,一般会用得比较少。

    webpack配置信息,涉及到样式内图片的解析

    /**

    * webpack 配置文件

    * 配置项、入口文件、输出项信息

    */

    var path = require('path');

    var webpack = require('webpack');

    var admin_components_dir = path.join(__dirname, 'admin/script/components/');

    //重定向文件

    var alias= {

    Login : admin_components_dir + 'login/Login.js',

    Layout : admin_components_dir + 'layout/Layout.js',

    Article : admin_components_dir + 'article/Article.js',

    Pager : admin_components_dir + 'common/Pager/Pager.js',

    Tip : admin_components_dir + 'common/Tip/Tip.js',

    Confirm : admin_components_dir + 'common/Confirm/Confirm.js',

    Select : admin_components_dir + 'common/Select/Select.js',

    ArticleForm : admin_components_dir + 'article/ArticleForm.js',

    Editor : admin_components_dir + 'common/Editor/Editor.js',

    CheckBox : admin_components_dir + 'common/CheckBox/CheckBox.js'

    };

    var config = {

    devtool: 'inline-source-map',

    entry: [

    'webpack-dev-server/client?http://127.0.0.1:4000',

    'webpack/hot/only-dev-server',

    './admin/script/temp.js'

    ],

    output: {

    path: path.join(__dirname, 'admin/dist/'),

    filename: 'app.js',

    publicPath: '/static/'

    },

    resolve: {

    alias: []

    },

    mole: {

    noParse : [],

    loaders: [{

    test: /\.jsx?$/,

    loaders: ['react-hot', 'babel'],

    include: path.join(__dirname,'admin/script/')

    },{

    test: /\.css$/,

    exclude: [

    path.resolve(__dirname, 'node_moles')

    ],

    loaders: ['style', 'css?moles&localIdentName=[name]_[local]_[hash:base64:5]','autoprefixer?{browsers:["> 5%", "ie 9"]}']

    },{

    test: /\.(svg|png|jpg|jpeg|gif)$/i,

    loaders: ['file', 'image-webpack?bypassOnDebug&optimizationLevel=7&interlaced=false']

    }

    ]

    },

    plugins: [

    new webpack.HotMoleReplacementPlugin(),

    new webpack.NoErrorsPlugin()

    ]

    }

    //重定向文件赋值

    config.resolve.alias = alias;

    mole.exports = config;

    webpack中有css的命名规则、css代码自动补全(就是不用写浏览器前缀了)等配置

    这样第二、第三中的css都会打包到app.js中,入口文件(如:index.html)只要用<script src>的形式引用即可

    React全家桶怎样搭建后台管理系统


    这次给大家带来React全家桶怎样搭建后台管理系统,React全家桶搭建后台管理系统的注意事项有哪些,下面就是实战案例,一起来看一下。
    引子

    学生时代为了掌握某个知识点会不断地做习题,做总结,步入岗位之后何尝不是一样呢?做业务就如同做习题,如果‘课后'适当地进行总结,必然更快地提升自己的水平。
    由于公司采用的react+node的技术栈,于是就完成了一个reactSPA小项目,计划日后把平时工作中遇到的业务以及学习中遇到有趣的东西给抽象成demo展示出来。目前该项目只是把雏形搭好,效果如下。在此文的基础上,写了篇新文章使用React全家桶搭建一个后台管理系统,欢迎围观。(附注:因为项目不时更新,文章不一定会即时更新,所以以实际的项目为准)



    其实这套界面风格不仅仅可以作为后台管理系统界面,也可以修改成一个可以展示项目并且美观的博客。项目地址在这里(本地跑效果更佳),如果有好的意见欢迎提issue或pr。



    项目的初始结构和构造原因已罗列如上,由于过些日子会引人ts,所以项目结构必然还会改动,但肯定基于这基本雏形扩展的。

    下面对目录结构作以下说明

    项目最初始是用create-react-app初始化的,create-react-app 是*官方提供的react脚手架,也是业界最优秀的 React 应用开发工具之一;
    中间件目录到时候可以引人日志中间件等;container和components存放的都是react组件,区别是:只要和主页样式有关的组件就放在container中,和功能有关的模块(比如我实现分装的表格组件、弹出输入框组件等)就应放到components中;前端有些通用配置最好是存到全局(浏览器)中,这样调用起来就不用引用了,方便;ajax模块需要自己实现的原因是到时候要是自己需要有跨域cors之类的需求,需要自定义多种Ajax请求(用fetch的情况下,未来fetch会越来越强大)
    技术栈相关

    虽然用到的技术栈众多,但是自己也谈不上熟练运用,多半是边查API边用的,所以只罗列些自己用相关的技术栈解决的点;

    webpack(2.6)

    ①按需加载:

    babel-plugin-import 是一个用于按需加载组件代码和样式的 babel 插件(原理),在config/webpack.config.dev.js 文件中作如下修改:
    {
    test: /.(js|jsx)$/,
    include: paths.appSrc,
    loader: 'babel',
    query: {
    plugins: [
    ['import', [{ libraryName: "antd", style: 'css' }]],
    ],
    cacheDirectory: true
    }
    },
    ②引人less:

    首先引人 less-loader 来加载 less 样式,同时修改 config/webpack.config.dev.js 文件
    loaders: [
    {
    exclude: [
    /.html$/,
    /.(js|jsx)$/,
    + /.less$/,
    /.css$/,
    /.json$/,
    /.svg$/
    ],
    loader: 'url',
    },
    ...
    // Process JS with Babel.
    {
    test: /.(js|jsx)$/,
    include: paths.appSrc,
    loader: 'babel',
    query: {
    plugins: [
    - ['import', [{ libraryName: "antd", style: 'css' }]],
    + ['import', [{ libraryName: "antd", style: true }]], // 加载 less 文件
    ],
    },
    ...
    + // 解析 less 文件,并加入变量覆盖配置
    + {
    + test: /.less$/,
    + loader: 'style!css!postcss!less?{modifyVars:{"@primary-color":"#1DA57A"}}'
    + },
    ]
    这里利用了 less-loader 的 modifyVars 来进行主题配置, 变量和其他配置方式可以参考 配置主题 文档。

    ③一键发布到gh-pages:

    用到了gh-pages,使用 npm run deploy 一键发布到自己的gh-pages上,姑且把gh-pages当成生产环境吧,所以在修改config/webpack.config.dev.js 文件的同时也要对config/webpack.config.prod.js作出一模一样的修改。

    ps:尽管我是这样发布到gh-pages的,该项目的gh-pages展示地址为这里,在gh-pages上展示图明显比本地大了好些像素,如果有朋友知道是为什么,不吝赐教啊。

    ④引用路径的缩写:
    resolve: {
    fallback: paths.nodePaths,
    alias: {
    'react-native': 'react-native-web',
    components: path.resolve(dirname, '..') + '/src/common/components',
    container: path.resolve(dirname, '..') + '/src/common/container',
    images: path.resolve(dirname, '..') + '/src/common/images',
    pages: path.resolve(dirname, '..') + '/src/common/pages',
    utils: path.resolve(dirname, '..') + '/src/common/utils',
    data: path.resolve(dirname, '..') + '/src/server/data',
    }
    },
    配置了引用路径的缩写后,就可以在任意地方如这样引用,比如



    antd(2.10)

    antd是(蚂蚁金服体验技术部)经过大量的项目实践和总结,沉淀出的一个中台设计语言 Ant Design,使用者包括蚂蚁金服、阿里巴巴、口碑、美团、滴滴等一系列知名公司,而且我从他们的设计理念也学到了很多关于UI、UX的知识。

    该项目采用的是antd最新的版本2.10.0,由于2.x的版本和1.x的版本还是相差蛮大的,之前参考的项目(基于1.x)改起来太费劲,所以在组件那块就干脆自己重新封装了一遍。这部分知识点我建议还是看文档,文档解决不了扒扒源码。

    react-router(4.x)

    react-router 4.x和2.x的差异又是特别的大,召唤文档,网上基本上都还是2.x的教程,看过文档之后,反正简而言之其就是要让使用者更容易上手。印象最深的是以前嵌套路由写法在4.x中写到同层了。如下示例他们的效果是相同的。

    2.x:
    <Route path="/" component={App}>
    <Route path="/aaaa" component={AAAA} />
    <Route path="/bbbb" component={BBBB} />
    </Route>
    4.x:
    <Route path="/" component={App} />
    <Route path="/aaaa" component={AAAA} />
    <Route path="/bbbb" component={BBBB} />
    还有更多的特性和API的出现,期待有更好的分析文章的出现,有机会我也会来总结下react-router(4.x)和(2.x)的差异。

    fetch

    先推荐这篇文章《传统Ajax已死,Fetch永生》,再推荐API;

    fetch是个好东西,好在简单,除了promise最基本的用法,还能这样写
    fetch(url).then(response => response.json())
    .then(data => console.log(data))
    .catch(e => console.log("Oops, error", e))try {
    let response = await fetch(url);
    let data = await response.json();
    console.log(data);
    } catch(e) {
    console.log("Oops, error", e);
    }
    但是其简洁的特点是为了让我们可以自定义其扩展,还是其本身就还不完善呢?我在调用JSONP的请求时,发现用fetch掉不同,后来在文档上才发现其不支持JSONP的调用,所幸社区还是很给力的找到了fetch-jsonp这个模块,实现了对百度音乐接口的JSONP调用。fetch-jsonp使用也和fetch类似,代码如下
    fetchJsonp(url,{method: 'GET'})
    ??.then((res) =>res.json())
    ??.then((data) => {})
    rex

    使用了rex也已经有段时日了,我对rex的定义就是更好的管理组件的状态,没有rex的时候就像现在这个应用一样,逻辑少状态变化也还不太复杂,但是一旦逻辑复杂起来,各种组件状态、界面耦合起来,就容易出岔子,那rex就是为了解决这个而生的,让我们可以更多地关注UI层,而降低对状态的关注。之前也写了些rex的文章,纸上得来终觉浅,绝知此事要躬行。

    --------------------------更新---------------------------

    已经在项目中加入了rex技术栈。

    项目的一些待扩展计划

    封装组件

    不管组件封装得好不好,个人感觉其是提高水平很高效的方法,多练,继续封装出各式各样的功能组件。

    typescript

    公司大概会在6月份开始,新的项目就要采用ts开发了,所以我也到时会在该项目中引人ts的语法,我现在的感觉是使用ts后,前后端对接会更加轻松,不会有一些类型不匹配的低级错误,而且antd貌似和ts也能兼容得蛮好。

    测试框架

    这部分其实我还是没什么经验的,先写上吧,有机会会拿这个项目开刀,并写心得。
    相信看了本文案例你已经掌握了方法,更多精彩请关注Gxl网其它相关文章!
    推荐阅读:



    React全家桶怎样搭建后台管理系统


    这次给大家带来React全家桶怎样搭建后台管理系统,React全家桶搭建后台管理系统的注意事项有哪些,下面就是实战案例,一起来看一下。
    引子

    学生时代为了掌握某个知识点会不断地做习题,做总结,步入岗位之后何尝不是一样呢?做业务就如同做习题,如果‘课后'适当地进行总结,必然更快地提升自己的水平。
    由于公司采用的react+node的技术栈,于是就完成了一个reactSPA小项目,计划日后把平时工作中遇到的业务以及学习中遇到有趣的东西给抽象成demo展示出来。目前该项目只是把雏形搭好,效果如下。在此文的基础上,写了篇新文章使用React全家桶搭建一个后台管理系统,欢迎围观。(附注:因为项目不时更新,文章不一定会即时更新,所以以实际的项目为准)



    其实这套界面风格不仅仅可以作为后台管理系统界面,也可以修改成一个可以展示项目并且美观的博客。项目地址在这里(本地跑效果更佳),如果有好的意见欢迎提issue或pr。



    项目的初始结构和构造原因已罗列如上,由于过些日子会引人ts,所以项目结构必然还会改动,但肯定基于这基本雏形扩展的。

    下面对目录结构作以下说明

    项目最初始是用create-react-app初始化的,create-react-app 是*官方提供的react脚手架,也是业界最优秀的 React 应用开发工具之一;
    中间件目录到时候可以引人日志中间件等;container和components存放的都是react组件,区别是:只要和主页样式有关的组件就放在container中,和功能有关的模块(比如我实现分装的表格组件、弹出输入框组件等)就应放到components中;前端有些通用配置最好是存到全局(浏览器)中,这样调用起来就不用引用了,方便;ajax模块需要自己实现的原因是到时候要是自己需要有跨域cors之类的需求,需要自定义多种Ajax请求(用fetch的情况下,未来fetch会越来越强大)
    技术栈相关

    虽然用到的技术栈众多,但是自己也谈不上熟练运用,多半是边查API边用的,所以只罗列些自己用相关的技术栈解决的点;

    webpack(2.6)

    ①按需加载:

    babel-plugin-import 是一个用于按需加载组件代码和样式的 babel 插件(原理),在config/webpack.config.dev.js 文件中作如下修改:
    {
    test: /.(js|jsx)$/,
    include: paths.appSrc,
    loader: 'babel',
    query: {
    plugins: [
    ['import', [{ libraryName: "antd", style: 'css' }]],
    ],
    cacheDirectory: true
    }
    },
    ②引人less:

    首先引人 less-loader 来加载 less 样式,同时修改 config/webpack.config.dev.js 文件
    loaders: [
    {
    exclude: [
    /.html$/,
    /.(js|jsx)$/,
    + /.less$/,
    /.css$/,
    /.json$/,
    /.svg$/
    ],
    loader: 'url',
    },
    ...
    // Process JS with Babel.
    {
    test: /.(js|jsx)$/,
    include: paths.appSrc,
    loader: 'babel',
    query: {
    plugins: [
    - ['import', [{ libraryName: "antd", style: 'css' }]],
    + ['import', [{ libraryName: "antd", style: true }]], // 加载 less 文件
    ],
    },
    ...
    + // 解析 less 文件,并加入变量覆盖配置
    + {
    + test: /.less$/,
    + loader: 'style!css!postcss!less?{modifyVars:{"@primary-color":"#1DA57A"}}'
    + },
    ]
    这里利用了 less-loader 的 modifyVars 来进行主题配置, 变量和其他配置方式可以参考 配置主题 文档。

    ③一键发布到gh-pages:

    用到了gh-pages,使用 npm run deploy 一键发布到自己的gh-pages上,姑且把gh-pages当成生产环境吧,所以在修改config/webpack.config.dev.js 文件的同时也要对config/webpack.config.prod.js作出一模一样的修改。

    ps:尽管我是这样发布到gh-pages的,该项目的gh-pages展示地址为这里,在gh-pages上展示图明显比本地大了好些像素,如果有朋友知道是为什么,不吝赐教啊。

    ④引用路径的缩写:
    resolve: {
    fallback: paths.nodePaths,
    alias: {
    'react-native': 'react-native-web',
    components: path.resolve(dirname, '..') + '/src/common/components',
    container: path.resolve(dirname, '..') + '/src/common/container',
    images: path.resolve(dirname, '..') + '/src/common/images',
    pages: path.resolve(dirname, '..') + '/src/common/pages',
    utils: path.resolve(dirname, '..') + '/src/common/utils',
    data: path.resolve(dirname, '..') + '/src/server/data',
    }
    },
    配置了引用路径的缩写后,就可以在任意地方如这样引用,比如



    antd(2.10)

    antd是(蚂蚁金服体验技术部)经过大量的项目实践和总结,沉淀出的一个中台设计语言 Ant Design,使用者包括蚂蚁金服、阿里巴巴、口碑、美团、滴滴等一系列知名公司,而且我从他们的设计理念也学到了很多关于UI、UX的知识。

    该项目采用的是antd最新的版本2.10.0,由于2.x的版本和1.x的版本还是相差蛮大的,之前参考的项目(基于1.x)改起来太费劲,所以在组件那块就干脆自己重新封装了一遍。这部分知识点我建议还是看文档,文档解决不了扒扒源码。

    react-router(4.x)

    react-router 4.x和2.x的差异又是特别的大,召唤文档,网上基本上都还是2.x的教程,看过文档之后,反正简而言之其就是要让使用者更容易上手。印象最深的是以前嵌套路由写法在4.x中写到同层了。如下示例他们的效果是相同的。

    2.x:
    <Route path="/" component={App}>
    <Route path="/aaaa" component={AAAA} />
    <Route path="/bbbb" component={BBBB} />
    </Route>
    4.x:
    <Route path="/" component={App} />
    <Route path="/aaaa" component={AAAA} />
    <Route path="/bbbb" component={BBBB} />
    还有更多的特性和API的出现,期待有更好的分析文章的出现,有机会我也会来总结下react-router(4.x)和(2.x)的差异。

    fetch

    先推荐这篇文章《传统Ajax已死,Fetch永生》,再推荐API;

    fetch是个好东西,好在简单,除了promise最基本的用法,还能这样写
    fetch(url).then(response => response.json())
    .then(data => console.log(data))
    .catch(e => console.log("Oops, error", e))try {
    let response = await fetch(url);
    let data = await response.json();
    console.log(data);
    } catch(e) {
    console.log("Oops, error", e);
    }
    但是其简洁的特点是为了让我们可以自定义其扩展,还是其本身就还不完善呢?我在调用JSONP的请求时,发现用fetch掉不同,后来在文档上才发现其不支持JSONP的调用,所幸社区还是很给力的找到了fetch-jsonp这个模块,实现了对百度音乐接口的JSONP调用。fetch-jsonp使用也和fetch类似,代码如下
    fetchJsonp(url,{method: 'GET'})
    ??.then((res) =>res.json())
    ??.then((data) => {})
    rex

    使用了rex也已经有段时日了,我对rex的定义就是更好的管理组件的状态,没有rex的时候就像现在这个应用一样,逻辑少状态变化也还不太复杂,但是一旦逻辑复杂起来,各种组件状态、界面耦合起来,就容易出岔子,那rex就是为了解决这个而生的,让我们可以更多地关注UI层,而降低对状态的关注。之前也写了些rex的文章,纸上得来终觉浅,绝知此事要躬行。

    --------------------------更新---------------------------

    已经在项目中加入了rex技术栈。

    项目的一些待扩展计划

    封装组件

    不管组件封装得好不好,个人感觉其是提高水平很高效的方法,多练,继续封装出各式各样的功能组件。

    typescript

    公司大概会在6月份开始,新的项目就要采用ts开发了,所以我也到时会在该项目中引人ts的语法,我现在的感觉是使用ts后,前后端对接会更加轻松,不会有一些类型不匹配的低级错误,而且antd貌似和ts也能兼容得蛮好。

    测试框架

    这部分其实我还是没什么经验的,先写上吧,有机会会拿这个项目开刀,并写心得。
    相信看了本文案例你已经掌握了方法,更多精彩请关注Gxl网其它相关文章!
    推荐阅读:



    在React中如何实现组件内部通信

    这篇文章主要介绍了React数据传递之组件内部通信的方法,现在分享给大家,也给大家做个参考。

    1. 概述

    脱离初级前端一段时间后会发现,写样式的时间越来越少,处理数据的时间越来越多。处理数据的过程也就是实现业务逻辑的过程,这在项目中无疑是最重要的。

    所以学习前端框架,了解完基本语法后,接下来就要学习其如何进行数据传递。

    Angular 设计之初的一大亮点就是实现了数据的双向绑定,使用 Vue 一段时间后发现,所谓数据的双向绑定,组件内部唯一的应用场景就是 form 表单(input,textarea,select, radio),而这种场景下的数据双向绑定,即便框架内部没有实现,自己实现起来也非常简单。明白这一点后感觉之前认为 React 没有实现数据双向绑定很 low 的想法很幼稚。

    对于 React 的数据传递,涉及两方面的内容:

    组件内部的数据传递,典型的应用场景包括如何实现 form 表单双向数据绑定、如何绑定事件;

    组件间的数据传递。 包括父组件往子组件传递数据、子组件往父组件传递数据以及兄弟组件之间传递数据。

    本文先讨论组件内部的数据传递。

    2. 组件内部数据传递

    React 组件内部通信主要分为两部分:数据展示与事件处理。

    2.1 数据展示

    组件内部数据的展示和更新都是通过 state 来实现的,如果要使用 state 必须使用 ES6 的 class 定义组件。数据更新在双向数据绑定部分探讨,这部分仅讨论展示初始化数据。

    如果你熟悉 Vue,React 的 state 对象相当于 Vue 的 data 对象

    下面是一个纯展示数据的示例:

    class App extends Component {

    constructor(props) {

    super(props);

    // 初始化 state

    this.state = {

    inputValue: "test",

    };

    }

    render() {

    // 注意,在 react 中,DOM 元素是对象,所以使用‘()'包住

    return (

    <p className="App">

    <p>{this.state.inputValue}</p>

    </p>

    );

    }

    }在通过 class 定义的 React 组件中,除了生命周期钩子函数, constructor() 和 render() 着两个方法也是自动执行的,先执行 constructor() ,执行 constructor() 的同时也是再为 render() 渲染 DOM 做数据准备。

    实际上 constructor() 函数是组件生命周期中调用的第一个函数。

    2.2 事件

    2.2.1 与 DOM 中事件的异同

    在 React 中处理事件和在 DOM 中处理事件类似,有两点不同:

    React 中通过驼峰命名法命名事件,而不是全是小写字母;

    在 JSX 中直接传递函数作为事件处理程序,而不是字符串。

    第 2 点不同有坑,后面细说

    举个例子,HTML中的事件:

    <button onclick="activateLasers()">

    Activate Lasers

    </button>React 中的事件:

    // 因为 jsx 中'{}'里面代表函数表达式,

    // 所以传递给 onClick 的实际是函数 activateLasers 的函数体部分,

    // 因此需要指定 this 指向,不然会报错

    <button onClick={activateLasers}>

    Activate Lasers

    </button>2.2.2 存在的坑

    直接传递 function 作为 event handler 需要指定函数的执行环境,即需要手动绑定 this ,不然会报 this 为 undefined 的错。见下面的例子:

    class App extends Component {

    constructor(props) {

    super(props);

    this.state = {

    isToggleOn: true,

    };

    // 手动绑定 this

    this.handleClick = this.handleClick.bind(this);

    }

    handleClick() {

    // 如果不在 constructor() 方法中手动绑定 this,直接将其作为事件处理程序 this 为 undefined

    console.log(this);

    this.setState(prevState => ({

    isToggleOn: !prevState.isToggleOn

    }));

    }

    render() {

    return (

    <p className="App">

    <button onClick={this.handleClick}>

    {this.state.isToggleOn ? "on" : "off"}

    </button>

    </p>

    );

    }

    }2.2.3 为什么会有坑

    React 官网 说这个锅要 JS 原生语法来背,其实不尽然,React 实在 JS 语法早已确定的情况下设计了这样的事件系统,如果一定要有人站出来背锅,他们五五分吧。

    1, JS原生语法存在的问题

    JS语法中有这样的规则:如果将一个函数的函数体(没有 () )赋值给另一个变量,函数体内部的 this 指向可能会发生变化。会不会变化取决于函数和被赋值的变量是否处于同一个作用域(相同的执行环境)中,但实际使用中,将一个函数赋值给相同作用域的变量没有意义,那样的话直接使用那个函数就好,没必要在赋值给另一个变量。

    this 指向不发生改变的没有意义的例子(为了方便说明,直接使用 var 操作符):

    var fn = function () {

    console.log(this);

    };

    var a = fn;

    fn(); // window

    a(); // window

    this 指向发生改变的例子:

    var fn = function () {

    console.log(this);

    };

    // 将函数体赋值给一个对象的属性,函数执行时 this 和定义时指向不同

    var o = {

    a: fn,

    };

    fn(); // window

    o.a(); // o,即{a:f}如果想要在将函数体赋值另一个变量的同时把原函数的 this 指向也一块赋值过去,就需要在赋值的过程中进行绑定 this 的操作,如下:

    var fn = function () {

    console.log(this);

    };

    // fn 在赋值的同时将内部的 this 打包一块赋值给了 a

    var o = {

    a: fn.bind(this),

    };

    fn(); // window

    o.a(); // window通常在将函数体赋值给变量的时候为了避免 this 出错,都会进行 绑定执行环境的操作 ,典型的例子是 var bindId = document.getElementById.bind(document)

    2, JSX 存在的问题

    因为 JSX 中 DOM 元素也是对象,给元素的属性赋值实际是给 DOM 元素对象的属性赋值,见下:

    const element = (

    <button onClick={this.handleClick}>click me</button>

    );等同于

    const element = {

    type: 'button',

    props: {

    onClick: this.handleClick,

    children: 'click me',

    },

    };

    这实际就是 将函数体赋值给一个对象的属性,函数执行时 this 和定义时指向不同 的场景,和原生语法相同的是 this 指向发生了改变,不同的是原生 JS 中不管怎样, this 总归是有个指向的,而 JSX 直接 undefined 。

    所以说不绑定 this 报 undefined 的错不能全怪 JS 原生语法。

    3. 双向数据绑定

    通过 state 传递数据加上事件处理程序便能实现数据的双向绑定,其背后的思想是(以 input 为例):初始化时将 state 中预定义的 state a 赋值给 input,当 input 的 value 发生改变时,触发事件处理程序,将改变后的 value 赋值给状态 a ,React 监测到 state 改变时重新调用 render() 方法,即重新渲染组件,达到双向绑定的目的。

    class App extends Component {

    constructor(props) {

    super(props);

    this.state = {

    inputValue: "test",

    };

    this.changeInput = this.changeInput.bind(this);

    }

    changeInput(e) {

    // 将改变后的 input 值赋值给 inputValue,通过事件对象 $event.target.value 实现

    this.setState({

    inputValue: e.target.value

    });

    }

    render() {

    // input 改变时触发 changeInput

    return (

    <p className="App">

    <input value={this.state.inputValue} onChange={this.changeInput} />

    <p>{this.state.inputValue}</p>

    </p>

    );

    }

    }这里用到了事件对象,React 的事件对象和 JS 原生事件对象保持一致。

    上面是我整理给大家的,希望今后会对大家有帮助。

    相关文章:

    使用Node.js爬虫如何实现网页请求

    使用VueAwesomeSwiper容易出现的问题?

    在angular2中有关Http请求原理(详细教程)

    在node中如何实现http小爬虫

    React性能优化指南

    使用React开发的项目,可以从加载性能和运行时性能两个方面进行优化。

    加载性能优化的目标是让用户更早地看到界面、更早地和应用交互。运行时性能优化目标是降低卡顿,交互更流畅 。

    我们知道React的setState会触发diff和更新。默认是将整个组件树进行对比,但很多情况下diff是不必要的,因为一个子组件的props没有改变,就不需要进行diff工作。

    为了避免这种对没有改变props的子组件进行多余的diff工作的情况,React提供了shouldComponentUpdate这个生命周期钩子, shouldComponentUpdate(nextProps, nextState) 。 这个生命周期钩子如果返回true,则会执行后面的render和diff工作,如果返回false,则React不会向下继续。用户可以在这个生命周期钩子中进行state和props的对比,判断是否需要更新。通常一个组件当前的props与nextProps属性值相同,并且state的属性值也相同,则不需要更新。

    React.PureComponent实现了shouldComponentUpdate这个方法,PureComponent采用了浅比较,

    【 前端面试刷题网站 : 灵题库 ,收集大厂面试真题,相关知识点详细解析。】

    对应class组件的PureComponent,函数组件有React.memo方法实现类似的效果。

    React.memo

    由于默认的PureComponent和memo都是默认用的浅比较。因此如果对象层级较深,会导致漏更新。

    解决办法是,如果对象改变,重新创建一个对象,如果数组改变,重新创建一个数组,解构赋值可以很容易地实现这一点: {...oldData};[...oldArr] 。

    用户可以自己实现shouldComponentUpdate以自定义比较逻辑,对于函数式组件,则可以通过React.memo的第二个参数来定义比较逻辑。

    如果想要精确地判断区别,除了手动判断,还有一个自动化程度比较高的方式:不可变数据,这时一个不可变数据的JS实现: immutable-js 。

    只有发生改动的节点会创建新的引用,因此相应的组件才会执行render和diff。

    结论:最佳实践是PureComponent/React.memo + 不可变数据。

    Fragment可以避免不必要的dom节点。

    JSX的标签表达式要求有一个根节点

    如果就想让表达式返回一个标签列表,不应该在最外层加一个根节点,应该使用Fragment。

    也可以简写

    在注册事件回调时候,不要用匿名函数或者用bind生成新函数,应该用箭头函数或者构造里面bind,最好是构造函数里面bind(因为可以继承)。

    当我们需要注册事件回调时候,可以写成这样写:

    或者

    上面这两种:匿名函数和bind表达式,都不推荐 。因为匿名函数的写法会在每次调用render时候都创建新的函数,而bind表达式也会在每次调用时候创建一个新的函数,React做diff时候发现事件回调函数不同,就会将旧的函数解绑(这样还会触发GC)并且绑定新的函数。

    因此最好这样实现

    或者

    更推荐后者,因为我们知道:

    class Test {log = () => {};} 和 class Test {log() {}}

    这两种写法的区别在于前者log是类的实例方法,而后者是原型方法,因此在构造函数中绑定,能让其他使用原型继承方法继承Test的组件可以继承到log方法。

    如果使用函数式组件,应该使用useCallback这个hook。关于useCallback的使用,请参考本知识库的React进阶一文。

    因为React在解析JSX时候需要将style对象解析成css style字符串。更推荐将样式写在CSS中。

    如果在render方法进行setState,可能导致循环地进行diff工作。

    让条件分支中只包含需要改动的元素,不包含不需要改动的元素,防止diff子节点和更新节点时候增加不必要的操作,消耗性能。

    示例:

    应该改成下面这种写法:

    我们知道,Vue中有计算属性的能力,能够根据依赖的数据计算出我们关心的数据,而且有缓存的能力:依赖的值不变的话,不需要计算,直接返回结果。

    React如果想要实现根据依赖的数据计算我们关心的数据,方法很简单。

    但是这样实现没有缓存值的能力,当计算耗时较长时候会影响性能。

    如何实现缓存值的能力呢?

    可以使用memorize-one这个库: https://www.npmjs.com/package/memorize-one

    如果使用函数式组件,可以使用useMemo来实现。关于useMemo库的使用,请参考本讲义中React进阶一文。

    react-vitualize

    启用concurrent mode之后,React会采取可中断渲染,让大规模的diff计算不会影响到界面的渲染,保证渲染和交互的流畅性。

    使用Suspense组件可以在加载局部组件时候有更好的切换加载体验。

    concurrent详细的介绍请阅读本系列concurrent mode文章。

    不使用key或者用index作为key,都可能使列表在变化时候,让React无法辨别前后item对应关系,只能遍历对比,更新属性,这样可能会有多余的操作,造成性能损耗。

    为什么需要key呢?我会单独写一篇文章详细讲解。

    React官方提供了一个性能检测工具: react-addons-perf 。

    这个工具可以在渲染React应用时候打印各个组件的各种耗时,用来分析性能浪费。

    其中比较重要的一个方法是printWasted(),可以打印并未更新组件的渲染操作,如果发现你的组件花了很长时间render和diff,但组件视图实际并未发生变化,那就要考虑是否需要引入PureComponent等优化渲染性能了。

    微宠网还为您提供以下相关内容希望对您有帮助:

    如何在 React 中运用 CSS

    第一:全局部分:比如base.css(用来通用的css,如:.clearfix、.mt10、.mt05之类的)。这个文件可以直接在入口文件如(index.html)中直接用&lt;link href&gt;的形式直接引入 第二:通用部分:比如我可以把整个webapp需要用到的按钮样式作为一个样式写到一个文件里如:common/button.css,写法的话遵循模块...

    React-JSX中如何实现Class与Style的动态绑定(附实例)

    本文以React-JSX语法为基础,结合其它框架的实现方法,介绍如何实现ClassName 与 Style 的动态绑定。注:本文实例都已经过验证,错误的请广大道友批评指正绑定 HTML Class对象语法我们可以传给 className 一个对象,以动态地切换 class:注:使用类似vue、小程序等对象语法是不支持的错误例子:render(){ retu...

    如何在react.js 中利用for循环之类的输出html

    在react中,可以用遍历直接循环输出。react使用的是es6语法,建议先学习es6然后再使用react。以下是遍历添加option,然后下面就可以直接读取了。其中stationData是map数据,station是当前循环遍历的单条数据。let Options = stationData.map(station =&gt; &lt;Option key={station.SiteUid}&gt;{station.SiteName}&lt;/Op...

    react中,import导入文件怎么理解,与css中的import有区别吗

    在React的世界里,结构和逻辑交由JSX文件组织,React将模板内嵌到逻辑内部,实现了一个JS代码和HTML混合的JSX。结构在JSX文件中,可以直接通过 React.createClass 来定义组件:var CustomComponent = React.creatClass({ render: function(){ return (&lt;div className="custom-component"&gt;&lt;/div&gt;); }});通过这种方式可以...

    reactnative实战工程中怎样使用activityindicator

    React native充分利用了Facebook的现有轮子,是一个很优秀的集成作品,并且我相信这个团队对前端的了解很深刻,否则不可能让Native code「退居二线」。 对应到前端开发,整个系统结构是这样: JSX vs HTML CSS-layout vs css ECMAScript 6 vs ECMAScript 5 React native View vs DOM 无需编译,我在第一次编译了ipa装...

    杂记2:React的亮点

    虚拟DOM 对于三大框架 React、Angular和Vue这不算很稀奇的事情。只是对比jQuery有优势。颠覆传统的前端开发 意味着开发者要学习一些新的开发范式。比如传统前端遵循html/css/js分离,而React因为组件化,所以都使用JSX把html写在了JavaScript中。Vue号称自己的侵入性比 React 和 Angular 小,而且仍然...

    React性能优化指南

    React.memo 由于默认的PureComponent和memo都是默认用的浅比较。因此如果对象层级较深,会导致漏更新。解决办法是,如果对象改变,重新创建一个对象,如果数组改变,重新创建一个数组,解构赋值可以很容易地实现这一点: {...oldData};[...oldArr] 。用户可以自己实现shouldComponentUpdate以自定义比较逻辑...

    2024最新React面试题篇,赶紧学起来

    7. 控制组件的奥秘:讨论如何通过高级技术如Context API或Redux来实现组件间的更精细控制。8. JSX的力量:揭示JSX语法在React中的核心地位,它是如何将HTML与JavaScript无缝结合的。以上只是React面试的冰山一角,持续关注前端知识前沿,小蓝将持续分享更多实用的学习资源和实战经验,助你顺利应对面试挑战。

    详解如何使用webpack在vue项目中写jsx语法

    this.msg } &lt;/div&gt; );}但值得注意的是,浏览器默认是解析不了JSX的,它必须要先编译成标准的JavaScript代码才可以运行。就像我们需要将sass或者less编译为CSS代码之后才能运行一样。在Vue中使用JSXVue框架并没有特意地去支持JSX,其实它也没必要去支持,因为JSX最后都会编译为标准的JavaScript代码。

    React项目的css样式,为什么标签选择器和ID选择器可以生效,类选择器不行...

    说将className更改为class的一定是不会React JSX语法的。请忽略。看你代码似乎没问题,请检查css文件是否引入正确路径。是否有相关的webpack loader,例如 css-loader,style-loader等。看看浏览器是否报错。

    Top