react知识点

官方文档:https://zh-hans.reactjs.org/docs/hello-world.html

核心概念

一、元素渲染

1、ReactDom.render(template,targetDOM):将模板转换为html并插入到指定DOM根节点

//index.js入口文件
import React from 'react';
import ReactDOM from 'react-dom';

ReactDOM.render( //ReactDom.render(template,targetDOM)方法将模板转换为html并插入到指定DOM节点
  <h1>hello world</h1>
  document.getElementById('root')
);

2、元素不可变,一旦创建就无法更改其子元素和属性,如同电影的单帧,代表某一特定时刻的UI,更新UI的唯一方式是创建一个新的元素并传入ReactDOM.render()

function fan() {
      const element = <div><h1>hello world</h1><h1>{new Date().getSeconds()}</h1></div>;
      ReactDOM.render(element,document.getElementById('ele'));
}
setInterval(fan, 1000);
return (
      <div className="App">
          <div id="ele" />
      </div>
);

3、只更新需要更新的部分

二、JSX

1、在jsx中嵌入表达式:使用花括号,花括号内放置任何js有效表达式:

formate(user),a+b,user.url
    function fan(a) {
        return ('hello'+a)
    }
const name = 'world';
const element=<div>Hello,{name}</div>;
const ele = <div>fan(name)</div>;

2、可以存在if语句,for循环中,作为函参传入,函数返回值

function fan(a) {
        if(a){return (<h1>hello+{a}</h1>)}
        return (<h1>hello</h1>)
}

3、指定属性:字符串使用引号,表达式使用花括号

const user={url:'www.baidu.com',data:'0'};
const element = <div tabIndex="0">111</div>;  //注意:jsx语法中的属性要以小驼峰(camelCase)命名
const img = <img src={user.url} />;

4、jsx防止注入攻击
在reactDOM渲染前内容都被转换成了字符串,确保在你的应用中,永远不会注入那些并非自己明确编写的内容。
5、babel将jsx转换成react.createElement()的调用函数,创建了一个对象,下面三种写法等价

 const element = <div className='ele'>hello</div>;
 相当于:
 const element=react.createElement(
        'h1',
        {className:'ele'},
        "hello"
 );
 相当于:
 const element={
        type:'div',
        props:{
            className:'ele',
            children:'hello'
        }
  };

三、组件和props

1、概念:
组件: 将UI拆分为独立、可复用代码片段,类似js函数,入参props,返回描述页面的React元素。组件名称大写字母开头
props:当react元素为用户自定义组件时,jsx会将接收的属性和子组件(children)转换为单个对象传给组件,这个对象就是props,不可被修改

2、函数组件与class组件
函数组件

 function Fan(props) { //自定义组件
      return <h1>hello,{props.name}</h1>;
 }
const element = <Fan name="fan" />; //name会作为props的属性传递给Fan自定义组件
ReactDOM.render(element,document.getElementById('root'))

ES6 class组件:

class Fan extends React.Component{
  render(){
    return  <h1>hello,{this.props.name}</h1>
  }
}

3、组合组件与提取组件

要求:将下面的组件提取出UserInfo组件,使得Comment为组合组件

function Comment(props) {
  return (
    <div className="Comment">
      <div className="UserInfo">
        <img className="Avatar"
          src={props.author.avatarUrl}
          alt={props.author.name}
        />
        <div className="UserInfo-name">
          {props.author.name}
        </div>
      </div>
      <div className="Comment-text">
        {props.text}
      </div>
      <div className="Comment-date">
        {formatDate(props.date)}
      </div>
    </div>
  );
}

提取组件:

function Avatar(props){
   <img className="Avatar"
         src={props.user.avatarUrl}
         alt={props.user.name}
     />
}
 function UserInfo(props) {
        return (
            <div>
                <Avatar user={props.user} /> //二级嵌套子组件
                <div className="UserInfo-name">
                    {props.user.name}
                </div>
            </div>
        )
    }

组合组件:

function Comment(props) {
  return (
    <div className="Comment">
      <UserInfo user={props.author}/>  //一级嵌套子组件
      <div className="Comment-text">
        {props.text}
      </div>
      <div className="Comment-date">
        {formatDate(props.date)}
      </div>
    </div>
  );
}

四、state与生命周期
1、概念:
state:组件内部私有
2、class组件中才可以使用state与生命周期函数,将函数组件转换成class组件步骤:

创建es6 class,继承于React.Component
添加空render(){}方法
将函数体移动到render()方法中
在render()方法中使用this.props替换props

3、封装一个组件,设置自己的计时器并每秒钟更新UI上当前秒

import React,{Component} from 'react';

