派大星

vuePress-theme-reco 派大星    2021 - 2022
派大星 派大星
主页
博客
  • 前端
  • JavaScript文章
  • 三级目录
  • 笔记
  • 学习笔记
  • 页面
  • CSS
  • HTML
  • 技术
  • 技术文档
  • GitHub技巧
  • 技术笔记
  • 实用工具
  • Nodejs
  • 博客搭建
  • 更多
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • JavaScript
  • 浏览器&网络
  • 前端框架
  • 资源工具
  • 持续集成
  • 小程序
  • 杂谈
  • React
  • Mysql
  • 面试题
  • uniapp
  • 《ES6 教程》笔记
  • 《Git》学习笔记
  • 《JavaScript教程》笔记
  • 《React》笔记
  • 核心概念
  • 高级指引
  • Hook
  • 案例演示
  • 《TypeScript 从零实现 axios》
  • 初识 TypeScript
  • TypeScript 常用语法
  • ts-axios 项目初始化
  • ts-axios 基础功能实现
  • ts-axios 异常情况处理
  • ts-axios 接口扩展
  • ts-axios 拦截器实现
  • ts-axios 配置化实现
  • ts-axios 取消功能实现
  • ts-axios 更多功能实现
  • ts-axios 单元测试
  • ts-axios 部署与发布
  • 《Vue》笔记
  • 基础
  • 组件
  • 过渡&动画
  • 工具
  • 规模化
  • 可复用性&组合
  • 其他
  • Vuex
标签
时间轴
关于
author-avatar

派大星

272

文章

69

标签

主页
博客
  • 前端
  • JavaScript文章
  • 三级目录
  • 笔记
  • 学习笔记
  • 页面
  • CSS
  • HTML
  • 技术
  • 技术文档
  • GitHub技巧
  • 技术笔记
  • 实用工具
  • Nodejs
  • 博客搭建
  • 更多
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • JavaScript
  • 浏览器&网络
  • 前端框架
  • 资源工具
  • 持续集成
  • 小程序
  • 杂谈
  • React
  • Mysql
  • 面试题
  • uniapp
  • 《ES6 教程》笔记
  • 《Git》学习笔记
  • 《JavaScript教程》笔记
  • 《React》笔记
  • 核心概念
  • 高级指引
  • Hook
  • 案例演示
  • 《TypeScript 从零实现 axios》
  • 初识 TypeScript
  • TypeScript 常用语法
  • ts-axios 项目初始化
  • ts-axios 基础功能实现
  • ts-axios 异常情况处理
  • ts-axios 接口扩展
  • ts-axios 拦截器实现
  • ts-axios 配置化实现
  • ts-axios 取消功能实现
  • ts-axios 更多功能实现
  • ts-axios 单元测试
  • ts-axios 部署与发布
  • 《Vue》笔记
  • 基础
  • 组件
  • 过渡&动画
  • 工具
  • 规模化
  • 可复用性&组合
  • 其他
  • Vuex
标签
时间轴
关于

React学习篇章四

vuePress-theme-reco 派大星    2021 - 2022

React学习篇章四

派大星 2021-01-07 React脚手架

# React04

# 回顾

foreach 遍历不修改源数据

map 处理数组的每个元素返回新数组

# 列表渲染

foreach 遍历不修改元数据

map处理数组的每个元素返回新数组

  • 在 react 中会把数组的元素挨个渲染到页面

  • 添加渲染标签的时候,返回一个数组

skill = ['uni-app','react']
//foreach
showALink(){
	let arr = []
this.skills.foreach((item,index)=>{
arr.push(<a>{item}</a>)
})
return arr
}
//map  箭头函数 如果结构体写了{}  就必须写return
showAlink2 =()=>this.skill.map((item,index)=>(
    <a key ={index}>{item}</a>
))

组件生命周期

componentDidmount 组件挂载时 发送请求

componentDiaupdate 组件更新时触发 监控组件状态[state,props]的变化

shouldComponentUpdate必须布尔类型的返回值 确定是否渲染 DOM true 渲染 false 不渲染 性能优化

componentWillUnmount组件将要挂载 回收资源操作

# 发送请求 fetch 浏览器支持发送请求的新标准 对比 XHR

fetch(url).then(res=>res.json()).then(res=>{
    console.log(res)
})

跨域 proxy node 的代理服务插件 http-proxy-middleware

target secure pathrewrite

子元素绑定 ref属性绑定子元素组件 可以调用到子元素的方法或者属性

# 语法学习

hook

hook 时 React16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性

// rfc 函数组件快捷方式
// react16.8版本后hook特性
// hook特性 函数组件使用useState
// useState 函数组件使用state
// 引入useState
import React, { useState } from "react";

export default function App() {
  // 2.useState state 和setState方法
  // 参数1 state的名称 参数2 修改state的方法 参数3 state的默认值
  // 相当于rcc中state = {num:1}
  const [num, setNum] = useState(1);
  const [num1, setNum1] = useState(100);
  return (
    <div>
      {num}
      <button onClick={() => setNum(num + 1)}>加1</button>
      <div>
        {num1}
        <button onClick={() => setNum1(num1 + 10)}>{num1}</button>
      </div>
    </div>
  );
}

