react组件间传值

没有特别的幸运,那么就特别的努力!!!

React + ReactHook + ReactRouter + Redux + Axios + Less 移动端h5搭建新项目

  • 第一个React项目创建
  • 安装路由 react-router-dom
    • router路由 index.js
    • App.js
    • 页面跳转
    • 接收跳转传参
  • react 生命周期
    • 安装antd
    • 安装Axios
      • 创建 api 文件夹
      • 封装 axios
    • 参考项目地址
  • react组件间传值
  • 示例1:redux
  • 示例2
    • for循环
    • 1.父传子 props
    • 2.子传父 父组件定义一个方法
    • 3.隔组件传值
      • 完整代码

第一个React项目创建

你需要在你的机器上安装 Node >= 8.10 和 npm >= 5.6。要创建项目

npx create-react-app my-app
cd my-app
npm start

第一行的 npx 不是拼写错误 —— 它是 npm 5.2+ 附带的 package 运行工具。

安装路由 react-router-dom

npm install react-router-dom

在src下面新建一个router文件夹

router路由 index.js

// router文件夹下面新建一个index.js文件
import NotFound from '../view/error';
import Login from '../view/login';
import { Suspense } from 'react';
import { Navigate, useRoutes } from 'react-router-dom';


const staticRoutes = [
  {
    path: '/',
    element: <Navigate to="error" />
  },
  {
    path: '/login',
    element: <Login />,
    meta: {
      title: '登录页'
    }
  },
  {
    path: '/error',
    element: <NotFound />
  },
  {
    path: '*',
    element: <Navigate to="error" />
  }
];

function recursionRoutes(routes) {
  routes.forEach((route) => {
    if (route.component) {
      route.element = (
        <Suspense>
          <route.component />
        </Suspense>
      );
    }
    route.children && recursionRoutes(route.children);
  });
}

recursionRoutes(staticRoutes);


export default function Routes() {
  return useRoutes([...staticRoutes]);
}

App.js

import { BrowserRouter } from 'react-router-dom';
import Routes from './router';
import './App.css';

function App() {
  return (
    <BrowserRouter>
      <Routes></Routes>
    </BrowserRouter>
  );
}

export default App;

页面跳转

import React from  "react"
import { useNavigate } from 'react-router-dom'

const Error = () =>{
  const history = useNavigate()
  const loginHandle = () => {
    // 页面跳转方法
    history('/ErrorDetail',{ state: { id: '1' }})
  }
  return(
    <div>
      首页
      <hr />
      <div onClick={loginHandle}>点击进详情</div>
    </div>
  )
}

export default Error

接收跳转传参

import React, {useEffect} from "react";
import { useLocation } from "react-router-dom";

const Detail = () =>{
  const { state } = useLocation()
  useEffect(()=>{
    console.log('父级页面参数',state)
  },[]) //仅在挂载和卸载的时候执行

  return(
    <div>
      详情
    </div>
  )
}

export default Detail

react 生命周期

安装antd

node版本 – Expected version “^12.22.0 || ^14.17.0 || >=16.0.0”

yarn add antd

修改 src/App.js,引入 antd 的按钮组件。

import React from 'react';
import { Button } from 'antd';
import './App.css';

const App = () => (
  <div className="App">
    <Button type="primary">Button</Button>
  </div>
);

export default App;

修改 src/App.css,在文件顶部引入 antd/dist/antd.css。

@import '~antd/dist/antd.css';

安装Axios

npm i axios
yarn add axios

创建 api 文件夹

在项目 src 目录中创建一个 api 目录,用来存放所有的请求接口。

// 在 api 目录中创建一个 categories.js 文件
import http from '../utils/axios';

/**
 * 获取首页列表
 */
 function getCategoriesAsync(){
  return  http("get",'/zlb/monthly/learning/enabled/list');
}

export {
  getCategoriesAsync
}

封装 axios

在项目 src 目录中创建一个 utils 目录,用来存放工具类的文件,我们将 axios 的封装文件 axios.js 也可以放在里面。

/**
 * 网络请求配置
 */
import axios from "axios";

axios.defaults.timeout = 100000;
axios.defaults.baseURL = "https://gateways-test.shiduais.com";

/**
 * http request 拦截器
 */
