react 0基础学习

2020-02-18  本文已影响0人  青争小台

npm i antd
npm i react-router-dom

react简介

前端三大主流框架

React与vue的对比

1、什么是模块化:是从代码的角度来进行分析的;把一些可复用的代码,抽离为单个的模块;便于项目的维护和开发;
2、什么是组件化:是从 UI 界面的角度 来进行分析的;把一些可服用的UI元素,抽离为单独的组件;便于项目的维护和开发;
3、组件化的好处:随着项目规模的增大,手里的组件越来越多;很方便就能把现有的组件,拼接为一个完整的页面;
4、Vue是如何实现组件化的: 通过 .vue 文件,来创建对应的组件, .vue 文件由三部分组成:template 结构;script 行为;style 样式
5、React如何实现组件化:大家注意,React中有组件化的概念,但是,并没有像vue这样的组件模板文件;React中,一切都是以JS来表现的;因此要学习React,JS要合格;ES6 和 ES7 (async 和 await) 要会用;

1、React是由FaceBook前端官方团队进行维护和更新的;因此,React的维护开发团队,技术实力比较雄厚;
2、Vue:第一版,主要是有作者 尤雨溪 专门进行维护的,当 Vue更新到 2.x 版本后,也有了一个以 尤雨溪 为主导的开源小团队,进行相关的开发和维护;

1、在社区方面,React由于诞生的较早,所以社区比较强大,一些常见的问题、坑、最优解决方案,文档、博客在社区中都是可以很方便就能找到的;
1、Vue是近两年才火起来的,所以,它的社区相对于React来说,要小一些,可能有的一些坑,没人踩过;

1、Vue,结合 Weex 这门技术,提供了 迁移到 移动端App开发的体验(Weex,目前只是一个 小的玩具, 并没有很成功的 大案例;)
2、React,结合 ReactNative,也提供了无缝迁移到 移动App的开发体验(RN用的最多,也是最火最流行的);

为什么要学习React

React中几个核心的概念

1、DOM的本质是什么:浏览器中的概念,用JS对象来表示 页面上的元素,并提供了操作 DOM 对象的API;
2、什么是React中的虚拟DOM:是框架中的概念,是程序员 用JS对象来模拟 页面上的 DOM 和 DOM嵌套;
3、为什么要实现虚拟DOM(虚拟DOM的目的):为了实现页面中, DOM 元素的高效更新
4、DOM和虚拟DOM的区别
DOM:浏览器中,提供的概念;用JS对象,表示页面上的元素,并提供了操作元素的API;
虚拟DOM:是框架中的概念;而是开发框架的程序员,手动用JS对象来模拟DOM元素和嵌套关系;本质: 用JS对象,来模拟DOM元素和嵌套关系;目的:就是为了实现页面元素的高效更新;

1、tree diff:新旧两棵DOM树,逐层对比的过程,就是 Tree Diff; 当整颗DOM逐层对比完毕,则所有需要被按需更新的元素,必然能够找到;
2、component diff:在进行Tree Diff的时候,每一层中,组件级别的对比,叫做 Component Diff;
如果对比前后,组件的类型相同,则**暂时**认为此组件不需要被更新;
如果对比前后,组件类型不同,则需要移除旧组件,创建新组件,并追加到页面上;
3、element diff:在进行组件对比的时候,如果两个组件类型相同,则需要进行 元素级别的对比,这叫做 Element Diff;