# 生命周期 useEffect

// 函数组件的hook特性,提供了函数组件生命周期
// useEffect
import React, { useEffect, useState } from "react";

export default function App() {
  // useState
  const [show, setShow] = useState(false);
  return (
    <div>
      父组件
      {/* 调用子组件 */}
      <button onClick={() => setShow(!show)}>显示/隐藏子组件</button>
      {show ? <Son /> : null}
    </div>
  );
}

// 子组件
function Son() {
  const [num, setNum] = useState(1);
  // 练习  监控count值的变化
  // 更新前和更新后的值的变化
  // 第一段 挂载或者更新
  // 第二段 将要卸载
  // 第三段 监控数据变化
  useEffect(() => {
    // componentDidMount和componentDidUpdate结合
    console.log("挂载和刷新触发了");
    // 更新后的数据
    console.log("num更新后:", num);
    return () => {
      // componentWillMount 将要卸载触发
      console.log("将要卸载触发了");
      console.log("num更新前的数据:", num);
    };
    // [input]监控组件状态的变化 没有监控的值 就写[]
  }, [num]);
  const [count, setCount] = useState(100);
  useEffect(() => {
    console.log("Count更新后的变化", count);
    return () => {
      console.log("count更新前的变化", count);
    };
  }, [count]);
  return (
    <div style={{ border: "2px solid green" }}>
      <div>这是子组件</div>
      <button onClick={() => setNum(num + 1)}>{num}</button>
      <button onClick={() => setCount(count + 10)}>{count}</button>
    </div>
  );
}

# 路由系统

单页面 spa 的也买你切换 需要使用到路由功能

多个组件的路由和切换 使用路由

React 中默认没有安装路由 需要手动安装

安装不指定版本时最新版本 6

目前大部分的项目还可能处于版本 5

npm i react-router-dom@5

npm 卸载命令

npm uninstall react-router-dom

安装之后 在 package.json 确认下软件名称及其版本

官方文档:https://reactrouter.com/

其他中文文档 语法可能过时 要注意甄别

以下为版本 5 的写法

# ①建立几个页面

在/src/pages 目录下建立A.js,B.js,C.js

image-20220111142626883

页面组件内部,添加一些内容,生成一个组件,如果没有内容,切换路由会报错,如果页面组件内容为空,切换路由会报错

src\pages\A.js

import React, { Component } from 'react'

export default class A extends Component {
    render() {
        return (
            <div>
                A组件
            </div>
        )
    }
}

# ② 编写路由切换

/src/App.js

treesharking 树摇

基于 ES6 模块机制

import React, { Component } from "react";
/**
 * 路由的组成
 * 1.组件和路由对应关系  routes routes=[{path:'/a',component:'组件的名称'}]
 * 2.router 管理整个路由
 * 3.router-link 切换标签  to 路劲参数
 * 4.router-view 切换的组件展示的位置
 */
// 1.导入
// import as 别名  起个小名  方便调用
import {
  BrowserRouter as Router, //管理整个路由系统
  Route, //路径和组件的对应关系
  Switch, //类似router-view
  Link, //类似router-link的作用 切换组件
} from "react-router-dom";
// 2.导入页面组件
import A from "./pages/A";
import B from "./pages/B";
import C from "./pages/C";
// 3.路由管理
// Router 管理整个路由

export default class App extends Component {
  render() {
    return (
      <Router>
        {/* 切换标签 */}
        <div>
          <Link to="/a">A页面</Link>
          <Link to="/b">B页面</Link>
          <Link to="/c">C页面</Link>
        </div>
        <hr />
        {/* 对应关系和组件切换展示位置 */}
        <Switch>
          {/* Router 对应关系 path路径 component组件 */}
          <Route path="/a" component={A}></Route>
          <Route path="/b" component={B}></Route>
          <Route path="/c" component={C}></Route>
        </Switch>
      </Router>
    );
  }
}

# 路由练习

三分钟 15:00

制作 3 个页面 名称为 HomePage,NewsPage.js,ContactPage.js

首页,新闻页,联系我们

路由切换练习 以及路由传参

src/App.js

import React, { Component } from "react";
import { BrowserRouter as Router, Route, Switch, Link } from "react-router-dom";
import HomePage from "./pages/HomePage";
import NewsPage from "./pages/NewsPage";
import ContactPage from "./pages/ContactPage";

export default class App extends Component {
  render() {
    return (
      <Router>
        <div>
          <Link to="/HomePage">HomePage页面</Link>
          <br />
          {/* 传参 步骤二 */}
          <Link to="/NewsPage/100/标题">NewsPage页面</Link>
          <br />
          <Link to="/ContactPage">ContactPage页面</Link>
        </div>
        <hr />
        <Switch>
          {/* 默认访问的组件页面 */}
          {/* exact精确匹配 path路径 */}
          <Route path="/" exact component={HomePage}></Route>
          <Route path="/HomePage" component={HomePage}></Route>
          {/* 定义传参方式 步骤一 */}
          <Route path="/NewsPage/:id/:title" component={NewsPage}></Route>
          <Route path="/ContactPage" component={ContactPage}></Route>
        </Switch>
      </Router>
    );
  }
}

