react学习(2019/7/30-8/7)

今日总结

课上提到的内容

1. 讲了react要学习的内容提纲

  • react 基础,JSX语法,插件
  • react-router 路由
  • redux 状态管理
  • ant-ui 组件库(自己学习)

2.基础知识

  • react是什么?

      帮助构建页面的js库
    
  • 组件开发方式

    类组件:有状态(state)和完整的生命周期

    和函数式:只做展示(hook自有状态)

作业

1.大家根据我们今天讲到的内容,结合自己的学习,写一篇关于jsx的使用,组件相关的总结

  • JSX是JavaScript的语法扩展,具有JavaScript的全部功能
    const element = 

Hello, world!

;
  • 为什么使用JSX?
    • React 认为渲染逻辑本质上与其他 UI 逻辑内在耦合
    • React 并没有采用将标记与逻辑进行分离到不同文件这种人为地分离方式,而是通过将二者共同存放在称之为“组件”的松散耦合单元之中,来实现关注点分离
  • 在JSX中嵌入表达式
    const name = 'Josh Perez';
    const element = 

Hello, {name}

; ReactDOM.render( element, document.getElementById('root') ); //在JSX语法中,你可以在大括号内放置任何有效的 JavaScript 表达式。例如,2 + 2,user.firstName或 formatName(user)都是有效的JavaScript表达式
    • 为了便于阅读,我们会将 JSX 拆分为多行
  • JSX 也是一个表达式
    • 你可以在 if 语句和 for 循环的代码块中使用 JSX,将 JSX 赋值给变量,把 JSX 当作参数传入,以及从函数中返回 JSX
  • JSX 特定属性
    • 你可以通过使用引号,来将属性值指定为字符串字面量,也可以使用大括号,来在属性值中插入一个 JavaScript 表达式
    const element = 
; const element = ;
  • 使用 JSX 指定子元素
    • 假如一个标签里面没有内容,你可以使用 /> 来闭合标签,就像 XML 语法一样:
      const element = ;
    • JSX 标签里能够包含很多子元素:
  • JSX 防止注入攻击
  • JSX 表示对象
    • Babel 会把 JSX 转译成一个名为 React.createElement() 函数调用,以下两种示例代码完全等效:
    const element = (
    

Hello, world!

); const element = React.createElement( 'h1', {className: 'greeting'}, 'Hello, world!' );
  • react生命周期
    组件传给ReactDom.render()->调用组件的构造函数->this.state初始化->React调用组件的render()方法->组件插入DOM中后调用ComponentDidMount()->当组件被移除的时候,React 就会调用 componentWillUnmount()
  • 正确使用State
  1. 不要直接修改State,而是应该使用setState,构造函数是唯一可以给this.state赋值的地方

  2. State的更新可能是异步的,出于性能考虑,React 可能会把多个 setState() 调用合并成一个调用。

  • 因为 this.props 和 this.state 可能会异步更新,所以你不要依赖他们的值来更新下一个状态。
  • 例如,此代码可能会无法更新计数器:
    // Wrong
    this.setState({
    counter: this.state.counter + this.props.increment,
    });
    
  • 要解决这个问题,可以让 setState() 接收一个函数而不是一个对象。这个函数用上一个 state 作为第一个参数,将此次更新被应用时的 props 做为第二个参数:
    // Correct
    this.setState((state, props) => ({
    counter: state.counter + props.increment
    }));
    
  1. State 的更新会被合并

2.在201907-B-Train项目,自己的目录下,用create-react-app创建一个项目,项目名称叫做react-demo

3.可以使用这个 codesandbox.io去做一些在线开发验证

4.React.Children(demo5)

  • React.Children 提供了用于处理 this.props.children 不透明数据结构的实用方法
  • this.props.children有三种可能性。如果组件没有子节点,则值为undefined; 如果单个子节点,一个对象; 如果有多个子节点,则为数组

