react入门

react库

​ 用于构建用户界面的JavaScript库

​ 注意!!! React是一个库不是一个框架

react库的特点:

  • 声明式:
  • 组件化:
  • 一次学习,随处编写:版本的变动较小

react的生态现在是阿里做的

一、创建项目

  1. 通过script标签引入,在学习时一般直接引用cdn引入

  2. 通过react的脚手架,创建项目进行开发,部署

    // 1.安装脚手架
    cnpm installl -g create-react-app
    // 2.创建项目
    create-react-app 01helloworld
    // 开发时运行的环境
    cd  01helloworld
    npm start
    

二、React的渲染

使用jsx的写法,可创建js元素

注意:jsx的元素,必须要有一个根元素

let root = 

这是根元素

使用函数的方式创建元素

let desc = "这是根组件";
function App(){
    reture (
        

{desc}

) } export.default App

三、React组件传值

关于组件的创建

  • 组件的创建第一种方法:函数式组件
function App () {
    return (
        

这是一个组件

) } export default App
  • 组件的创建第二种方法:变量式创建
const app = new App({
  desc:'类组件是继承React.Component的'
}).render();
render(app,document.querySelector('#root'))

定义类的方式

import { render } from "react-dom";
class App extends React.Component{
  render() {
    // props是render函数传进来的参数的,是默认存在,不需要实际声明
    return (

组件1

{this.props.desc}

) } } render(,document.querySelector('#root'));

注意!!!这是React16之后的写法,在这之前的js还没有扩展出类写法,因此在这之前一般采用以下的写法:

const App = React.createClass({
  render(){
    return 

xxxxxxx

} }); render(,document.querySelector('#root'));

四、JSX

JSX的优点:

  1. ​ JSX执行更快,编译为JavaScript代码时进行优化
  2. ​ 类型更安全,编译过程中能即时发现错误
  3. ​ JSX编写模板更加简单快速(相对而言)

注意!!!

  1. ​ Jsx与Vue类似,必须要有一个根节点
  2. ​ 正常的普通HTML必须小写,大写会默认认为是组件

JSX内部的表达式:{}

  1. 可以使用大多数的JS表达式:如: 变量,函数,对象,条件运算符,三元运算符
  2. 可以直接使用HTML,不需要进行任何处理
  3. 在使用类名的时候尽量使用className,因为class是React的内置关键字

总结:

  1. ​ JSX由HTML的元素构成
  2. 中间如果需要加入变量,需要用括号括起来
  3. 可以使用表达式,表达式中可以使用JSX对象
  4. 属性和对象内容都是用括号插入内容

五、JSX-Style样式

1.class中,不可以存在多个class属性

2.style样式中,如果存在多个单词时,第二个单词开始必须首字母大写,或者用-引起来,否则会报错

let exampleStyle = {
  background:'skyblue',
  borderBottom:'5px solid #ccc'
  background-image:
    "url('https://www.baidu.com/img/pc_1c6e30772d5e4103103bd460913332f9.png')"  
};

3. 多个类共存的操作

let ele4 = (
  
横着1 竖着2
); let DOMElement = ( // 样式的类名要写className,因为class在React中是关键字 // 后面可以使用变量,也可以使用字符串

hello world

{1+1}

{str+time}

{str+localTime()}

{temp>37.2? :'不隔离'}

);

4. 关于JSX的注释

{/* 必须在表达式内书写注释,否则报错 */}

六、条件循环

1. 条件判断

2. 循环