class App extends Component{ //定义了一个名称为App的类,它继承于React.Component
    constructor(props){//创建一个构造函数,为this.state赋初值
        super(props); //class组件使用props调用父类的构造函数
        this.state={  //唯一可以直接为state赋值的地方
            date:new Date(),
            timerId:''
        }
    }
    componentDidMount(){  //生命周期函数:组件已经挂载到根节点上触发
        this.timerId = setInterval(()=>this.tick(),1000)//初始化定时器,每一秒调用一次tick函数
    }
    componentWillUnmount(){
        clearInterval(this.timerId)//生命周期函数:组件将要销毁:清除定时器
    }
    tick(){
        this.setState({date:new Date()}) //
    }
    render(){
        return(
            <div className="App">
               <div>{this.state.date.getSeconds()}</div>
            </div>
        )
    }
}
export default App;
总结调用顺序:
1、ReactDOM.render()会使用react调用Clock组件中的构造函数初始化this.state,显示this.state中的初始值
2、调用Clock组件的render()方法,根据Clock渲染的输出来更新DOM
3、当Clock的输出插入到DOM中后,调用ComponentDidMount()生命周期函数,向浏览器请求设置一个定时器来每秒调用一次tick()方法
4、浏览器每秒调用一次tick方法,该方法调用this.setState()进行一次UI更新,React知道state改变了就会重新调用render(),更新DOM
5、Clock组件被移除前调用ComponentWillUnmount()生命周期函数清除定时器

4、state的使用
(a)除了构造函数中,其他地方都不能直接修改state,不会重新渲染组件,要使用this.setState({aa:" "}), setState调用后会将其提供的对象合并到当前的state
(b) setState的更新可能是异步的:性能方面的考虑,react会合并多个setState再调用
影响:不要依赖this.prop和this.state来更新下一个状态,例如
this.setState({aa:props.a+state.b})
解决方法:传给setState一个函数,函参1为上一个state,函参2为props
this.setState((state,props)=>{aa:props.a+state.b}) 普通函数也可以
©向下的单向数据流
本组件可以将state作为props向下传递给子组件

<Formate date={this.state.date}> //在父组件中调用子组件,将state作为数据流传递下去

function Formate(props){   //自定义子组件
  return <div>{this.props.date}</div>
}

五、事件处理
1、命名:小驼峰(camelCase)
2、引入形式:jsx需要传入一个函数作为事件处理函数而不是字符串

传统:<button onclick="handleClick()">点击</button>
jsx: <button onClick={handleClick} >点击</button>

3、阻止默认行为:react中只能使用e.preventDefault,而不能使用return false

4、es6 class组件中将事件处理函数声明为class类的方法
js通用:如果你没有在方法后面添加 (),例如 onClick={this.handleClick},你应该为这个方法绑定 this。
绑定this方法如下
(a)constuctor中bind

 constructor(props) {
    super(props);
    // 为了在回调中使用 `this`,这个绑定是必不可少的
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() { }
  
  render() {
    return (
      <button onClick={this.handleClick}>aa </button>
    );
  }
}

(b)publish class fields语法(建议使用)

class LoggingButton extends React.Component {
  // 此语法确保 `handleClick` 内的 `this` 已被绑定。
  // 注意: 这是 *实验性* 语法。
  handleClick = () => {}

  render() {
    return (
      <button onClick={this.handleClick}>
        Click me
      </button>
    );
  }
}

©onclick中使用箭头函数或者绑定bind

class LoggingButton extends React.Component {
  handleClick() { }

  render() {
    // 此语法确保 `handleClick` 内的 `this` 已被绑定。
    return (
      <button onClick={() => this.handleClick()}>aa </button>
    );
  }
}

5、事件函数传参

//e为函参2,bind方式会将事件对象e隐式传递下去
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>

六、条件渲染
1、三种方式
(a)、if else
(b)、&&运算符
true && element //&&符号前面是true,返回后面的元素
false &&element//&&符号前面是false,返回false

 <div>
  {messages.length > 0 &&  <h2> hello</h2>}
  </div>

©、三目运算

condition? true:false

2、阻止组件渲染

render(){
  if(!props.warn){
    return null;
  } 
  return(...)
  }

七、列表与key
1、使用.map()渲染列表,实例如下:

 render(){
        const number = this.props.number; 
        const listItem = number.map((item)=>{
        //注意:每一项要有唯一标识赋值给key
           return <li key={item.id}>{item}</li> 
        });
        return(
            <div className="App">
               <ul>{listItem}</ul>
            </div>
        ) }}

使用jsx语法创建一个含有map循环的变量:

 render() {
        const number = this.props.number;
        const listItem = <ul>
            {number.map((item) => {
                return <li key={item.id}>{item}</li>
            })}
        </ul>;
        return (
            <div className="App">
                {listItem}
            </div>
        )
    }

2、key
作用:react用其来标识哪个元素发生了变化(添加或者删除),在兄弟节点之间必须是唯一的标识。一般使用数据中的id来作为元素的key。key将信息传递给react,而不会传递给组件

提问:是否可以使用索引作为key值
如果使用索引,那么当数据发生变化,索引对应的新值和索引对应的旧值对于react来说认为是没有变化的,会降低性能甚至引发组件状态问题。
如果数据不发生变化可以使用index

key的使用位置
map()方法中的元素需要设置key属性

八、表单