5.PropTypes属性(demo6)

  • 定义title应该是个字符串
    class MyTitle extends React.Component {
        static propTypes = {
            title: PropTypes.string.isRequired,
        }
        render() {
            return 

{this.props.title}

; } static defaultProps = {//给title设置默认值 title: 'Hello World', } }

6.React.createRef,ref(demo7)

  • 有时您需要引用组件中的DOM节点。React为您提供了ref将DOM节点附加到由其创建的实例的属性React.createRef()
    class MyComponent extends React.Component {
        constructor(props) {
          super(props);
          this.myTextInput = React.createRef();
          this.handleClick = this.handleClick.bind(this)
        }
        handleClick() {
          this.myTextInput.current.focus();
        }
        render() {
          return (
            
); } } ReactDOM.render( , document.getElementById('example') ); }

7.this.state(demo8)

  • React将组件视为状态机,并用于this.state保存组件的状态,this.setState()以更新this.state和重新呈现组件

8.react生命周期

  • componentWillMount():在初始渲染发生之前触发一次。连接消息监听器的好地方。this.setState在这里不起作用。
  • componentDidMount():在初始渲染发生后触发一次。可以用this.getDOMNode()。
  • componentWillUpdate(object nextProps,object nextState):在组件对DOM进行更新后触发。可以this.getDOMNode()用于更新。
  • componentDidUpdate(object prevProps,object prevState):在将组件的更新刷新到DOM之后立即调用。初始渲染不会调用此方法。将此作为在更新组件时对DOM进行操作的机会。
  • componentWillUnmount():在从DOM卸载组件之前立即触发。删除消息监听器或一般清理的好地方。
  • componentWillReceiveProps(object nextProps):在组件接收新props时触发。你可能想要this.setState依赖props。
  • shouldComponentUpdate(object nextProps,object nextState):在收到新的props或state时呈现之前触发。return false如果你知道不需要更新。

今天做了什么

1.写了日志

2.按照官网写了井字棋的小游戏

3.学习理解了阮一峰react的11个demo

4.官网看到了核心概念的第7条条件渲染

今日心得

今天通过老师讲解大致react学习的大纲,通过react官网逐步去适应了react的JSX编写规则,通过实践井字棋游戏,也理解了react父子组件的传参,只能通过props传参,state 和 props 之间最重要的区别是:props 由父组件传入,而 state 由组件本身管理。组件不能修改 props,但它可以修改state,state只能通过setState来修改等基础知识。

做了什么

  • 主要课上学习了react的条件渲染、列表渲染、表单、ref、状态提升等。
  • 做了todo-list demo,实现了react的组件嵌套,父子组件的传值,顶层组件数据控制,状态管理等

有什么收获

  • 写demo的时候遇到了很多问题,比如我想通过子组件去处理父组件传过来的props但是,在子组件中处理父组件的数据,逻辑非常混论,并且状态更新难以管理,后来,直接在父组件上面进行数据的绑定,函数的分装,然后通过事件传递给子组件,然后执行,完成状态管理
  • 在处理事件的时候,遇到了事件this绑定的问题,有三种方法可以实现,constuctor中事件.bind(this)、箭头函数和传递的时候.bind(this)
  • 还遇到了元事件e的隐式和显示传递问题,()=>{this.handle(item)}不传递e,(e)=>{this.handle(e)}
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';

// 类组件
// class Square extends React.Component{
//     render(){
//         return (
//             
//         );
//     }
// }
// 等价于函数组件
function Square(props){
    console.log(props)
    return (
        
    );
}

function calculateWinner(squares) {
    const lines = [
      [0, 1, 2],//[x,o,x,o,x,o,null,x,null,null]
      [3, 4, 5],
      [6, 7, 8],
      [0, 3, 6],
      [1, 4, 7],
      [2, 5, 8],
      [0, 4, 8],
      [2, 4, 6],
    ];
    for (let i = 0; i < lines.length; i++) {
      const [a, b, c] = lines[i];
      if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
        return squares[a];
      }
    }
    return null;
  }