接收路由传参以及编程式跳转

src/pages/NewsPage.js

import React, { Component } from "react";

export default class NewsPage extends Component {
  // 在React中把组件外部传入的数据存放在props
  // 默认情况下路由参数也存放在props中
  render() {
    console.log(this.props);
    // es6解构语法
    const { id, title } = this.props.match.params;
    // 获取编程式跳转路由的方法
    const { push } = this.props.history;
    return (
      <div>
        NewsPage页面
        <div>id:{id}</div>
        <div>title:{title}</div>
        {/* 编程式跳转 通过事件触发的方法 */}
        <button onClick={() => push("/HomePage")}>回到首页</button>
        <button onClick={() => push("/ContactPage")}>去联系我们</button>
      </div>
    );
  }
}

尝试 6 版本的写法,需要卸载 5 版本

6 版本中 编程跳转和接收路由参数 只能使用 rfc

npm install react-router-dom
import React, { Component } from "react";
import { BrowserRouter as Router, Route, Routes, Link } from "react-router-dom";
import HomePage from "./pages/HomePage";
import NewsPage from "./pages/NewsPage";
import ContactPage from "./pages/ContactPage";

export default class App extends Component {
  render() {
    return (
      <Router>
        <div>
          <Link to="/HomePage">HomePage页面</Link>
          <br />
          {/* 传参 步骤二 */}
          <Link to="/NewsPage/100/标题">NewsPage页面</Link>
          <br />
          <Link to="/ContactPage">ContactPage页面</Link>
        </div>
        <hr />
        <Routes>
          {/* 默认访问的组件页面 */}
          {/* exact精确匹配 path路径 */}
          <Route path="/" exact element={<HomePage />}></Route>
          <Route path="/HomePage" element={<HomePage />}></Route>
          {/* 定义传参方式 步骤一 */}
          <Route path="/NewsPage/:id/:title" element={<NewsPage />}></Route>
          <Route path="/ContactPage" element={<ContactPage />}></Route>
        </Routes>
      </Router>
    );
  }
}

import React from 'react'
import { useParams,useNavigate } from 'react-router-dom'
// hook rfc 的特征
// 路由参数的解构  useParams()
// 编程式跳转  useNavigate()

export default function NewsPage() {
    const params =useParams();
    // es6 解构语法获取id和title
    const{id,title} = params
    // 获取跳转方式
    const navigate = useNavigate()
    return (
        <div>
            新闻页
            <div>id:{id}</div>
            <div>title:{title}</div>
            {/* 编程方式跳转 通过事件触发方法*/}
            <button onClick={()=>navigate('/HomePage')}>回到首页</button>
            <button onClick={()=>navigate('/ContactPage')}>联系我们</button>
        </div>
    )
}

# Redux

安装 redux

npm i react-redux

Redux 是 Flux 的一种实现 ,Flux 是一种思想 杜宇所有组件状态进行统一管理,保存到同一个地方,修改入口也统一。全局状态管理管理组件的状态

Vuex 和 Redux 就是 Flux 思想的具体实现

备份之前的 index.js 之后还要用 index.js,index.js 是默认的入口文件 现在用来写测试代码

src/index.js

/**
 * Vuex:vue的全局状态管理工具  5个核心概念
 * State 存储共享变量的
 * Getters 计算属性
 * Mutaions 修改方法  只能通过它定义的方法进行修改
 * Actions 异步操作
 * Modules 拆分模块
 *
 * 5个概念组成一个store /src/store/index.js
 * 存 修改
 * this.$store.commit('方法名称',要修改的参数)
 *
 * 读
 * 组件值读取  this.$store.state.XXXXX
 * 语法糖  ...mapState  写在计算属性中
 *
 * Vuex对用Redux
 * Vuex                         Redux
 * state                        state   初始化值
 * mutations                    reducer 定义修改方法
 * this.$store.commit()         this.store.dispatch() 修改
 * this.$store.state.xxx        this.store.getState(xxx) 读取
 */
// 导入createStore 从redux
import { createStore } from "redux";
// 1.状态初始化
const iniState = {
  num: 1,
};
// 2.定义修改方法
// 第一个参数 初始值
// 第二个参数 action形参  操作方法的名称 传对象格式 type属性存储操作方法名称
// 参数格式:action={type:'doAdd'}
const reducer = (state = iniState, action) => {
  switch (action.type) {
    case "doAdd":
      // ...state 展开默认state
      // 修改对应state后面的值,其他的值不修改返回
      return { ...state, num: state.num + 1 };
    default:
      break;
  }
};
// 3.创建store管理reducer
const store = createStore(reducer);
// 4.操作store
// 读取
// console.log(store.getState());
// 修改
store.dispatch({ type: "doAdd" });
store.dispatch({ type: "doAdd" });
store.dispatch({ type: "doAdd" });
console.log(store.getState());

// 作业: 存储一个 count的值  定义方法每次+10  实现修改和读取的操作