1、input,select,textarea都是受控表单,使用value属性绑定state中的值,通过onChange函数setState修改state的值。

class App extends Component {
    constructor(props) {
        super(props); 
        this.state = {
            input:"",
            textarea:"",
            select:["3","2"]
        }
    }
    handleInput=(e)=>{
        this.setState({
            input:e.target.value
        })
    };
    handleSelect=(e)=>{
        this.setState({
            select:e.target.value
        })
    };
    handleTextarea=(e)=>{
        this.setState({
            textarea:e.target.value
        })
    };

    render() {
        return (
            <div className="App">
                <input type="text" value={this.state.input} onChange={this.handleInput}/>
                <textarea value={this.state.textarea} onChange={this.handleTextarea}/>
                <select value={this.state.select} onChange={this.handleSelect} multiple>
                    <option value="1">1</option>
                    <option value="2">2</option>
                    <option value="3">3</option>
                </select>
                
                 文件input标签:从用户存储设备上选择一个或多个文件,非受控组件
                <input type="file"/> 
                
                 受控输入空值: 一般情况下绑定了value值但是没有绑定onchange函数则会阻止用户更改input中值,除非为value设置了null或者undefined
                <input type="text" value={null} />
            </div>
        )
    }
}

export default App;

2、同时处理多个类型的input表单
添加name属性,根据e.target.name选择执行的操作

handleChange=(e)=>{
  const value=e.target.name==='aa'?e.target.checked:e.target.value;
  const name=e.target.name
  this.setState({[name]:value}) //es6的计算属性名称:给属性动态的修改值
}
...

return(
<div>
  <input name="aa" checked={this.state.aa} type="checkbox"/>
  <input name="bb" value={this.state.bb} type="number"/>
</div>
)

九、状态提升

应用场景:多个子组件互动(比如更改子组件1中的值会影响子组件2,更改子组件2会影响子组件1)

使用:将影响的子组件中的state中的值提升到他们共有的父组件中的props,然后处理

示例:

共有父组件

import React, {Component} from 'react';
import Temperature from '../src/components/temperature/Tempreture';
import './App.css';

class App extends Component {
    constructor(props) {
        super(props); 
        this.state = {
            scale:'c',
            temperature:"",
        }
    }
    handleC=(e)=>{
        this.setState({scale: 'c', temperature:e.target.value});
    };

    handleF=(e)=>{
        this.setState({scale: 'f', temperature:e.target.value});
    };

    render() {
        function tryConvert(temperature, convert) {  //温度转换函数
            const input = parseFloat(temperature);
            if (Number.isNaN(input)) {
                return '';
            }
            const output = convert(input);
            const rounded = Math.round(output * 1000) / 1000;
            return rounded.toString();
        }
        function toC(f) { //转换成摄氏度
            return (f - 32) * 5 / 9;
        }

        function toF(c) { //转换成华氏度
            return (c * 9 / 5) + 32;
        }
        
        const c = this.state.scale === 'c' ? this.state.temperature : tryConvert(this.state.temperature, toC);
        const f = this.state.scale === 'f' ?  this.state.temperature: tryConvert(this.state.temperature,toF);

        return (
            <div>
               提升了温度这个子组件中的state数据提升到了父组件中,在父组件中进行转换交互后使用props自上而下的数据流传递下去,从而实现两个无关的子组件实现互动
                <Temperature
                    scale="c"
                    temperature={c}
                    onTemperatureChange={this.handleC} />
                <Temperature
                    scale="f"
                    temperature={f}
                    onTemperatureChange={this.handleF} />
            </div>
        );
    }
}

export default App;
Temperature 子组件

class Temperature extends Component{
    constructor(props){
        super(props);
        this.state={};
    }
   render(){
        return(
            <div>
               <fieldset>
                   <legend>请输入{this.props.scale}温度</legend>
                   <input type="text" value={this.props.temperature} onChange={this.props.onTemperatureChange}/>
               </fieldset>
            </div>
        )
    }
}
export default Temperature

十、组合和继承 ==类似于vue的插槽slot的概念
组合:
组件之类的react元素本质是对象,可以把他们当作props中的数据传递下去。props可以是基本数据类型、函数、react元素
1、使用this.props.children
父组件在引用子组件A时,在子组件标签内组合一个子组件B,在子组件内可以使用this.props.children获取子组件2

父组件
 return (
      <div>
         <A>
            <B />
         </A>
      </div>
);

子组件A
 render(){
        return(
            <div>
                {this.props.children} //此处渲染的是B组件
            </div>
        )
    }

2、指定任意的props

父组件
 return (
      <div>
       left属性为指定的props
         <A left={<B />} />  
      </div>
);

子组件A
 render(){
        return(
            <div>
                {this.props.left} //此处渲染的是B组件
            </div>
        )
    }

十一、react哲学:拿到一个UI图和API后的思考步骤
1、根据UI分析组件之间的嵌套关系

2、根据props数据按照自上而下(嵌套简单)或者自下而上(嵌套复杂)开发无交互的静态页面