class Board extends React.Component{
    // constructor(props){
    //     super(props);  
    //     this.state = {
    //         squares:Array(9).fill(null),
    //         xIsNext:true,
    //     }                                                                 
    // }
    // handleClick=(i)=>{
    //     const squares = this.state.squares.slice();
    //     if (calculateWinner(squares) || squares[i]) {
    //         return;
    //     }
    //     squares[i]= this.state.xIsNext ? 'X' : 'O';
    //     this.setState({
    //         squares:squares,
    //         xIsNext:!this.state.xIsNext,
    //     });
    // }
    renderSquire(i){
        console.log(this.props);
        return (
        this.handleClick(i)}
            value={this.props.squares[i]}
            onClick={()=>this.props.onClick(i)}
            // onClick={()=>this.props.onCd()}
        />);
    }
    render(){
        // const winner = calculateWinner(this.state.squares);
        // let status;
        // if(winner){
        //     status="Winner:"+winner;
        // }else{
        //     status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
        // }
        // const status = 'Next player:'+ (this.state.xIsNext ? 'X' : 'O');
        return (
            
{/*
{status}
*/}
{this.renderSquire(0)} {this.renderSquire(1)} {this.renderSquire(2)}
{this.renderSquire(3)} {this.renderSquire(4)} {this.renderSquire(5)}
{this.renderSquire(6)} {this.renderSquire(7)} {this.renderSquire(8)}
); } } class Game extends React.Component { constructor(props) { super(props); this.state = { history: [{ squares: Array(9).fill(null), }], stepNumber:0, xIsNext: true, }; console.log(props) } handleClick(i){ // const history = this.state.history; const history = this.state.history.slice(0, this.state.stepNumber + 1); const current = history[history.length - 1]; const squares = current.squares.slice(); // const squares = this.state.squares.slice(); if (calculateWinner(squares) || squares[i]) { return; } squares[i]= this.state.xIsNext ? 'X' : 'O'; this.setState({ history: history.concat([{ squares: squares, }]), stepNumber:history.length, xIsNext:!this.state.xIsNext, }); } jumpTo(step){ this.setState({ stepNumber:step, xIsNext:(step % 2)===0, }) } render() { const history = this.state.history; const current = history[this.state.stepNumber]; const winner = calculateWinner(current.squares); const moves = history.map((step, move) => { const desc = move ? 'Go to move #' + move : 'Go to game start'; return (
  • ); }); let status; if(winner){ status="Winner: "+winner; }else{ status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O'); } return (
    this.handleClick(i)} // onCd={()=>this.l(1)} />
    {status}
      {moves}
    ); } } // ======================================== ReactDOM.render( , document.getElementById('root') );

    学习内容

    1. react-router学习

    2. router配置

    3. 路由匹配原理

    4. 默认路由

    练习内容

    完成路由切换的demo

    遇到的问题?

    未完成用a标签实现路由跳转

    代码:

    import React from 'react';
    import { BrowserRouter as Router, Route, Link } from "react-router-dom";
    import Introduction from './Introduction'
    import Introduction1 from './Introduction1'
    import Basis from './Basis'
    import './App.css'
    function App(){
        return (
            
                
    • Introduction
    • 1.简介
    • 2.基础
      • 2.1路由配置
      • 2.2路由匹配原理
      • 2.3History
      • 2.4默认路由
    • 3.高级用法
      • 2.1路由配置
      • 2.2路由匹配原理
      • 2.3History
      • 2.4默认路由
    • 4.升级指南
    • 5.排错
    • 6.Api文档
    • 7.词汇表
    ) } export default App

    学习内容

    redux基础学习

    Action,Reducer,Store,数据流的学习

    1. action 只是一个带有type属性的普通对象
    2. store 是一个用于改变state状态的对象
     storeChange(){
         this.setState(store.getState())
     }
     store.subscribe(this.storeChange) //订阅Redux的状态
     store.dispatch(action)//触发一次订阅
    
    1. reducer是一个纯函数,接受上一个state和action作为参数,并返回下一个要更新的state给store,reducer里面的内容主要是通过action的type去对下一个state进行限定和修改,但是不更新

    今日总结

    1. 今天做了什么

    1. 今天主要做了表单的页面部分内容
    2. 是通过使用antd插件进行构建的

    2. 学习

    1. 学习了antd的一些基本使用方法
    安装,引入,按模块导入,导入css文件
    

    3. 收获

    1. 最后引入的样式很完美,但是因为对这个库根本不熟悉所以,中间的数据不知道怎么传递,最后以失败告终,从而自己的进度就拉下了,
    2. 感悟和收获:以后做项目,一定先写逻辑再写页面样式,这样做有很多好处,交互的逻辑先写完,样式可以慢慢加,但写样式,如果逻辑加不进去可能导致重写。

    明日计划

    继续redux学习


    image.png

    image.png

    今日总结

    1.做了什么?

    1. 重写了项目的交互逻辑
    2. 重写了项目的页面
    3. 明白了redux的数据状态管理:component创建action,通过store.dispatch(action)传递给store,store接受到action后先不处理,而是将action当参数传递给reducer,reducer根据传来的action,将state做相应的更新以后,将新的state返还给store,store接受到新的state后更新全局的state,store可以通过store.subscribe订阅store的改变

    2.学了什么

    1. 上面描述的redux的工作机制
    2. 对selet和form等使用和学习

    3.明日计划

    继续完善项目的校验功能
    

    今日总结

    1.做了什么?

    1. 用mockjs模拟了后台数据,并且通过axios能获取到,通过里面的参数也可以向后台传递参数
    import Mock from 'mockjs'//导入mockjs模块
    
    Mock.mock('/data','get',(options)=>{//options 为axios传递给mock的数据,return的对象为mock给axios的body内数据内容
        console.log(options);
        return{    
            'list|1':[{
                'id|+1': 1,
                'selectValue':null,
                'educationValue':null,
                'startTime':null,
                'endTime':null,
                'firstMajor':null,
                'firstMajorGPA':null,
                'secondMajor':null,
                'secondMajorGPA':null
            }]
        }
    })
    
    1. 通过for...of加switch做提交前的校验
            for(let i of list) {
                for(let item of Object.entries(i)){
                    let [key,value] = item;
                    console.log(key);
                    switch (key){
                        case "id": 
                            value===null?alert("id未填写"):console.log(value);
                            break
                        case "selectValue":
                            value === null ? alert("学校未填写") : console.log(value);
                            break
                        case "educationValue":
                            value === null ? alert("学历未填写") : console.log(value);
                            break
                        case "startTime":
                            value === null ? alert("起始时间未填写") : console.log(value);
                            break
                        case "endTime" :
                            value === null ? alert("终止时间未填写") : console.log(value);
                            break
                        case "firstMajor":
                            value === null ? alert("第一学位未填写") : console.log(value);
                            break
                        case "firstMajorGPA":
                            value === null ? alert("第一学位GPA未填写") : console.log(value);
                            break
                        case "secondMajor":
                            value === null ? alert("第二学位未填写") : console.log(value);
                            break
                        case "secondMajorGPA":
                            value === null ? alert("第二学位GPA未填写") : console.log(value);
                            break
                        default:
                            console.log("success");
                    }
                }
            }
    

    2.学了什么

    1. mockjs和axios的简单使用
    2. switch的使用
    3. for...of的使用

    3.明日计划

    继续完善表单的前台,后端校验和提交前的校验等功能,将代码分块
    

    今日总结

    1.做了什么?

    1. 继续完善表单
      • 将代码分块,将所有的action操作全部提取出来,放在actionTypes.js里面,将action提取出来放在actionCreators.js
      • 对表单的数据和UI做了双向绑定
    2. 复习了Generator函数,看来一部分redux-saga内容

    2.遇到问题

    1. 几个需要注意的地方
      • 刚开始的input监控事件是用onBlur事件,但是这个不能用于数据的双向绑定,因为它不能实时更新input框里面的内容,所以会造成input框数据第一次可以输入,但是第二次输入不了的情况,因为第一次的值绑定了以后,输入框再要改变必须要onBlur才行,而输入内容的时候是onFocus
      • 初始化数据,包括后面新增数据项的初始化数据尽量不要设置成null,而是缓存空字符串,要不然会有警告

    3.明日计划

    • 继续学习redux-saga内容

    今日总结

    做了什么

    1. 对redux-saga基础进行学习
    2. 对angular1.x进行学习,学习了指令,表达式,模型,$scope,控制器和过滤器等

    遇到什么问题

    1. redux-saga文档给的例子,只有分支上的可以跑起来,master分支上的会报错
    2. angular1.x没有官方文档,只能通过菜鸟教程去学习,上面给的例子很简单,导致复杂应用的开发的话没什么借鉴意义

    有哪些收获

    • redux-saga还很迷,后面还需要好好重新学习,感受了老框架angular初代版本的魅力,觉得学习和使用的成本很低,还挺实用的

    明日计划

    • 开始hzero前端开发的学习

    你可能感兴趣的:(react学习(2019/7/30-8/7))