aiyoudiao aiyoudiao
  • JavaScript
  • Vue
  • React
  • 低代码
  • 线性系统
  • 暂未分类
  • LeetCode
  • 算法
  • 数据结构
  • 设计模式
  • Other
  • PMP
  • Office
  • 面试
  • Bash
  • 流年往事
  • 经验片段
  • 读书杂感
  • 归档
  • 分类
  • 标签
  • 简介
  • 收藏
  • 有趣
  • 文档

码二

扫微信二维码,认识一下码二吧😉。
  • JavaScript
  • Vue
  • React
  • 低代码
  • 线性系统
  • 暂未分类
  • LeetCode
  • 算法
  • 数据结构
  • 设计模式
  • Other
  • PMP
  • Office
  • 面试
  • Bash
  • 流年往事
  • 经验片段
  • 读书杂感
  • 归档
  • 分类
  • 标签
  • 简介
  • 收藏
  • 有趣
  • 文档
  • JavaScript

  • vue

  • react

    • 16_4

      • React16_4整理-开篇
      • React16_4整理-TodoList
        • 前言
        • 基础语法
        • 响应式设计思想和事件绑定
        • TodoList 新增、删除功能
        • JSX 细节语法补充
        • JSX 中不去转义 手动输入的 Html 标签
        • 拆分组件与组件之间的传值
        • TodoList 代码优化
        • 总结
          • 声明式与命令式开发
          • 与其它框架并存
          • 组件式的开发(组件化)
          • 单向数据流
          • 视图层的框架
          • 函数式编程
      • React16_4整理-上阶
      • React16_4整理-Redux开篇
      • React16_4整理-Redux上阶
      • React16_4整理-实战
    • react心得
    • react设计的哲学
    • react上手知识点(上篇)
    • react上手知识点(下篇)
    • antd
  • 低代码

  • 读书会

  • 线性代数

  • docker

  • auto

  • 杂记

  • 笔记
  • react
  • 16_4
aiyoudiao
2022-04-12

React16_4整理-TodoList

# 前言

React只做两件事,一件事是渲染ui,一件事是响应事件。
mvc和mvvm都是早些年angular的设计理念。react并不是什么mvvm和mvc,它只是一个很小的东西,只做那两件事儿。它只是个工具。backbone才是真正的mvc,它是模仿java的spring,挪到前端来了。

上一篇文章中基础的工程搭建完毕,基础的语法也知悉了,那么开始弄一个todolist 练练手。学任何一门框架或者语言,都可以用todolist来练练手噢,也就是增删改查的逻辑尽快熟悉并上手。

# 基础语法

React 中 JSX 语法:render 函数中只能有一个根节点,所以你写的多个 html 标签必须包含在一个容器中,比如<div></div>中。

如果你不想页面中多一个div包在你众多html标签外面,可以通过引入 import React, {Component, Fragment} from 'react'来引入 Fragment,然后用Fragment替换掉render函数中外层包裹着div,这样就能够在渲染页面时只显示你写的众多html标签。

# 响应式设计思想和事件绑定

你可以通过 this.state={} 来存储数据,这样你就能够在 JSX 中使用了。
如果你想在JSX中使用js的表达式或者变量,你必须使用{}括起来。

在 JSX 语法中如果你给一个标签设置了值,如input标签的value,你设置了{this.state.inputValue},那么你给this.state.inputValue设置了值,就会导致你的输入框中就无法输入值了。

除非你绑定onChange事件,这个onChange事件与onchange事件不同,这是JSX中的,所以你给他添加的方法还是需要用{}括号括起来。

在给事件绑定方法时,必须要这样,onChange= {this.changeHandler.bind(this)},不然this指向会有问题,或者onChange={() => {this.changeHandler()}},因为箭头函数就是匿名函数使用了bind(this)。

事件绑定的方法里你可以通过e.target来获取你输入的值,这时候你可以通过以下的方式来让文本框中的值改变。

    this.setState({this.state.inputValue: e.target.value});