创建基本的webpack4.x项目

  1. 运行npm init -y 快速初始化项目
  2. 在项目根目录创建src源代码目录和dist产品目录
  3. 在 src 目录下创建 index.html
  4. 使用 cnpm 安装 webpack ,运行cnpm i webpack webpack-cli -D(如何安装 cnpm: 全局运行 npm i cnpm -g
  5. 注意:webpack 4.x 提供了 约定大于配置的概念;目的是为了尽量减少 配置文件的体积;
    • 默认约定了:
    • 打包的入口是src -> index.js
    • 打包的输出文件是dist -> main.js
    • 4.x 中 新增了 mode 选项(为必选项),可选的值为:developmentproduction;

使用 create-react-app 快速构建 React 开发环境

可以使用create-react-app -V查看当前版本

npm install -g create-react-app
create-react-app my-app
cd my-app/
npm start

打包发布

npm run build 
npm install -g serve
serve build
访问http://localhost:5000/

项目中使用antd

npm i antd
//实现组件的按需打包
npm i react-app-rewired customize-cra babel-plugin-import

在项目中使用 react

  1. 运行 cnpm i react react-dom -S 安装包
    react: 专门用于创建组件和虚拟DOM的,同时组件的生命周期都在这个包中
    react-dom: 专门进行DOM操作的,最主要的应用场景,就是ReactDOM.render()

  2. index.html页面中,创建容器:

 <!--html-- 容器,将来,使用 React 创建的虚拟DOM元素,都会被渲染到这个指定的容器中 -->
   <div id="app"></div>
  1. 导入包:
 //js
   import React from 'react'
   import ReactDOM from 'react-dom'
  1. 创建虚拟DOM元素:
//jsx
 // 这是 创建虚拟DOM元素的 API
 <h1 title="啊,五环" id="myh1">你比四环多一环</h1>
 //  第一个参数: 字符串类型的参数,表示要创建的标签的名称
 //  第二个参数:对象类型的参数, 表示 创建的元素的属性节点
 //  第三个参数: 子节点
 const  myh1 = React.createElement('h1', { title: '啊,五环', id: 'myh1' }, '你比四环多一环')
  1. 渲染:
  //js
 // 3. 渲染虚拟DOM元素
 // 参数1: 表示要渲染的虚拟DOM对象
 // 参数2: 指定容器,注意:这里不能直接放 容器元素的Id字符串,需要放一个容器的DOM对象
   ReactDOM.render(myh1, document.getElementById('app'))

JSX语法

什么是JSX语法:就是符合 xml 规范的 JS 语法;(语法格式相对来说,要比HTML严谨很多) webpack是不能识别jsx的语法的 需要babel包将其转换为React.creatElement()

  1. 如何启用 jsx 语法?
    • 安装能够识别转换jsx语法的包 babel/preset-react
    • 运行cnpm i @babel/preset-react -D
    • 添加 .babelrc 配置文件(新建一个名为.babelrc的文件)
    {
        "presets": ["@babel/preset-    env","@babel/preset-react"],
        "plugins": [
                    "@babel/plugin-transform-runtime",
                    "@babel/plugin-proposal-class-properties"
                    ]
    }
    
    • 添加babel-loader配置项(在webpack.config.js文件中):
    module: { //要打包的第三方模块
         rules: [
           { test: /\.js|jsx$/, use: 'babel-loader', exclude: /node_modules/ }
         ]
     }
    
    https://www.cnblogs.com/amcy/p/10273929.html
  2. jsx 语法的本质
    并不是直接把 jsx 渲染到页面上,而是 内部先转换成了 createElement 形式,再渲染的;

3.在 jsx 中混合写入 js 表达式
在 jsx 语法中,要把 JS代码写到 { } 中:

例:

//创建虚拟DOM元素:
const obj={name:"赵静怡",age:18,title:"哈哈"}
const myh2=<h2>我是h2</h2>
var flag=true;
const mydiv=<div>
                {obj.name}<!--js语法写在{}里  !-->
                <h1 title={obj.title}>{obj.age}</h1><!--直接绑定属性,不需要“:”  !-->
                {myh2}
                <div>{flag?1:2}</div>
             </div>

//渲染:
ReactDOM.render(mydiv,document.getElementById("app"))

遍历方式:

//1.普通方式:
var arr=[]
var obj=["A","B","C"];
obj.forEach((item,index)=>{
    arr.push(<h1 key={index}>{item}</h1>)
})
const mydiv=<div>{arr}</div>
//渲染
ReactDOM.render(mydiv,document.getElementById("app"))


//2.Map方式:
var obj=["A","B","C"];
const mydiv=<div className="box">
    {obj.map((item,index)=><h2 key={index}>{item}</h2>)}
    <p>
        <input type="checkbox" value="A" id="A"/>
        <label htmlFor="A">A</label>
    </p>
</div>
<!--渲染!-->
ReactDOM.render(mydiv,document.getElementById("app"))
<!--遍历时一定要传入key!-->

注意:

React中创建组件

第1种 - 创建组件的方式

使用构造函数来创建组件,如果要接收外界传递的数据,需要在 构造函数的参数列表中使用props来接收;

必须要向外return一个合法的JSX创建的虚拟DOM;

第2种 - 创建组件的方式

使用 class 关键字来创建组件
ES6 中 class 关键字,是实现面向对象编程的新形式;

两种创建组件方式的对比
1. 用构造函数创建出来的组件:叫做“无状态组件”,没有自己的私有数据和生命周期函数
2. 用class关键字创建出来的组件:叫做“有状态组件”,有自己的私有数据和生命周期函数
有状态组件和无状态组件之间的**本质区别**就是:有无state属性!

props和state/data的区别
props中的数据都是外界的 并且是可读的不可写的
state/data中的数据都是自己私有的 并且是可读可写的

ES6 class类

如果要生成一个对象实例,需要先定义一个构造函数,然后通过new操作符来完成。构造函数示例:

//函数名和实例化构造名相同且大写(非强制,但这么写有助于区分构造函数和普通函数)
function Person(name,age) {
    this.name = name;
    this.age=age;
}
Person.prototype.say = function(){
    return "我的名字叫" + this.name+"今年"+this.age+"岁了";
}
//通过构造函数创建对象,必须使用new 运算符
var obj=new Person("laotie",88);
console.log(obj.say());//我的名字叫laotie今年88岁了

React中组件传值

React中的样式问题

兄弟组件的并列写

将兄弟组件用标签包起来,语法:
ReactDOM.render(<div>组件1组件2</div>,document.getElementById("app"))
例:

ReactDOM.render(<div>
    <Login/>
    <Register/>
    </div>,document.getElementById("app"))

事件绑定及修改组件的值

react实现的双向数据绑定

组件的应用方式

容器组件和单纯组件

class Test extends React.Component{
    render(){
        return <div>
            <!--  加上这个就变成了容器组件用来来显示在组件标签中的孩子  !-->
            {this.props.children}
        </div>
    }
}


class App extends React.Component{
    constructor(){
        super();
        this.state={
            data:"大家好"
        }
    }
    render(){
        return <div>
            <Test>
                <span>呵呵</span>     
            </Test>
        </div>
    }
} 

组件的生命周期

每个组件的实例从创建到运行直到销毁在这个过程中会触发一系列的事件,这些事件就是生命周期的函数
react的生命周期分为三部分:

路由

路由传参

本地存储

componentWillMount() 初始化的时候在这个方法中读取localStorage的值

绑定回车事件

onKeyPress={(e)=>this.addlist(e)}

addlist(e){
   if(e.which!=13) return false
   console.log('我点击了回车键');
}

获取真实dom

首先给元素 添加一个 ref属性 ref="变量"
在方法中通过 this.refs.变量 来获取真实的dom元素
http://www.todolist.cn/
https://www.bootcdn.cn/
https://webthemez.com/demo/insight-free-bootstrap-html5-admin-template/index.html

Redux

Redux是针对JavaScript应用的可预测状态容器
就是一个应用的state管理库 组件之间数据共享
redux 是一个状态管理器,那什么是状态呢?状态就是数据
可预测性(predictable): 因为Redux用了reducer与纯函数(pure function)的概念,每个新的state都会由旧的state建来一个全新的state。因而所有的状态修改都是”可预测的”。
状态容器(state container): state是集中在单一个对象树状结构下的单一store,store即是应用程序领域(app domain)的状态集合。
JavaScript应用: 这说明Redux并不是单指设计给React用的,它是独立的一个函数库,可通用于各种JavaScript应用。
Redux模型中的几个组成对象action 、reducer、store
action:官方的解释是action是把数据从应用传到 store 的有效载荷,它是 store 数据的唯一来源;要通过本地或远程组件更改状态,需要分发一个action;
reducer:action发出了做某件事的请求,只是描述了要做某件事,并没有去改变state来更新界面,reducer就是根据action的type来处理不同的事件;
store:store就是把action和reducer联系到一起的对象,store本质上是一个状态树,保存了所有对象的状态。任何UI组件都可以直接从store访问特定对象的状态。
运行流程
在Redux中,所有的数据(比如state)被保存在一个被称为store的容器中 ,在一个应用程序中只能有一个store对象。当一个store接收到一个action,它将把这个action代理给相关的reducer。reducer是一个纯函数,它可以查看之前的状态,执行一个action并且返回一个新的状态

官网介绍
import { createStore } from 'redux'
/**

图片路径

后来看了看create-react-app的官网,官网明确说出最好将图片样式等放在public文件夹中,并且据我测试,文件夹名最好是assets


WechatIMG69.png
WechatIMG71.png

修改ant默认样式

拿到这个名字,直接在代码上进行修改。
在我们拿到的这个名字前面加:global(),把名字写在括号里面,直接写上你想要修改的样式就可以了。
:global(.has-error .ant-form-explain){
position: absolute;
}
这样直接修改会破坏其他的组件的样式,可以在你想要修改样式的标签外面定义一个父级元素,在用一个父级选择器就可以了。·

封装axios

http.js

import axios from 'axios'
import { message } from 'antd'
/*
函数返回值是promise对象
优化:
一、统一处理请求异常
    1.在外层抱一个自己创建的promise对象
    2.在请求出错时(catch),不reject(error),而是显示错误提示
二、异步得道不是response,而是response.data
    在异步请求成功resolve时,resolve(response.data)
*/
export default function http (url, data = {}, type = 'GET') {
    return new Promise((resolve, reject) => {
        let promise
        // 1.执行异步ajax请求
        if (type === "GET") {
            promise = axios.get(url, {
                params: data//配置对象
            })
        } else {
            promise = axios.post(url, data)
        }
        promise.then(response => {
            // 2.如果成功了,调用resolve(value),传入response
            resolve(response.data)
        }).catch(error => {
            // 3.如果失败了,不调用reject(error),而是提示异常信息
            // 如果调用reject就会触发catch,但是我们想要统一处理错误提示
            message.error('请求出错了了', error)
        })
    })
}

login.js

import http from './http.js'
export const login = (data) => http('/login', data, 'POST')

login.jsx

import React, { Component } from 'react'
import { Form, Input, Button, message } from 'antd';
import { UserOutlined, LockOutlined } from '@ant-design/icons';
import './login.scss'
import { login } from '../../api/login'

// 高阶函数
// 高阶组件
export default class Login extends Component {
    onFinish = async (values) => {
        console.log('Received values of form: ', values);
        // 1----
        // login(values).then(res => {
        //     console.log('ok', res)
        // }).catch(err => {
        //     console.log('no', err)
        // })

        // 2----
        // try {
        //     const response = await login(values)
        //     console.log('请求ok',response)
        // } catch (err) {
        //     console.log('请求出错',err)
        // }

        // 3---
        // const response = await login(values)
        // console.log('请求ok',response)

        // 4---
        // const response = await login(values)
        // const result =response.data
        // if(result.meta.status_code===422){
        //     message.success('登录成功')
        //     // replace不能再回到login,push还可以回到login
        //     this.props.history.replace('/')
        // }else{
        //     message.error('失败',result.msg)
        // }

        // 5---
        const result = await login(values)
        if(result.meta.status_code===422){
            message.success('登录成功')
            // replace不能再回到login,push还可以回到login
            this.props.history.replace('/')
        }else{
            message.error('失败',result.msg)
        }
    };
    render () {
        return (
            <div className='login'>
                <header className='header'>
                    <img src="assets/logo.png" alt="" />
                    <h1>电考:后台管理系统</h1>
                </header>
                <section className='content'>
                    <h2>用户登录</h2>
                    <Form
                        name="normal_login"
                        className="login-form"
                        initialValues={{
                            remember: true,
                        }}
                        onFinish={this.onFinish}
                    >
                        <Form.Item
                            name="username"
                            rules={[{ required: true, message: '请输入用户名!', },]}>
                            <Input prefix={<UserOutlined className="site-form-item-icon" />} placeholder="用户名" />
                        </Form.Item>
                        <Form.Item
                            name="password"
                            rules={[{ required: true, message: '请输入密码!', },]}>
                            <Input prefix={<LockOutlined className="site-form-item-icon" />} type="password" placeholder="密码" />
                        </Form.Item>
                        <Form.Item>
                            <Button type="primary" htmlType="submit" className="login-form-button">登录</Button>
                        </Form.Item>
                    </Form>
                </section>
            </div>
        )
    }
}

/*  async和await
简化promise对象的使用:
     1.不用再使用.then()来指定成功/失败的回调函数
     2.以同步编码(没有回调函数)方式实现异步流程

await:在返回promise的表达式左侧await,不想要promise,想要promise异步执行的成功的value数据
async:await所在函数(最近的)定义的左侧写async

onFinish = async (values) => {
    try {
        const response = await login(values)
        console.log('请求ok',response)
    } catch (err) {
        console.log('请求出错',err)
    }
};

onFinish = (values) => {
        console.log('Received values of form: ', values);
     login(values).then(res => {
        console.log('ok', res)
     }).catch(err => {
        console.log('no', err)
     })

    };
*/

431605993228_.pic.jpg
上一篇 下一篇

猜你喜欢

热点阅读