axios.interceptors.request.use(
  (config) => {
    config.data = JSON.stringify(config.data);
    config.headers = {
      "Content-Type": "application/json",
    };
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

/**
 * http response 拦截器
 */
axios.interceptors.response.use(
  (response) => {
    if (response.data.errCode === 2) {
      console.log("过期");
    }
    return response;
  },
  (error) => {
    console.log("请求出错:", error);
  }
);

/**
 * 封装get方法
 * @param url  请求url
 * @param params  请求参数
 * @returns {Promise}
 */
export function get(url, params = {}) {
  return new Promise((resolve, reject) => {
    axios.get(url, {
        params: params,
      }).then((response) => {
        landing(url, params, response.data);
        resolve(response.data);
      })
      .catch((error) => {
        reject(error);
      });
  });
}

/**
 * 封装post请求
 * @param url
 * @param data
 * @returns {Promise}
 */

export function post(url, data) {
  return new Promise((resolve, reject) => {
    axios.post(url, data).then(
      (response) => {
        //关闭进度条
        resolve(response.data);
      },
      (err) => {
        reject(err);
      }
    );
  });
}

/**
 * 封装patch请求
 * @param url
 * @param data
 * @returns {Promise}
 */
export function patch(url, data = {}) {
  return new Promise((resolve, reject) => {
    axios.patch(url, data).then(
      (response) => {
        resolve(response.data);
      },
      (err) => {
        msag(err);
        reject(err);
      }
    );
  });
}

/**
 * 封装put请求
 * @param url
 * @param data
 * @returns {Promise}
 */

export function put(url, data = {}) {
  return new Promise((resolve, reject) => {
    axios.put(url, data).then(
      (response) => {
        resolve(response.data);
      },
      (err) => {
        msag(err);
        reject(err);
      }
    );
  });
}

//统一接口处理,返回数据
// eslint-disable-next-line import/no-anonymous-default-export
export default function (fecth, url, param) {
  let _data = "";
  return new Promise((resolve, reject) => {
    switch (fecth) {
      case "get":
        console.log("begin a get request,and url:", url);
        get(url, param)
          .then(function (response) {
            resolve(response);
          })
          .catch(function (error) {
            console.log("get request GET failed.", error);
            reject(error);
          });
        break;
      case "post":
        post(url, param)
          .then(function (response) {
            resolve(response);
          })
          .catch(function (error) {
            console.log("get request POST failed.", error);
            reject(error);
          });
        break;
      default:
        break;
    }
  });
}

//失败提示
function msag(err) {
  if (err && err.response) {
    switch (err.response.status) {
      case 400:
        alert(err.response.data.error.details);
        break;
      case 401:
        alert("未授权,请登录");
        break;

      case 403:
        alert("拒绝访问");
        break;

      case 404:
        alert("请求地址出错");
        break;

      case 408:
        alert("请求超时");
        break;

      case 500:
        alert("服务器内部错误");
        break;

      case 501:
        alert("服务未实现");
        break;

      case 502:
        alert("网关错误");
        break;

      case 503:
        alert("服务不可用");
        break;

      case 504:
        alert("网关超时");
        break;

      case 505:
        alert("HTTP版本不受支持");
        break;
      default:
    }
  }
}

/**
 * 查看返回的数据
 * @param url
 * @param params
 * @param data
 */
function landing(url, params, data) {
  if (data.code === -1) {
  }
}


参考项目地址

https://gitee.com/hammer1010_admin/react-app.git




react组件间传值

示例1:redux

state => redux中的state是不能直接修改的,只能通过action来修改,相当于我们在单例中定义setter方法。

action => 要更改state中的内容,你需要发送action。一个action是一个简单的对象,用来描述state发生了什么变更。

reducer => reducer就是根据action来对state进行操作。

react组件间传值_第1张图片

1.redux和react没有任何关系
2.redux状态管理器
3.redux公共的容器,数据 组件
// 安装redux
yarn add redux --save
或npm install redux --save

index.js引入

import {createStore} from 'redux'

const store = createStore(counter); // 创建store
const render=()=>{
  ReactDOM.render(
      <App store={store}/>, //传入
    document.getElementById('root')
  );
}
render(); // 渲染
store.subscribe(render);  // 监听state的变化

目录结构,下面是完整代码
react组件间传值_第2张图片
index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import {createStore} from 'redux'
import {counter} from './redux/reducers'
import App from './redux1/app';
import reportWebVitals from './reportWebVitals';

const store = createStore(counter); // 创建store
const render=()=>{
  ReactDOM.render(
      <App store={store}/>,
    document.getElementById('root')
  );
}
render(); // 渲染
store.subscribe(render);  // 监听state的变化

reportWebVitals();

app.jsx

import React from "react";
import * as actions from "../redux/actions";

export default class App extends React.Component{
  state={
    count:0
  }
  add=()=>{
    const num = this.refs.numSelect.value * 1;
    // const count = this.state.count + num;
    // this.setState({count})
    this.props.store.dispatch(actions.increment(num));
  }
  del=()=>{
    const num = this.refs.numSelect.value * 1;
    this.props.store.dispatch(actions.decrement(num));

  }
  async=()=>{

  }

  render(){
    return(
      <div>
        <p>展示count:{this.props.store.getState()}</p>
        <select ref="numSelect">
          <option value="1">1</option>
          <option value="2">2</option>
          <option value="3">3</option>
        </select>
        <button onClick={this.add}>+</button>{' '}
        <button onClick={this.del}>-</button>{' '}
        <button onClick={this.async}>increment async</button>
      </div>
    )
  }
}

actions.js

import {INCREMENT,DECREMENT} from './actionType'
export const increment = number => ({type:INCREMENT,number})
export const decrement = number => ({type:DECREMENT,number})

actionType.js

export const INCREMENT = 'increment'
export const DECREMENT = 'decrement'

reducers.js

import {INCREMENT,DECREMENT} from './actionType'
export function counter(state=0,action){
    switch(action.type){
        case INCREMENT:
            return state + action.number
        case DECREMENT:
            return state - action.number
        default:
            return state
    }
}

示例2

react组件间传值_第3张图片

for循环

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      infoList: ['Jack','sim','tom']
    }
  }
  render() {
    return (
        <div>{this.state.infoList.map((item,index)=>(
          <div key={index}>{item}</div>
        ))}</div>

		{/* 
{this.state.infoList.map((item,index)=>{ return
{item}
})}
*/
} ); } }