React只能够直接以数据驱动视图,并不能直接以视图来改变数据,而且如果你使用this.state.inputValue= e.target.value;那也是无效的,它只能使用this.setState来进行修改state中的值。它不像vue那种响应式监听,自动给你修改data中的值,这也是它和vue的不同点`。

# TodoList 新增、删除功能

es6中有一个展开运算符: ...,如[...[1,2,3,4]] 会把数组中的元素一个个的展开,变成这样[1,2,3,4],也就是把原数组中的元素放入了新数组中,也可以在对象中使用。

你在this.setState中加的{}里面的成员都会变成this.state的成员。这表示将原来的this.state.list平铺到新的数组中,并且还将this.state.inputValue添加进去。

    this.setState({list: [...this.state.list, this.state.inputValue]});

可以将已经添加的文本框中的值清空掉。

    this.setState({list: [...this.state.list, this.state.inputValue], this.state.inputValue: ''});

在 React 中你做循环渲染标签的时候一定要给这个标签添加一个 key 属性,属性值可以赋值为 index,但是在实际的编程中,使用 index 作为 key 值是一个不好的习惯。

    <ul>
        {
            this.state.list.map((item,index) => {
                retrun (<li key = {index}>{item}</li>)
            })
        }
    </ul>

React 中有一个规则叫immutable ,表示state 不允许我们做任何的改变,不然性能优化方面就会出现问题。

    // 所以你删除的时候不允许直接用下面这种方式
    // this.state.list.splice(index, 1);

    // 需要你拷贝一个副本
    const list = [...this.state.list];
    list.splice(index, 1);
    this.setState({
        list: list
    });

# JSX 细节语法补充

JSX 中大写字母开头的标签表示这是一个组件,小写字母开头的标签表示这是一个html元素。
{/* 注释内容 */} 是 JSX 中的注释
JSX 中添加类名和 style,className = "box",style = { {color: red} }。
JSX 中 使用label标签时使用for时要改为htmlFor

# JSX 中不去转义 手动输入的 Html 标签

也就是页面文本框中输入 <h1>xxxx</h1> 在页面中显示时会被转义成下面这样。

    &it;h1&gt;xxxx&it;/h1&gt;

通过给对应的标签 加上 dangerouslySetInnerHTML = { {__html: <h1>xxx</h1>} },表示危险的设置InnerHTML内容,这样就会存在被xss攻击的可能。

    // 因为写了dangerouslySetInnerHTML 所以li标签对中的item就没必要写了
    <li key={index} dangerouslySetInnerHTML = {{__html:item}}><li>

# 拆分组件与组件之间的传值

组件会变成一个树形的结构,因为一个大的组件中会有很多个小组件,小组件中又有其它的更小的组件。

父组件传递子组件数据的方式,直接在子组件中添加属性。

    // 给子组件传递一个content属性
    <TodoList content = {this.state.inputValue} />

    // 子组件中通过 this.props.属性名来使用
    <div>{this.props.content}<div>

如果你嫌每次绑定事件的方法都写.bind(this),那么你可以把这一步放到constructor中去做,这样可以节约一些性能。

    constructor (props) {
        super(props);
        this.handleClick = this.handleClick.bind(this);
    }

当你给子组件传递父组件中的方法,记得给方法加上一个.bind(this),不然子组件调用时会出现this指向问题。

# TodoList 代码优化

通过代码解构来优化代码。

    const {content} = this.props;
    //上面这行代码表示 将this.props.content 赋值给content
    //const content = this.props.content;

将样式的引入放到引入组件的后面,将事件绑定的方法中需要.bind(this)的写法,统一的放到构造函数中,这样 JSX 中调用方法时就不必每次都.bind(this)了。

    constructor (props) {
        super(props);
        this.handleClick = this.handleClick.bind(this);
    }
    <div onClick = {this.handleClick}></div>

如果你将 遍历列表的操作直接放到JSX中会显得代码过于臃肿,那么你可以写一个方法,然后在JSX中直接调用你写的方法即可。

    <div>{this.getListItem()}</div>

    getListItem(){
        return  this.state.list.map((item,index) => {
            return <li key = {index}>{item}</li>
        })
    }

由于React中的setState是异步操作,所以你其实可以传递函数来替代传递对象。

    // 原来同步的写法
    this.setState({
        list: ['1','2']
    })

    // 现在的异步写法
    this.setState(()=>{
        return {
            list: ['1','2']
        }
    })

    // 再简化一下
    this.setState(()=>({list: ['1','2']}));

如果你使用了 异步写法,那么注意了,如果使用了event对象,那么要将值先保存一下,因为异步的写法获取不到 event对象的,就像for循环里面写函数获取不到每次的i一样。

    handleInput(evnet) {
        const value = event.value;
        this.setState({} => ({inputValue: value}));
    }

当使用了异步的写法后,你可以通过函数里传递过来的参数来替代this.state

        // 再简化一下
    this.setState((preState)=>(
            {
                list: [...preState.list,inputValue],
                inputValue: ''
            }
        )
    );

循环的时候key的属性因该放到循环体的最外的那个元素上。

# 总结

# 声明式与命令式开发

声明式开发方式:使用框架来操作DOM,如 React、Vue,减少 DOM 操作。
命令式开发方式:直接操作DOM ,如 jQuery

# 与其它框架并存

React 最终有一个ReactDOM.Render方法,这个方法会将组件渲染成DOM填充页面中容器。
也就是说,它最后只会填充那个容器,页面其它的容器它管不着,其它的容器你就可以使用其它的技术,如 Vue,Jquery 等等。
这就是 React 可以与其它框架并存的原因。

# 组件式的开发(组件化)

首字母大写就是组件,首字母小写就是 html 元素
父子传值 通过属性的方式,父组件中给子组件设置属性,子组件中通过 this.props 获取属性。
子父传值,也是一样,只不过传递的是父组件中的方法,但是每个方法都要.bind(this),表示将父组件中的方法的 this 指向父组件,这样子组件调用的时候才有效。

# 单向数据流

父组件可以给子组件传递值,但是子组件一定不能够直接去修改父组件的值,一旦你改变了,React 会给你报一个错误出来,因为传递过来的值是一个只读的属性。

单向数据流是为了让测试起来和开发起来方便,不容易遇到坑。

如果父组件中有五六个组件,都传递了同一个值,然后你在其中一个子组件中直接修改父组件传递给你的那个属性,那么其它的组件就完蛋了。
虽然最后还是会修改父组件中的那个属性,但是那不一定,因为 setState 这个操作是异步进行的,前面的修改某个属性的操作,会被后面修改某个属性的操作覆盖掉,只执行最后一次操作。

如果页面出现了 bug,你调试起来也不方便,因为你这个属性被五六个组件公用了,都可以直接修改值,这样很不好。
所以 React 出了单向数据流,只允许父组件向子组件传递数据,但是不允许子组件直接修改父组件传递过去的数据,你可以通过父组件传递过去的方法,来修改父组件中的数据。
单向数据流代码维护方便。

# 视图层的框架

做大型项目时传值是一个问题,所以需要配合一个数据层的框架,帮我们解决 React 中组件间复杂传值的问题。
如 兄弟组件间传值,这个最麻烦,一层一层往上,再一层一层的往下,项目很大,那就会崩溃。代码冗余。
所以 React 就把它定义为一个视图层的框架,它并不是什么问题都解决,我只帮你解决数据和视图在页面渲染的问题,至于组件之间传值我并不负责,我交给其它组件来做。
如果只有两层组件,借助 React 内部的传值机制就可以了,如果有多层组件,就是用Redux等等数据层框架来辅助。
这也是为什么React将自己称为一个视图层的框架,而不是一个大型的完整的框架,它会借助很多的辅助框架。

# 函数式编程

面向测试的开发流程,前端自动化测试的时候,如果你的代码都是一个个函数,那么测试时就调用这个函数,查看输入输出即可,这样就给前端自动化测试带来很大的便利。

#react
上次更新时间: 10年18月2023日 01时57分53秒
React16_4整理-开篇
React16_4整理-上阶

← React16_4整理-开篇 React16_4整理-上阶 →

最近更新
01
01.数据结构导论一览.md
10-16
02
30.2023年06月04日.md
06-04
03
08.与测量相关.md
05-06
更多文章>
Theme by Vdoing | Copyright © 2017-2023 aiyoudiao 码二 备案号: 鄂ICP备2022002654号-1