3、分析最小state集合:根据事件推移发生变化;不是从父组件流下来的数据;不能根据其他的state或者props数据计算得到。根据state数据放置在合适组件(使用该state的最高阶组件)并添加交互

4、添加反向数据流:使用回调函数反向传递

高级知识点

一、无障碍
1、保证html语义:解决ol,ul,dl等在div包裹下失效问题
Fragment、短语法<></>实现语义HTML多个元素的添加且不在DOM中增加额外节点

 <dl>
      {props.items.map(item => (
        Fragments 也需要添加key
        <Fragment key={item.id}>
          <dt>{item.term}</dt>
        </Fragment>
      ))}
  </dl>
  
  或者:
  <dl>
      {props.items.map(item => (
        当fragmen没有需要添加的属性时,可以使用<></>
        由于循环数组需要添加key属性,所以不能使用短语法
        <>
          <dt>{item.term}</dt>
        </>
      ))}
  </dl>

2、表单控制
lable for属性规定 label 与哪个表单元素绑定。在jsx中写成htmlFor
作用: 在点击label时会自动将焦点移动到绑定的元素上

实现功能:点击lable,input框获得焦点

<label htmlFor="namedInput">Name:</label>
<input id="namedInput" type="text" name="name"/>
实现功能:点击男,id=nan的checkbox选中

  <label for="nan"></label>
  <input type="checkbox" id="nan" />
  <label for="nv"></label>
  <input type="checkbox" id="nv" />

二、代码分割

1、打包概念:将文件引入合并到一个文件中,形成一个bundle,在页面上引入一次性加载。
代码分割:就是按照需求的先后顺序分割代码生成多个bundle,按需加载,避免bundle过大造成加载时间过长