1.父传子 props

   <label>
        <input type="checkbox" checked={this.props.isAllChecked} onChange={this.handlerSelectAll} />全选
    </label>

2.子传父 父组件定义一个方法

// 父: 定义一个方法抛出
    <TodoHeader addTodo = {this.addTodo}/>

    addTodo = (todoItem)=>{
      this.state.todos.push(todoItem)
      // 
      this.setState({
        todos:this.state.todos
      })
    }
    
// 子:
    <input type="text" onKeyUp={this.handelKeyUp} placeholder="请输入你的任务名称,按回车键确认" className="form-control"/>

    handelKeyUp = (e)=>{
        // 获取input的值
        if(e.keyCode == 13){
            let value = e.target.value;
            if(!value) return false
            let newTodoItem = {
                text:value,
                isDone:false
            }
            e.target.value = ''
            // 调用父组件传过来的方法
            this.props.addTodo(newTodoItem)
        }
        
    }

3.隔组件传值

// 父:app.js --- 1.定义一个方法抛出
 deleteFather = (val) =>{
    this.state.down = val
    this.setState({
      down:this.state.down
    })
  }
  render () {
    return (
      <div className="App">
        <Footer {...this.state} deleteFather = {this.deleteFather} />
      </div>
    );
  }
  
// 子:Footer --- 2.子组件 must 传{...this.props}
import React from 'react';
import List from './list'
class Header extends React.Component{

  render(){
    return(
      <div>
        <div>隔代组件传值:</div>
        <List down={this.props.down} {...this.props}/>
      </div>
    )
  }
}
export default Header;

// 孙(List)--- 3.调用父组件方法
import React from 'react';
class Header extends React.Component{
  delete = () =>{
    this.props.deleteFather("已经删除了")
  }
  render(){
    return(
      <div>
        <div>孙组件:{this.props.down}</div>
        <button onClick={this.delete}>删除底部</button>
      </div>
    )
  }
}
export default Header;

完整代码

目录结构
react组件间传值_第4张图片
app.js

import React from 'react'
import logo from './logo.svg';
import './App.css';
import Header from './components/header';
import Content from './components/content';
import Footer from './components/footer';

class App extends React.Component {
  constructor(props){
    super(props)
    this.state = {
      top: '我是头部',
      list: '我是中间部分',
      down: '我是底部',
    }
  }
  getChildren = (val) =>{
    this.state.list = '原先值:' + this.state.list + '---现在变成' + val
    this.setState({
      list:this.state.list
    })
  }
  deleteFather = (val) =>{
    this.state.down = val
    this.setState({
      down:this.state.down
    })
  }
  render () {
    return (
      <div className="App">
        <Header {...this.state} /><hr />
        <Content getChildren = {this.getChildren}/><div>{this.state.list}</div><hr />
        <Footer {...this.state} deleteFather = {this.deleteFather} />
      </div>
    );
  }
}

export default App;

header.js

import React from 'react';
class Header extends React.Component{

  render(){
    return(
      <div>
        <div>组件header:</div>
        <div>直接拿取父元素的值:{this.props.top}</div>
      </div>
    )
  }
}
export default Header;

content.js

import React from 'react';
class Header extends React.Component{
  handelKeyUp = (e) =>{
    if(e.keyCode === 13){
      let val = e.target.value;
      if(!val) return false
      e.target.value = ''
      // 调用父组件传过来的方法
      this.props.getChildren(val)
    }
  }
  render(){
    return(
      <div>
        <div>组件content:</div>
        <div>子给父级传值:<input type="text" onKeyUp={this.handelKeyUp} placeholder="请输入你的任务名称,按回车键确认"/></div>
        
      </div>
    )
  }
}
export default Header;

footer.js

import React from 'react';
import List from './list'
class Header extends React.Component{

  render(){
    return(
      <div>
        <div>隔代组件传值:</div>
        <List down={this.props.down} {...this.props}/>
      </div>
    )
  }
}
export default Header;

list.js

import React from 'react';
class Header extends React.Component{
  delete = () =>{
    this.props.deleteFather("已经删除了")
  }
  render(){
    return(
      <div>
        <div>孙组件:{this.props.down}</div>
        <button onClick={this.delete}>删除底部</button>
      </div>
    )
  }
}
export default Header;

希望能帮助到大家,同时祝愿大家在开发旅途中愉快!!!

拿着 不谢 请叫我“锤” !!!

你可能感兴趣的:(react,前端,react)