1. 简单的循环方式
let arr = ['芜湖','起飞','南通','哈哈哈哈'];
// 循环渲染
class ParentCom extends React.Component{
  constructor(props){
    super(props)
  }
  render() {
    let res = [];
    arr.forEach((item,index)=>{
      let temp = 
  • {item}
  • ; res.push(temp) }); // 这里的循环方式也可以使用map的方法 return (
      {res}
    ) } }
    2. 简化后的循环方式

    ​ 使用数据的map方法,对每一项数据按照jsx的形式进行加工,最终得到1个每一项都是jsx对象的数值,

    七、组件

    注意ReactDom.render()一般只会放一个根组件,但是一个根组件可以加载无数的组件

    1. 函数式组件

    import {render} from "react-dom";
    import React from 'react';
    import logo from './logo.svg';
    // props是父组件传进来的参数
    // 比如  即: props.weather = '下雨'
    function App(props) {
      // 注意,在括号中可以任何有效的JavaScript表达式并用大括号引起来
      return (
        
    logo

    Edit src/App.js and save to reload.

    {desc}

    {props.desc}

    Learn React
    ); }

    2. 类组件

    import {render} from "react-dom";
    import React from 'react';
    class App extends React.Component{
      render() {
        // props是render函数传进来的参数的,是默认存在,不需要实际声明
        return (

    组件1

    {this.props.desc}

    ) } } // 组件的是需要render函数返回模板 // 类组件不用刻意声明形参 // 比如 即: this.props.weather = '下雨'

    3. 复合组件

    class ChildCom extends React.Component{
        render(){
            return(
                

    hello {this.props.name} !!!

    ) } } class ParentCom extends React.Component{ render() { // props是render函数传进来的参数的,是默认存在,不需要实际声明 return (

    组件1

    今天的天气是: {this.props.weather}

    {this.props.desc}

    ) } } // 复合组件传参的方式 //

    4. 函数式与类组件的区别

    1. 类组件可以自定义事件,函数式组件不方便设置事件
    2. 内容定死,只传一些简单的参数,就是使用函数式组件,即为静态组件
    3. 函数式组件操作简单,但可支持功能较少
    4. 类组件用于交互和数据修改

    注意!!!无论是类组件还是函数式组件的调用都是 这种的方式

    八、props

    1. 父传递子组件

    要对子组件进行控制,如:是否显示,则只需要在父组件处传入一个布尔值即可:

    // 父组件
    class ParentCom extends React.Component{
      constructor(props){
        super(props);
        this.state = {
          isActive:true
        };
        this.changeShow = this.changeShow.bind(this)
      }
      changeShow(){
        this.setState({
          isActive:!this.state.isActive
        })
      }
      render() {
        return (
          

    这是父元素控制子元素的操作

    ) } } // 子组件 class ChildCom extends React.Component{ constructor(props){ super(props) } render() { let ele = null; if (this.props.isActive) { return (

    这是子组件

    ) // 需要注意这里无论如何都需要返回一个模板对象 }else { return ( null ) } } }

    2. 子组件向父组件数据传递

    // 实现子传父
    class ParentCom extends React.Component{
      constructor(props) {
        super(props);
        this.state = {
          childData:'',
        }
      }
      setChildData=(data)=>{
        this.setState({
          childData:data
        })
      };
      render() {
        return (
          

    这个是子元素传递给父元素的数据:{this.state.childData}

    {/* 往子组件处传递一个函数,用以控制父组件的内容 */}
    ) } } class ChildCom extends React.Component{ constructor(props){ super(props); this.state = { msg:'hello world' }; // 这里的绑定也可以进行绑定 this.sendData = this.sendData.bind(this) } sendData(){ console.log(this.state.msg); this.props.setChildData(this.state.msg) } render() { return (
    ) } }

    九、React事件

    特点:

    1. react事件,绑定事件的命名,驼峰命名
    2. 传入1个函数,而不是字符串,如果的

    事件对象:

    ​ React返回的事件对象是代理处理后的事件对象,如果想要查看事件对象的具体值,必须之间输出事件对象的属性

    ​ 原生的JS,可以直接使用return false,来阻止浏览器的默认行为

    ​ 但是因为React代理处理了原生JS使得return false 变为无效,要阻止浏览器的默认行为就使用 e.preventDefault

    React事件传参

    1. 使用函数的方式

      
      
    2. 不使用箭头函数方式

      
      

    十、组件条件循环渲染

    1. 三元运算符

    // 组件1
    function UserGreet() {
      return (
        

    你好,尊敬的用户

    ) } // 组件2 function UserLogin() { return (

    你好请登录

    ) } // 条件渲染的主组件 class ParentCom extends React.Component{ constructor(props){ super(props); this.state = { isLogin:false, } } changeEvent = (e)=>{ console.log(e); this.setState({isLogin:!this.state.isLogin}) }; render() { let ele = null; /* 条件渲染组件的方式 if (this.state.isLogin){ ele = }else { ele = }*/ // 这里可以使用三元运算符 ele = this.state.isLogin?:; return (

    这是头部

    {ele}

    这是尾部

    ) } }

    2. 列表循环渲染

    十一、React制作疫情地图

    1.疫情数据的API接口

    注意!!! (不允许跨域请求)

    https://c.m.163.com/ug/api/wuhan/app/index/feiyan-data-list?t=1580892891419

    2.写入一个Json数据文件

    3.导入Json数据

    import jsonData from "./feiyan";
    console.log(jsonData);
    

    4.设置(设计)数据模型

    let provinceObj = {
      // "广东省":{
      //   confirm:'',
      //   suspect:'',
      //   heal:'',
      //   deal:''
      // }
    };
    

    5.进行数据累加

    jsonData.data.list.forEach((item,index)=>{
      // 数据的初始化处理
      if (provinceObj[item.province]===undefined){
        provinceObj[item.province] = {
          confirm:0,
          suspect:0,
          heal:0,
          dead:0,
        }
      }
      // 数据异常处理
      item.confirm = item.confirm?item.confirm:0;
      item.suspect = item.suspect?item.suspect:0;
      item.heal = item.heal?item.heal:0;
      item.dead = item.dead?item.dead:0;
      // 对数据进行累加处理,以获取每个省份的数值
      provinceObj[item.province] = {
        confirm:provinceObj[item.province].confirm+item.confirm,
        suspect:provinceObj[item.province].suspect+item.suspect,
        heal:provinceObj[item.province].heal+item.heal,
        dead:provinceObj[item.province].dead+item.dead,
      }  
    });
    let provinceList = [];
    for (let item in provinceObj) {
      provinceObj[item].province = item;
      provinceList.push(provinceObj[item])
    }
    

    6.对数据进行排序

    // 对数组进行降序排序
    let provinceListSort = provinceList.sort((a,b)=>{
      if (a.confirm > b.confirm) {
        return -1
      }else {
        return 1
      }
    });
    

    7.将数据渲染至页面上

    import React from 'react';
    import ReactDOM from 'react-dom';
    class ParentCom extends React.Component {
      constructor(props) {
        super(props);
        this.state = {};
      }
    
      render() {
        return (
          

    中国病例

    • 地区 确诊 死亡 疑似
    • { this.props.list.map((item,index)=>{ return (
    • {item.province} {item.confirm} {item.dead} {item.suspect}
    • ) }) }
    ); } } ReactDOM.render(,document.querySelector('#root'));

    十二、React的生命周期

    生命周期的3个状态:

    1. mount:挂载
    2. update:数据更新
    3. unMount:卸载

    十三、 表单

    1. 必须绑定value值
    2. 必须绑定onChange事件

    十四、Ajax与React

    本次小案例运用到的是技术有:

    • axios网路请求
    • express后端框架
    • React前端框架
    • AJax异步请求

    1.API接口

    https://i.snssdk.com/ugc/hotboard_fe/hot_list/template/hot_list/forum_tab.html?activeWidget=1

    获取到首页的信息后查看Ajax的数据请求

    可以获取到首页的数据请求

    以及

    2.建议服务器

    • express --view=ejs react-serve
    • cd react-serve
    • npm install

    3.axios的安装

    • npm install axios

    十五、React实现todoList

    复习一下React的事件机制

    涉及到的技术有:Ref以及键盘事件

    十六、关于prop-types

    1.prop-types介绍

    prop-types是用于限制父组件传给子组件的数据类型,以及是否为必须的数据

    ​ prop-types的报错只是表明与声明的规范不一致导致的报错,并不一定会影响最终的DOM渲染

    2. prop-types的安装

    ​ 自从React V15之后,prop-type就作为单独的插件,需要另外的安装,而且也不是必须使用的插件

    安装:

    npm i prop-types --save

    3.prop-types的使用

    // 1. 导入prop-types
    // ES6的写法
    import PropTypes from 'prop-types';
    // ES5的写法
    var PropTypes = require('prop-types');
    
    // 2. 创建一个组件
    class MyComponent extends React.Component {
      construction(props){
          super(props)
      }  
      render() {
        // ... 写入需要生成的DOM元素
      }
    }
    
    // 3. 使用prop-types
    MyComponent.propTypes = {
        // 定义类型为字符串
        desc:PropTypes.string,
        // 定义类型为数字类型
        x:PropTypes.number,
        // 定义类型为数字类型,且为必须的数字类型
        y:PropTypes.number.isRequrie
    }
    // 4. 使用prop-types的默认属性值
    MyComponent.defaultProps = {
        y:2
    };
    

    当然还有另外一种写法:

    class MyComponent extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          title:this.props.title
        };
        console.log(this.props);
      }
      static propTypes = {
        desc:PropTypes.string,
        x:PropTypes.number,
        y:PropTypes.number.isRequired
      };
      static defaultProps = {
        y:2
      };
      render() {
        return (
          

    这是{this.state.title}

    {this.props.children} {this.props.x+this.props.y}
    ); } }

    十七、React插槽

    ​ 组件中写入自定义内容,这些内容可以被识别和控制,

    1.原理

    插槽的内容会默认传入props.children处,直接调用可以使用this.props.children

    组件中的HTML内容直接全部插入,调用{this.props.children}

    根据HTML内容的不同插入的内容也不同的,(即对组件插槽进行处理)

    // 父组件
    
              

    这是放置头部的内容

    这是放置主要内容的内容

    这是放置尾部的内容

    // 定义子组件 class ChildCom extends React.Component { render() { let headerCom,mainCom,footerCom; this.props.children.forEach((item, index)=>{ if (item.props["data-position"] === "header"){ headerCom = item } else if (item.props["data-position"] === "main") { mainCom = item }else { footerCom = item } }); return (
    {headerCom}
    {mainCom}
    {footerCom}
    ); } }

    十八、 React 路由

    1.安装

    cnpm i react-router-dom --save

    2.路由的三大组件

    1. Router:所有的路由的根组件
    2. Link:用于页面的跳转相当于HTML的A标签
    3. Route:路由根组件下面匹配的组件

    3.写一个简单的路由

    
        
    Home Product Me
    {/* 如果需要精确匹配就需要加入exact属性 */}

    4.路由传参

    外面显示的所有内容:

    Home Product Me
    {/* 如果需要精确匹配就需要加入exact属性 */}

    5.路径切换

    路由的切换,默认采用的push方法,可以前进后退

    replace:进入的该路由之后,就会将该路由设置为默认首页,此时不可以前进或者后退

    
        
    Me

    6.动态路由

    
        
    News
    {/* this.props.match.params.id 获取动态路由的信息 */}

    7.路由重定向

    // 当访问到LoginInfo组件的是否,该组件会跟条件重定向至不同的内容
    function LoginInfo(props) {
      // props.loginState = "success";
      // props.loginState = "fail";
      console.log(props);
      if (props.location.state.loginState === "success"){
        return (
          
        )
      }else {
        return  (
          
        )
      }
    }
    
    

    8.路由函数式导航

    class ChildCom extends React.Component {
      toIndex = ()=>{
        console.log(this.props);
        this.props.history.push("/",{msg:'从childCom发给首页的数据'})
          {/* 首页接收数据是以 this.props.location.state.msg */}  
      };
      render() {
        return (
          
    ); } }

    9.Switch组件

    让switch组件内容的route只匹配1次,只要匹配到了内容,便不会往下匹配

    
        
            {/* 此时不会显示abc2页面 */}
            (

    这是abc1页面

    )} /> (

    这是abc2页面

    )} />

    十九、Redux状态管理树

    ​ 解决React数据管理(状态管理),用于中大型项目,数据比较庞大,且组件间的数据交互多的情况下使用

    Redux的特点:

    1. Store:数据仓库,保存数据的地方
    2. state:state是一个对象,数据仓库的所有数据都放到state里面
    3. action:与Vue有点区别,action就是一个动作用于触发数据改变的方法,不是用于Ajax异步请求
    4. dispatch:将action动作触发成方法
    5. Reducer:是一个函数,通过获取动作,改变数据生成一个新的状态state从而改变页面

    1.安装Redux

    cnpm install redux --save

    2.初始化仓库

    // 1.导入redux
    
    // 2.创建store仓库
    const store = createStore(reducer);
    
    // 3.初始化仓库数据以及方法
    const reducer = function (state = {num: 0}, action) {
      console.log(action); // 输出{type: "add"}
      switch (action.type) {
        case "add":
          state.num++;
          break;
        case "decrement":
          state.num--;
          break;
      }
      return {...state}
    };
    // 4.调用数据
    function add() {
      // 通过仓库的方法进行修改数据
      store.dispatch({type: "add"});
      // console.log(store.getState());
    }
    function decrement() {
      // 通过仓库的方法进行修改数据
      store.dispatch({type:"decrement"})
    }
    // 获取数据的方式
    let state = store.getState()
    // 5.修改视图--监听数据的变化重新渲染视图
    store.subscribe(()=>{
            ReactDOM.render(, document.getElementById('root'));
        }
    )
    
    

    3.React-redux

    安装:

    cnpm i react-redux --save

    概念:

    1. Province

    使用:

    1. 初始化仓库数据

      function reducer(state=0,action) {
        switch (action.type) {
          case "add":
            state.num++;
            break;
          case "decrement":
            state.num--;
            break;
          default:
            break;
        }
        return {...state}
      }
      
    1. 实例化数据仓库

      const store = createStore(reducer);
      
    1. 数据的获取--映射函数

      // 设置action
      let addAction = {
          type:"add"
      }
      
      // 将state映射到props函数中
      function mapStateToProps(state) {
        return {
          value:state.num,
        }
      }
      // 将修改state数据的方法,映射到props,默认会传入store里的dispatch方法
      function mapDispatchToProps(dispatch) {
        return {
          onAddClick:()=>{
            dispatch(addAction)
          },
       onDecrementClick:()=> dispatch({type:"decrement"})
        }
      }
      
    1. 将两个映射函数结合成一个新的App函数

      const App = connect(
        mapStateToProps,
        mapDispatchToProps
      )(Counter)
      
    2. 渲染组件

      ReactDOM.render(
        
          
        ,
        document.getElementById('root')
      )
      

    你可能感兴趣的:(react入门)