2、基于路由的代码分割,路由懒加载(按需加载

() => import(’@/components/HelloWorld’)
vue/react框架都可以使用,因为是由webpack提供的功能

三、全局数据的传递

方式一:使用props一直传递(适用三层组件内)

方式二:context

应用场景:一些属性需要层层传递,全局数据的传递

作用:可以避免层层传递,将值植入组件树,任何组件都可以取到

使用:

1、创建生产者和消费者
export const {Provider, Consumer} = React.createContext(defaultValue);

注意:组件所处的树中没有匹配到 Provider 时, defaultValue才会生效,与provider中的value值无关

2、在父组件中添加生产者,需要传递的数据放置在value中
 <Provider value={‘传递下去的数据’}>
       <Temperature/>
 </Provider>
 
 注意:provider的value发生变化,消费组件重新渲染,不受shouldComponentUpdate控制。当祖先组件退出更新情况下也可以更新。

3、在子孙组件中引入消费者,注意consumer里面的必须是函数
import {Consumer} from "../../父组件";
 <Consumer>
       {(context) =>
            <div> {context} </div>
       }
 </Consumer>

示例:

父组件

import React, {Component} from 'react';mport Temperature from "./components/temperature/Tempreture";

export const {Provider, Consumer} = React.createContext();

class App extends Component { //定义了一个名称为App的类,它继承于React.Component
    constructor(props) {//创建一个构造函数
        super(props); //class组件使用props调用父类的构造函数
        this.state = {
            list: [1, 1, 2, 2, 3, 4, 5, 6, 8]
        }
    }

    render() {
        return (
            <Provider value={this.state.list}>
                <Temperature/>
            </Provider>
        )
    }
}

export default App;

子组件
import React, {Component} from 'react'
import {Consumer} from "../../App";

class Temperature extends Component {
    constructor(props) { super(props); }
    render() {
        return (
            <Consumer>
                {(context) => <div> {context} </div>}
            </Consumer>
        )
    }
}

export default Temperature

方式三:在父组件将配置好属性的孙组件作为属性传递下去

function Page(props) {
  const user = props.user;
  为孙组件Feed配置user属性
  const content = <Feed user={user} />;
  const topBar = (
    <NavigationBar>
      <Link href={user.permalink}>
        <Avatar user={user} size={props.avatarSize} />
      </Link>
    </NavigationBar>
  );
  return (
    <PageLayout
      topBar={topBar}
      content={content}
    />
  );
}

四、高阶组件

五、refs转发

一、组件结构与数据绑定

1、super关键字:
参考:http://www.phonegap100.com/thread-4911-1-1.html
Es6中super关键字,用于类的继承,指代父级整个prototype或者__proto__指向的对象(实例),返回父类的this对象,然后对其进行加工。所以子类必须在constructor方法中调用super方法,因为子类没有自己的this对象。

3、React绑定数据、对象 、属性的知识点

a. 所有的模板要被一个根节点包含起来 (xml语法)
b.模板元素不要加引号
c.{}数据渲染
d.绑定属性:绑定属性的两种方法:1.e.target.name 2.this.refs.name
ref的使用:1.给元素设置ref属性2.通过this.refs.refName获取dom节点
注意:
class要变成 className; for 要变成 htmlFor ; style属性如下:

<div> style={{'color':'blue'}}>{this.state.title}</div>
<div style={{'color':this.state.color}}>{this.state.title}</div>  

e.循环数据要加key(加在最外层标签中即可) 如下:
.map((value,key)=>{return(<div key={key}> </div>)})
f.构造函数中一定要注意 super
g.组件名称首字母大写、组件类名称首字母大写

react的MVVM流图:
在这里插入图片描述

二、 事件处理函数

1、概念
以类继承方式定义的组件中,为能方便调用当前组件的其他成员方法或属性,需将事件处理函数运行时的 this 指向当前组件实例。

2、绑定事件处理函数this的几种方法:

3、 事件对象e/event

4、键盘事件onKeyUp、onKeyDown

5、生命周期函数
在这里插入图片描述
在这里插入图片描述

三、表单处理

react类似vue的双向数据绑定:监听函数(如:onchange)监听表单value值的改变,在监听函数内部修改state的值(使用this.setState({}))改变model更新state中input的Value的值;点击按钮获取新的state中input 的Value值(表单元素中设置value=this.state.inputValue)。

注意:判断等于的问题,由于value为字符串,所以不能使用绝对等于===,使用==

四、父子组件及传值

解决html 标签构建应用的不足。

使用组件的好处:把公共功能单独抽离成一个组件,哪里使用哪里引入。

1、父子组件:组件的相互调用中,我们把调用者称为父组件,被调用者称为子组件

父组件给子组件传值
1.在调用子组件的时候定义一个属性 <Header msg='首页'></Header>
2.子组件里面 this.props.msg 说明:父组件不仅可以给子组件传值,还可以给子组件传方法,以及把整个父组件传给子组件。
父组件主动获取子组件的数据
1、调用子组件的时候指定ref的值 <Header ref='header'></Header>
2、通过this.refs.header 获取整个子组件实例

2、父子组件传值,如果父组件调用子组件的时候不给子组件传值,可以在子组件中使用defaultProps定义的默认值
验证父组件传值的类型合法性:propTypes,方法如下:

import PropTypes from 'prop-types';

类.propTypes={name:PropTypes.string};

使用实例:

<Headerf title={this.state.headers}/>  //父组件只给出了title属性的值,没有num、str属性的值

 //子组件
import React,{Component} from "react";
import PropsType from 'prop-types';

class Headerf extends Component{
    constructor(props) {
        super(props);
    }

    render() {
        return(
            <div>
                {this.props.title}//父组件给子组件传值
                
                <h3>{this.props.num}</h3>
                <h3>{this.props.str}</h3>
            </div>
        )
    }
}

Headerf.defaultProps={// 给子组件的属性赋值,注意所在位置
    num:520,
    str:'111'
};
Headerf.propsType={
    str:PropsType.string
};

export default Headerf;

五、以上知识点运用的实例

import React, {Component} from "react";               //引入react脚手架
import Logo from "../assets/images/logo.svg";         //引入图片
class FormProcess extends Component{
    constructor(props){
        super(props);
        this.state={
            msg:"我是原始数据",
            list:[111,222,333,444],
            name:'请输入用户名',
            sex:1,
            city:'',
            cities:['北京','上海','天津'],
            hobby:[{'title':'睡觉','checked':true},{'title':'吃饭','checked':false},{'title':'打游戏','checked':true}],
            info:''

        };
    }
    
    setData=(str)=>{                                //注意函数名称以及组件名称不能与内置函数名称相同
        this.setState({                             // this.setState方法更改数据
            msg: str,           
            list:[555,666,777,888],
            inputMessage:"请输入",
            username:''
        });
    };
    
    getState=()=>{
        alert(this.state.msg);
    };
    
    inputChange=(event)=>{                          //表单处理函数:使用事件对象绑定属性值
      this.setState({
          inputMessage:event.target.value
      })
    };
    
    getValue=()=>{
        alert(this.state.inputMessage);
    };

    getRefValue=()=>{                              //表单处理函数:使用ref绑定属性值:1.给元素设置ref属性 2.通过this.refs.refName获取dom节点*/
        let val=this.refs.username.value;
        this.setState({
            username:val})
    };
    
    getRef=()=>{
        alert(this.state.username);
    };

    inputKeyUp=(e)=>{                            // 键盘处理函数,实现功能:按下回车后弹出input的输入值 回车keyCode为13*/
        if(e.keyCode === 13){
            alert(e.target.value);
        }
    };
   
    handleName=(e)=>{                            // 约束性与非约束性组件
        this.setState({
            name:e.target.value
        })
    };
    
    
    //==============================以下是各种表单的处理==========================
    handleSubmit=(e)=>{
        e.preventDefault();                     //阻止submit的提交事件*/
        console.log(this.state.name,this.state.sex,this.state.city,this.state.hobby,this.state.info);
    };
  
    handleSex=(e)=>{
        this.setState({
            sex:e.target.value
        });
    };
    
    handleSelect=(e)=>{
        this.setState({
            city:e.target.value
        })
    };
    handleCheckbox=(key)=>{
       var hobby=this.state.hobby;
       hobby[key].checked=! hobby[key].checked;
       this.setState({
           hobby:hobby
       })
    };
    handleTextarea=(e)=>{
        this.setState({
            info:e.target.value
        })
    };

    render(){
        var listValue=this.state.list.map( (item,key)=>{
          return(
              <li key={key}>{item}</li>
          )
        });
        return(
           <div style={{opacity:this.state.opacity}}>                        //数据渲染
               <h3>1.数据渲染:</h3>
               <ul>{listValue}</ul>
               
               <h3>2.图片引入的两种方法:本地、远程:</h3>                      //图片引入
               <img src="https://www.baidu.com/img/bd_logo1.png" alt="图片无法显示" style={{ width:"100px"}}/>
               <img src={Logo} alt="图片无法显示" style={{ width:"100px"}}/>
               
               <h3>3.react实现类似vue的双向数据绑定:</h3>                     //双向数据绑定
               <button onClick={this.getState}>state</button>
               <button onClick={this.setData.bind(this,"修改后")}>点击改变state</button>
               
               <h3>4.事件对象:</h3>
               <button abd="123" onClick={this.getEvent}>获取事件节点</button>
               
               <h3>5.绑定属性的两种方法:</h3>
               <input type="text" onChange={this.inputChange} placeholder="事件对象方法获取属性值"/>
               <button onClick={this.getValue}>获取input框的值</button>
               <br/>
               <input ref="username" type="text" placeholder="ref方式获取属性值" onChange={this.getRefValue}/>
               <button onClick={this.getRef}>ref方法获取属性值</button>
               
               <h3>6.键盘事件:</h3>
               <input type="text" onKeyUp={this.inputKeyUp} placeholder="按下回车显示value值"/>
               
               <h3>7.约束性与非约束性组件</h3>
               <form onSubmit={this.handleSubmit}>
                   用户名:<input type="text" value={this.state.name} onChange={this.handleName}/>
                   <br/>
                   性别:
                   <input type="radio" value="1" checked={this.state.sex==1} onChange={this.handleSex}/>男
                   <input type="radio" value="2" checked={this.state.sex==2} onChange={this.handleSex}/>女
                   <br/>
                   居住城市:
                   <select value={this.state.city} onChange={this.handleSelect}>
                       {
                           this.state.cities.map((value,key)=>{
                           return(
                               <option key={key}>{value}</option>
                           )
                       })}
                   </select>
                   <br/>
                   爱好:{
                   this.state.hobby.map((item,key)=>{
                       return(
                           <span key={key}>
                                <input type="checkbox" checked={item.checked} value={item.title} onChange={this.handleCheckbox.bind(this,key)}/> {item.title}
                           </span>

                       )

                   })
               }
                   <br/>
               备注:<textarea value={this.state.info} onChange={this.handleTextarea}/>
                   <br/>
                   <input type="submit" defaultValue="提交"/>
               </form>
           </div>

        )
    }
}
export default FormProcess;

六、ToDolist实例

import React, {Component} from "react";
import "../assets/css/todolist.css";
import {Button} from "antd";

class ToDolist extends Component {
    constructor(props){
        super(props);
        this.state={
            list:[]
        }
    }
    
    addData=(e)=>{                               //增加todo事件函数
        if(e.keyCode===13){
            var tempList=this.state.list;
            tempList.push({
                'title': e.target.value,
                'checked':false
            });
            this.setState({
                list:tempList
            });
            e.target.value='';/*表单置为空*/
            localStorage.setItem('todolist',JSON.stringify(tempList)); /*设置缓存数据*/
        }
    };
    
    handleCheckbox=(key)=>{                      //操作todo事件函数
        var tempList=this.state.list;
        tempList[key].checked=!tempList[key].checked;
        this.setState({
            list:tempList
        });
        localStorage.setItem('todolist',JSON.stringify(tempList)); /*设置缓存数据*/
    };
    
    removeData=(key)=>{                         //移除todo事件函数
        var tempList=this.state.list;
        tempList.splice(key,1);
        this.setState({
            list:tempList
        });
        localStorage.setItem('todolist',JSON.stringify(tempList));/*通过setItem与getItem获得的是字符串格式的数据,通过json更改一下,设置缓存数据:application==localstorage里面查看*/
    };
   
    componentDidMount() { /*生命周期函数:加载完成后触发,实现缓存数据*/
        var todolist=JSON.parse(localStorage.getItem('todolist'));
        if(todolist){
            this.setState({
                list:todolist
            })
        }
    }

    render(){
        return(
            <div>
                <header className="head">ToDolist: <input type="text" onKeyUp={this.addData}/></header>
                <h3>待办事项</h3>

                <hr/>
                <ul>
                    {
                        this.state.list.map((item,key)=>{
                            if(!item.checked){
                                return(
                                    <li key={key}>
                                        <input type="checkbox" checked={item.checked} onChange={this.handleCheckbox.bind(this,key)}/>
                                        {item.title}
                                        <Button type="primary" onClick={this.removeData.bind(this,key)}>删除</Button>
                                    </li>
                                )
                            }
                        })
                    }
                </ul>

                <h3>已完成事项</h3>
                <hr/>
                <ul>
                    {
                        this.state.list.map((item,key)=>{
                            if(item.checked){
                                return(
                                    <li key={key}>
                                        <input type="checkbox" checked={item.checked} onChange={this.handleCheckbox.bind(this,key)}/>
                                        {item.title}
                                        <button onClick={this.removeData.bind(this,key)}>删除</button>
                                    </li>
                                )
                            }
                        })
                    }
                </ul>
            </div>
        )
}
}
export default ToDolist;

七、路由

react-router可以让跟组件动态的挂载不同的其他组件,根据用户访问的地址动态的加载不同组件
参考链接:https://reacttraining.com/reac-router/web/example/basic
安装:npm install react-router-dom --save

1、路由配置

  import {BrowserRouter as Router, Link} from "react-router-dom";
  import Root from "../component/Root";


  <Router>
  <Link to="/user">用户中心</Link>   
  <Route exact path='/user' component={Root}/>
  </Router>

2、页面跳转传值的几种方式

a. 动态路由传值(动态路由概念:path后面可以传入不同值)

路由配置: 路由配置加 :参, <Route path="/content/:aid" component={Content}>
跳转: Link to 使用了es6的模板字符串<Link to={'/content/${value.aid}'}>{value.title}</Link>
获取:componentDidMount函数中获取this.props.match.params

b. get传值:路由普通配置
跳转:Link to中加上?参=值
获取:componentDidMount函数中获取this.props.location.search。使用了node.js的url模块来解析this.props.location.search里面的地址(react官网==dom element(https://reactjs.org/docs/dom-elements.html))

3、js实现跳转路由
在这里插入图片描述

八、react请求

1、axios请求
在这里插入图片描述
2、fetchJsonp请求
查看接口是否符合jsonp请求,将接口放在浏览器地址栏中后面加上&callback=xxxx,返回的数据如果是xxxx({response…})格式,说明该接口支持jsonp请求
在这里插入图片描述

九、知识点案例–无人收银系统

主页面

 import React, {Component} from 'react';
 import axios from 'axios';
 import '../assets/css/orderSystem.css';
 import {Link} from "react-router-dom";
        
class OrderSystem extends Component{
    constructor(props){
        super(props);
        this.state={
            domain:"http://a.itying.com/",
            list:[]
        }
    }

    getData=()=>{
        var api= `${this.state.domain}api/productlist`;
        axios.get(api)
            .then((response)=>{             //在内部使用到this要用箭头函数
            this.setState({
                list:response.data.result
            });
        }).catch(function(error){
            console.log(error);
        });
    };

    componentDidMount(){
        this.getData();                    //加载时请求数据铺页面
    };

    render(){
    
        return(
            <div className="order-system">
                <br/>
                <button style={{width:"150px"}}><Link to={"/login"}>js实现跳转之登陆功能</Link></button>       //使用js跳转到Login模块
                <br/>
                    {
                        this.state.list.map((value,key)=>{
                            return(
                                <div key={key}>
                                    <h3 className="title">{value.title}</h3>
                                    <ul className="ul-list">
                                        {value.list.map((v,k)=>{                      //知识点1:嵌套循环铺数据
                                            return(
                                                <li key={k} className="list">
                                                    <Link to={`/detail/${v._id}`}>
                                                    <div>
                                                        <img style={{width:"100px",height:"100px"}} src={`${this.state.domain}${v.img_url}`}/>
                                                        <p>{v.title}</p>
                                                        <p className="price">¥{v.price}</p>
                                                    </div>
                                                    </Link>
                                                </li>
                                                )   })
                                    </ul>
                                </div>
                                )   }) }
            </div>        
            ) }}
export default OrderSystem;

//Detail详情页
import React, {Component} from 'react';
import axios from 'axios';
import '../assets/css/orderSystem.css';
import {Link} from "react-router-dom";


class Detail extends Component {
    constructor(props){
        super(props);
        this.state={
            domain:"http://a.itying.com/",
            list:[]
        }
    }

    getData=(pid)=>{
        var api= `${this.state.domain}api/productcontent?id=${pid}`;
        axios.get(api)
            .then((response)=>{
               this.setState({
                   list:response.data.result[0]
               });
            }).catch(function(error){
            console.log(error);
        });
    };
componentDidMount() {
    let pid=this.props.match.params._id;  //获取动态路由传值
    this.getData(pid);
};

    render(){
        return(
            <div className="detail">
                <Link to={`/order`} className="go-back">
                   返回
                </Link>
                <div className="content">
                    {this.state.list.img_url?<img src={`${this.state.domain}${this.state.list.img_url}`}/>:""}{/*知识点3:执行顺序导致的报错*/}
                    <p>{this.state.list.title}</p>
                    <p dangerouslySetInnerHTML={{__html: this.state.list.content}}/>{/*知识点2:react中关于html的解析*/}
                </div>
            </div>
        )
    }
}

export default Detail;

//登陆页
import React, {Component} from 'react';
import {Redirect} from 'react-router-dom';

class Login extends Component {
    constructor(props){
        super(props);
        this.state={
            loginFlag:false
        }
    }

    handleLogin=(e)=>{
        e.preventDefault();//注意:阻止默认的提交行为
       const username=this.refs.username.value;
       const password=this.refs.password.value;
       if(username==="admin" && password==="111111"){
           this.setState({
               loginFlag:true
           })
       }else{
           alert("用户名或密码错误!");
       }
    };

    render(){
        if(this.state.loginFlag){
            return <Redirect to={"/order"} />
        }
        return(
            <form onSubmit={this.handleLogin}>
                <input type="text" ref="username" placeholder="用户名"/>
                <br/>
                <input type="password" ref="password" placeholder="密码"/>  <br/>  <br/>
                <input type="submit" value="执行登陆" />
            </form>
        )
    }
}
export default Login;

十、路由的模块化

路由配置文件:

import EmbedRoute from "../component/EmbedRoute";                  //一级路由
   import User from "../component/User";                           //二级路由
       import Main from "../component/user/Main";                  //三级路由
       import Info from "../component/user/Info";
   import Shop from "../component/Shop";
       import ShopList from "../component/shop/ShopList";
       import ShopAdd from "../component/shop/ShopAdd";
   import HomePage from "../component/HomePage";

/*路由的模块化*/
let routes=[
    {
        path: "/embedroute",
        component: EmbedRoute,
        routes:[{                                 二级路由的配置
            path: "/embedroute",
            component: HomePage,
        },{
            path: "/user",
            component: User,
            routes:[{
                path: "/user",
                component: "Main"
            },{
                path: "/user/info",
                component: "Info"
            }]
        },{
            path: "/shop",
            component: Shop,
            routes:[
                {
                    path: "/shop",
                    component: "ShopList"
                },{
                    path: "/shop/shopadd",
                    component: "ShopAdd"
                }
            ]
        }]
    }];

export default routes;

//组件中的应用
import React,{Component} from 'react';
import { BrowserRouter as Router,Route,Link } from 'react-router-dom';

class EmbedRoute extends Component{
    constructor(props) {
        super(props);
    }
    componentDidMount() {
        const list=[];
        this.props.routes.map((route,key)=>{
            return(
                <div key={key}>
                    if(route.routes){
                   list.push(route.routes)
                }
                </div>
            )});};

    render(){
        return(
            <Router>
                <div className="embedroute">
                    <header className="head">
                        <Link to="/embedroute" className="link">首页</Link>
                        <Link to="/user" className="link">用户</Link>
                        <Link to="/shop" className="link">商品</Link>
                    </header>
                </div>
                {
                    this.props.routes.map((route,key)=>{       // this.props.routes包含着每一级的路由信息,具体看下面的图片
                        return(
                            <Route key={key} path={route.path} component={route.component}/>
                            )}
                        )
                    }
            </Router>
        )
    }

}

export default EmbedRoute;

一级路由信息:
在这里插入图片描述
二级路由信息:
在这里插入图片描述
十一、AntDesign
在这里插入图片描述
在这里插入图片描述

以下是React中常用的一些知识点: 1. 组件:React将用户界面拆分为可重用的组件,组件是构建React应用的基本单元。组件可以是函数组件或者类组件。 2. JSX:JSX是一种类似于HTML的语法扩展,可以在JavaScript代码中编写类似HTML的结构。它允许我们以声明式方式描述UI组件的结构。 3. Props:Props是组件的属性,用于传递数据和配置参数给组件。通过props,我们可以向子组件传递数据并进行组件之间的通信。 4. State:State是用于存储和管理组件内部的数据的对象。当state发生变化时,React会自动重新渲染组件,并更新相应的视图。 5. 生命周期:React组件具有生命周期方法,这些方法在组件的不同阶段被调用,例如组件被创建、更新、卸载等。 6. Hooks:Hooks是React 16.8版本引入的特性,它允许我们在无需编写类组件的情况下使用状态和其他React特性。常用的Hooks包括useState、useEffect、useContext等。 7. 条件渲染:React允许我们根据条件来渲染不同的内容或组件。常用的条件渲染方式包括if语句、三元表达式和逻辑与(&&)运算符等。 8. 列表渲染:React提供了map方法来遍历数组或者列表,动态生成列表项。通过列表渲染,我们可以根据数据动态生成多个相似的组件。 9. 表单处理:React提供了一些事件和处理函数来方便地处理表单的输入和提交。通过onChange事件,我们可以监听表单元素的值变化,并将其保存到组件的state中。 10. 组件通信:React中的组件通信可以通过props、状态提升、上下文(Context)和全局状态管理工具(如Redux)等方式来实现。 这些是React中常用的知识点,当然还有更多深入的内容和特性可以学习和掌握。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值