React 学习笔记

1-列表渲染
const songs = [
  { id: 1, name: "111" },
  { id: 2, name: "222" },
  { id: 3, name: "333" },
];

function App() {
  return (
    <div className="App">
      <ul>
        {songs.map((item) => (
          <li key={item.id}>{item.name}</li>
        ))}
      </ul>
    </div>
  );
}

export default App;
2-条件渲染
const flag = true;
function App() {
  return <div className="App">{flag ? <span>app</span> : null}</div>;
}

export default App;
3-精简条件渲染
const getHtag = (type) => {
  if (type === 1) {
    return <h1>this is h1</h1>;
  }
  if (type === 2) {
    return <h2>this is h2</h2>;
  }
  if (type === 3) {
    return <h3>this is h3</h3>;
  }
};
function App() {
  return <div className="App">{getHtag(2)}</div>;
}

export default App;

4-样式控制

与vue的class不同,react为className

文件内样式以自定义对象,用"style={自定义对象}"的形式写在标签内

import "./app.css";
const style = {
  color: "red",
  fontSize: "30px",
};
function App() {
  return (
    <div className="App">
      <span style={style}>span</span>
      <span className="active">span</span>
    </div>
  );
}

export default App;
5-动态类名

与vue相似,采用三元表达式完成

import "./app.css";
const style = {
  color: "red",
  fontSize: "30px",
};
let astive = true;
function App() {
  return (
    <div className="App">
      <span style={style}>span</span>
      <span className={astive ? "active" : ""}>span</span>
    </div>
  );
}

export default App;
6-事件绑定

需要添加事件的元素标签内以"onClick={自定义事件}"的形式实现事件绑定

import React from "react";
// 函数组件的创建和渲染
// 创建
function Hello() {
  const clickHandler = () => {
    console.log("Hello点击事件");
  };
  return <div onClick={clickHandler}>Hello</div>;
}

// 类组件的创建和渲染
// 创建
class HelloComponent extends React.Component {
  // 事件回调函数(标准写法)
  clickHandler = () => {
    console.log("class Hello React.Component点击事件");
  };
  render() {
    return <div onClick={this.clickHandler}>class Hello React.Component</div>;
  }
}

function App() {
  return (
    <div className="App">
      {/* 渲染Hello组件 */}
      <Hello></Hello>
      <HelloComponent></HelloComponent>
    </div>
  );
}

export default App;
7-事件传递参数

与vue相同在函数添加形参,调用函数时传入实参,事件e可打印事件对象

import React from "react";
// 函数组件的创建和渲染
// 创建
function Hello() {
  const clickHandler = (e, msg) => {
    console.log("Hello点击事件", msg, e);
  };
  return <div onClick={(e) => clickHandler(e, "Hello")}>Hello</div>;
}

// 类组件的创建和渲染
// 创建
class HelloComponent extends React.Component {
  // 事件回调函数(标准写法)
  clickHandler = (e, msg) => {
    console.log("class Hello React.Component点击事件", e, msg);
  };
  render() {
    return (
      <div onClick={(e) => this.clickHandler(e, "666")}>
        class Hello React.Component
      </div>
    );
  }
}

function App() {
  return (
    <div className="App">
      {/* 渲染Hello组件 */}
      <Hello></Hello>
      <HelloComponent></HelloComponent>
    </div>
  );
}

export default App;

8-状态定义修改

react中的状态类似与vue2中的静态数据,vue2中数据放在data函数中return出来

react中的状态需要方在state={}对象内,修改时需要用固定的方法setState方法修改状态值

// 组件状态 类组件作为演示
import React from "react";
class TestComponent extends React.Component {
  // 1.定义组件状态
  state = {
    // 定义各种属性,全都是当前组件状态
    name: "组件状态",
  };
  // 事件回调
  changeName = () => {
    // 3.修改state中的状态name
    // 注:不可以直接做赋值修改 必须通过一个方法
    this.setState({
      name: "2222",
    });
  };
  render() {
    // 2.使用状态
    return (
      <>
        <div>666 当前name为:{this.state.name}</div>
        <button onClick={this.changeName}>修改</button>
      </>
    );
  }
}

function App() {
  return (
    <div className="App">
      <TestComponent></TestComponent>
    </div>
  );
}

export default App;

9-this指向问题bind修正写法

react中的事件函数一般写为箭头函数,若写为普通函数时在事件调用时打印this就为undefined

遇到这种情况需要使用bind方法修正this指向问题

此种写法在实际项目中一般不使用

// this 有问题写法
import React from "react";
// this有问题的写法
class Test extends React.Component {
  constructor() {
    super();
    // 使用bind强行修正我们的this指向
    this.handler = this.handler.bind(this);
  }
  handler() {
    console.log(this);
  }
  render() {
    return <button onClick={this.handler}>点击</button>;
  }
}

// 根组件
function App() {
  return (
    <div className="App">
      <Test></Test>
    </div>
  );
}

export default App;
10-this指向问题的另一种修改

与上述this问题相同,此修正方式是将事件调用中的函数写法改为箭头函数方式

// this问题
import React from "react";
// this有问题的写法
class Test extends React.Component {
  handler() {
    console.log(this);
  }
  render() {
    // reander 函数中的this已经被react内部做了修正
    // 这里的this就是指向当前的组件实例对象
    // 那我们箭头函数中的this 直接沿用  所以也是指向组件的实例对象
    console.log("父函数中的this指向为:", this);
    return (
      // 如果不通过construcor做修正 直接可以在事件绑定的位置
      // 通过箭头函数的写法  直接沿用父函数中的this指向也可以
      <button onClick={() => this.handler()}>点击</button>
    );
  }
}

// 根组件
function App() {
  return (
    <div className="App">
      <Test></Test>
    </div>
  );
}

export default App;
11-react的状态不可变

修改state中的对象时需采用下面的方式

// react的状态不可变
import React from "react";

class Counter extends React.Component {
  // 定义组件状态
  state = {
    count: 0,
    list: [1, 2, 3],
    person: {
      name: "jack",
      age: 18,
    },
  };
  // react不能直接修改状态 setState
  // 数组修改
  arrayHandler = () => {
    // this.setState({
    //   list: [...this.state.list, 4, 5],
    // });
    // 删除数组 -filter
    this.setState({
      list: this.state.list.filter((item) => item !== 2),
    });
  };
  // 对象修改
  objectHandler = () => {
    this.setState({
      person: {
        ...this.state.person,
        name: "tome",
      },
    });
  };

  render() {
    return (
      <>
        <ul>
          {this.state.list.map((item) => {
            return <li key={item}>{item}</li>;
          })}
        </ul>
        <button onClick={this.arrayHandler}>数组修改</button>
        <div>{this.state.person.name}</div>
        <button onClick={this.objectHandler}>对象修改</button>
      </>
    );
  }
}

// 根组件
function App() {
  return (
    <div className="App">
      <Counter></Counter>
    </div>
  );
}

export default App;
12-表单组件-受控组件(推荐)

react表单处理中分为受控组件与非受控组件

例如input框中,受控表示iuput框的状态被react组件状态控制(可以理解为state中的状态)

使用步骤
  1. 在组件的state中声明一个组件的状态数据
  2. 将状态数据设置为input标签元素的value属性的值
  3. 为input添加change事件,在事件处理程序中,通过事件对象e获取到当前文本框的值(即用户当前输入的值
  4. 调用setState方法,将文本框的值作为state状态的最新值

类似于vue中的双向绑定(v-model)

// 表单处理
// 2.非受控组件
import React from "react";

class Input extends React.Component {
  state = {
    message: "this is message",
  };
  inputChange = (e) => {
    console.log("change", e);

    this.setState({
      message: e.target.value,
    });
  };

  // 产出ui模板结构
  render() {
    return (
      <>
        <input
          type="text"
          onChange={this.inputChange}
          value={this.state.message}
        />
      </>
    );
  }
}

// 根组件
function App() {
  return (
    <div className="App">
      <Input></Input>
    </div>
  );
}

export default App;

13-表单组件-非受控组件

非受控组件就是通过手动操作dom的方式获取文本框的值,文本框的状态不受react组件的state中的状态控制,直接通过原生dom获取输入框的值

使用步骤
  1. 导入createRef 函数
  2. 调用createRef函数,创建一个ref对象,存储到名为msgRef的实例属性中
  3. 为input添加ref属性,值为msgRef
  4. 在按钮的事件处理程序中,通过msgRef.current即可拿到input对应的dom元素,而其中msgRef.current.value拿到的就是文本框的值
// 表单处理
// 2.非受控组件
import React, { createRef } from "react";

class Input extends React.Component {
  // 这个实例属性是可以自定义的 语义化
  msgRef = createRef();
  getValue = () => {
    // 通过msgRef获取input value值
    console.log(this.msgRef.current.value);
  };
  // 产出ui模板结构
  render() {
    return (
      <>
        <input type="text" ref={this.msgRef} />
        <button onClick={this.getValue}>点击获取输入框的值</button>
      </>
    );
  }
}

// 根组件
function App() {
  return (
    <div className="App">
      <Input></Input>
    </div>
  );
}

export default App;

14-组件通信

组件是独立且封闭的单元,默认情况下组件只能使用自己的数据(state)

组件化开发的过程中,完整的功能会拆分多个组件,在这个过程中不可避免的需要互相传递一些数据

为了能让各组件之间可以进行互相沟通,数据传递,这个过程就是组件通信

  1. 父子关系 - 最重要的
  2. 兄弟关系 - 自定义事件模式产生技术方法 eventBus / 通过共同的父组件通信
  3. 其它关系 - mobx / redux / zustand
父传子
实现步骤
  1. 父组件提供要传递的数据 - state

  2. 给子组件标签添加属性值为 state中的数据

  3. 子组件中通过 props 接收父组件中传过来的数据

    1. 类组件使用this.props获取props对象
    2. 函数式组件直接通过参数获取props对象
  4. props说明
  5. 1. props是只读对象(readonly)

  6. 根据单项数据流的要求,子组件只能读取props中的数据,不能进行修改

  7. 2. props可以传递任意数据

  8. 数字、字符串、布尔值、数组、对象、函数、JSX

// 组件通信
// 父传子
// 父组件
import React from "react";

// 函数式的son
// function SonF(props) {
function SonF({ msg, list, userIfor, getMsg, child }) {
  // props是一个对象 里面存着通过父组件传入的所有数据
  // 可以解构赋值
  // const { msg, list, userIfor, getMsg, child } = props;
  return (
    <>
      <div>函数子组件,{msg}</div>
      <div>
        函数子组件数组,
        {list.map((item) => (
          <p key={item}>{item}</p>
        ))}
      </div>
      <div>{userIfor.name}</div>
      <button onClick={getMsg}>触发父组件传入的函数</button>
      <div>{child}</div>
    </>
  );
  // props也是一个普通的js对象,所以原生支持的写法  这里都是可以的
}

// 类组件的Son
class SonC extends React.Component {
  // 产出ui模板结构
  render() {
    return (
      // 类组件必须通过this关键词 去获取props
      <>
        <div>类子组件,{this.props.msg}</div>
      </>
    );
  }
}

class App extends React.Component {
  // 准备数据
  state = {
    message: "message",
    list: [1, 2, 3],
    userIfor: {
      name: "name",
      age: 12,
    },
  };
  // 传递函数
  getMsg = (i) => {
    console.log("父组件函数", i);
  };

  render() {
    return (
      <div>
        {/* 子组件身上绑定属性 属性名可以自定义 */}
        <SonF
          userIfor={this.state.userIfor}
          list={this.state.list}
          msg={this.state.message}
          getMsg={() => this.getMsg(1)}
          child={<button>this is child</button>}
        ></SonF>
        <SonC msg={this.state.message}></SonC>
      </div>
    );
  }
}

export default App;

子传父

父组件给子组件传递回调函数,子组件调用

实现步骤
  1. 父组件提供一个回调函数 - 用于接收数据
  2. 将函数作为属性的值,传给子组件
  3. 子组件通过props调用 回调函数
  4. 将子组件中的数据作为参数传递给回调函数
// 组件通信
// 子传父
import React from "react";

// 函数式的son
// function SonF(props) {
//   const { getSonMsg } = props;
//   return (
//     <>
//       <div>函数子组件</div>
//       <button
//         onClick={() => {
//           getSonMsg("子组件数据");
//         }}
//       >
//         子传父
//       </button>
//     </>
//   );
// }

// 另一种写法
function SonF(props) {
  const { getSonMsg } = props;
  function sonClick() {
    getSonMsg("子组件数据");
  }
  return (
    <>
      <div>函数子组件</div>
      <button onClick={sonClick}>子传父</button>
    </>
  );
}
class App extends React.Component {
  // 准备数据
  state = {
    list: [1, 2, 3],
  };
  // 准备一个函数 传给子组件
  getSonMsg = (i) => {
    console.log(i);
  };

  render() {
    return (
      <div>
        {/* 子组件身上绑定属性 属性名可以自定义 */}
        <SonF getSonMsg={this.getSonMsg}></SonF>
      </div>
    );
  }
}

export default App;

兄弟传值

在这里插入图片描述

通过状态提升机制,利用共同的父组件实现兄弟通信

// 组件通信
// 兄弟传值
// 实现方式
// 1.先将B中的数据通过子传父 传给App
// 2.再把App接收到的Son中的数据 通过父传子 传给A
import React from "react";

// sonA
function SonA(props) {
  return (
    <>
      <div>函数子组件A{props.sendAMsg}</div>
    </>
  );
}
// sonB
function SonB(props) {
  const bMsg = "这里来自于b组件中的数据";
  return (
    <>
      <div>
        函数子组件B
        <button onClick={() => props.getBMsg(bMsg)}>B子组件</button>
      </div>
    </>
  );
}

class App extends React.Component {
  state = {
    sendAMsg: "测试一下父传子",
  };
  // 声明一个传给B组件的方法
  getBMsg = (msg) => {
    console.log(msg);
    // 把msg交给子组件A
    this.setState({
      sendAMsg: msg,
    });
  };

  render() {
    return (
      <div>
        {/* 子组件身上绑定属性 属性名可以自定义 */}
        <SonA sendAMsg={this.state.sendAMsg}></SonA>
        <SonB getBMsg={this.getBMsg}></SonB>
      </div>
    );
  }
}

export default App;

跨组件传值
实现步骤

1- 创建Context对象 导出 Provider 和 Consumer对象

2- 使用Provider包裹上层组件提供数据

3- 需要用到数据的组件使用Consumer包裹获取数据

import React, { createContext } from "react";
// 组件通信
// 跨组件传值
// app ->A->c
// app数据 ->c

// 注:
// 1.上层组件和下层组件关系是相对的只要存在就可以使用 通常我们都会通过app作为数据提供方
// 2.这里涉及到的语法都是固定的
// 1.导入createContext方法并执行,结构提供者和消费者
const { Provider, Consumer } = createContext();

function ComA(props) {
  return (
    <>
      <div>ComA</div>
      <ComC></ComC>
    </>
  );
}

// function ComC(props) {
//   return (
//     <>
//       <div>
//         ComC
//         {/* 3.通过Consumer使用数据 */}
//         <Consumer>{(value) => <span> {value} </span>}</Consumer>
//       </div>
//     </>
//   );
// }

// 另一种方式
function ComC(props) {
  return (
    <>
      <Consumer>
        {(value) => (
          <div>
            ComC
            {/* 3.通过Consumer使用数据 */}
            <span> {value} </span>
          </div>
        )}
      </Consumer>
    </>
  );
}

class App extends React.Component {
  state = {
    msg: "msg",
  };
  render() {
    return (
      //2. 使用provider包裹根组件
      <>
        <Provider value={this.state.msg}>
          <div>
            {/* 子组件身上绑定属性 属性名可以自定义 */}
            <ComA></ComA>
          </div>
        </Provider>
      </>
    );
  }
}

export default App;

15-children属性

表示该组件的子节点,只要组件内部有子节点,props中就有该属性

children类型 普通文本、普通标签元素、函数/对象、jsx

/* eslint-disable array-callback-return */
import React from "react";

function ListItem({ children }) {
  // children();
  return (
    <>
      <div>
        ListItem
        {/* <span>{children}</span> */}
        {children}
      </div>
    </>
  );
}

class App extends React.Component {
  render() {
    return (
      <>
        <ListItem>
          {/* <div>哈哈哈哈</div>
          123 */}
          {/* {() => console.log(123)} */}
          {
            <div>
              <p>{"this is p"}</p>
            </div>
          }
        </ListItem>
      </>
    );
  }
}

export default App;

16-props类型校验基础使用

实现步骤

  1. 安装属性校验包:yarn add prop-types
  2. 导入prop-types
  3. 使用 组件名.propTypes = {} 给组件添加校验规则
/* eslint-disable array-callback-return */
import React from "react";
import PropTypes from "prop-types";

function ListItem({ list }) {
  return (
    <>
      <div>
        {list.map((item) => (
          <p key={item}>{item}</p>
        ))}
      </div>
    </>
  );
}
// eslint-disable-next-line react/no-typos
ListItem.propTypes = {
  // 定义各种规则
  list: PropTypes.array,
};

class App extends React.Component {
  render() {
    return (
      <>
        <ListItem list={[1, 2]}></ListItem>
      </>
    );
  }
}

export default App;
17-props默认值

两种方式

​ 函数式组件可在外部写好默认值,也可以在props中直接定义

​ 类组件需要在组件内通过 static defaultProps={} 定义默认值

import React from "react";
import PropTypes from "prop-types";

// function ListItem(props) {
//   return (
//     <>
//       <div>
//         ListItem
//         {props.pageSize}
//       </div>
//     </>
//   );
// }

// 第二种方式
// function ListItem({ pageSize = 10 }) {
//   return (
//     <>
//       <div>
//         ListItem
//         {pageSize}
//       </div>
//     </>
//   );
// }

// 类组件写法
class ListItem extends React.Component {
  static defaultProps = {
    pageSize: 10,
  };
  render() {
    return (
      <>
        <ListItem list={[1, 2]} pageSize={20}></ListItem>
      </>
    );
  }
}

ListItem.propTypes = {
  // 定义各种规则
  list: PropTypes.array.isRequired,
};
// 设置默认值
ListItem.defaultProps = {
  pageSize: 10,
};

class App extends React.Component {
  render() {
    return (
      <>
        <ListItem
          list={[1, 2]}
          // pageSize={20}
        ></ListItem>
      </>
    );
  }
}

export default App;
18-生命周期

life.png

life1.png

钩子 函数触发时机作用
constructor创建组件时,最先执行,初始化的时候只执行一次1. 初始化state 2. 创建 Ref 3. 使用 bind 解决 this 指向问题等
render每次组件渲染都会触发渲染UI(注意: 不能在里面调用setState()
componentDidMount组件挂载(完成DOM渲染)后执行,初始化的时候执行一次1. 发送网络请求 2.DOM操作
componentWillUnmount组件卸载(从页面中消失)执行清理工作(比如:清理定时器等)
19-hooks
hooks的本质:一套能够使函数更强大、更灵活的'钩子'

​ hooks是为了让函数有自己的状态

​ useState 每次定义都包含一个数据和修改数据的方法

// useState
// 1.导入useState函数 react
// 2.执行这个函数并且传入初始值
// 3.数据,修改数据的方法
// 4.使用数据 修改数据

import { useState } from "react";

function App() {
 const [count, setCount] = useState(0);
 return (
   <>
     <div>
       <button onClick={() => setCount(count + 1)}>{count}</button>
     </div>
   </>
 );
}

export default App;
状态读取修改

1、useSrate传过来的参数 作为count的初始值

2、[count,setCount] 这里的写法是一个解构赋值 useState返回值是一个数组

名字可以自定义 顺序不可以更换

3、setcount函数 作用用来修改count依旧保持不能直接修改原值还是生成一个新值替换原值

4、count, setCount 是一对 setCount只能用来修改对应的count值

hooks的副作用

​ useEffect函数

​ 副作用是相对于主作用来说的,一个函数除了主作用,其他的作用就是副作用。对于 React 组件来说,主作用就是根据数据(state/props)渲染 UI,除此之外都是副作用(比如,手动修改 DOM)

常见的副作用
  1. 数据请求 ajax发送
  2. 手动修改dom
  3. localstorage操作

​ useEffect函数的作用就是为react函数组件提供副作用处理的!

基础使用

import { useEffect, useState } from 'react'

function App() {
  const [count, setCount] = useState(0)
 
  useEffect(()=>{
    // dom操作
    document.title = `当前已点击了${count}次`
  })
  return (
    <button onClick={() => { setCount(count + 1) }}>{count}</button>
  )
}

export default App
依赖项控制执行时机
1- 不添加依赖项

组件首次渲染执行一次,以及不管是哪个状态更改引起组件更新时都会重新执行

  1. 组件初始渲染
  2. 组件更新 (不管是哪个状态引起的更新)
useEffect(()=>{
    console.log('副作用执行了')
})
2- 添加空数组

​ 组件只在首次渲染时执行一次

useEffect(()=>{
	 console.log('副作用执行了')
},[])
3- 添加特定依赖项

副作用函数在首次渲染时执行,在依赖项发生变化时重新执行

function App() {  
    const [count, setCount] = useState(0)  
    const [name, setName] = useState('zs') 
    
    useEffect(() => {    
        console.log('副作用执行了')  
    }, [count])  
    
    return (    
        <>      
         <button onClick={() => { setCount(count + 1) }}>{count}</button>      
         <button onClick={() => { setName('cp') }}>{name}</button>    
        </>  
    )
}
4- 清理副作用

​ 如果想要清理副作用 可以在副作用函数中的末尾return一个新的函数,在新的函数中编写清理副作用的逻辑

注意执行时机为:

  1. 组件卸载时自动执行
  2. 组件更新时,下一个useEffect副作用函数执行之前自动执行
useEffect - 发送网络请求
语法要求

​ 不可以直接在useEffect的回调函数外层直接包裹 await ,因为异步会导致清理函数无法立即返回

错误写法
useEffect(async ()=>{    
    const res = await axios.get('http://geek.itheima.net/v1_0/channels')   
    console.log(res)
},[])
正确写法

​ 在内部单独定义一个函数,然后把这个函数包装成同步

useEffect(()=>{   
    async function fetchData(){      
       const res = await axios.get('http://geek.itheima.net/v1_0/channels')
        console.log(res) 
    } 
},[])
20-useRef

在函数组件中获取真实的dom元素对象或者是组件对象

使用步骤

  1. 导入 useRef 函数
  2. 执行 useRef 函数并传入null,返回值为一个对象 内部有一个current属性存放拿到的dom对象(组件实例)
  3. 通过ref 绑定 要获取的元素或者组件
import React, { useEffect, useRef } from "react";

// 组件实例
// dom对象

class TestC extends React.Component {
  state = {
    name: "nihao",
  };
  getName = () => {
    return "this is child test";
  };
  render() {
    return (
      <>
        <div>我是类组件</div>;
      </>
    );
  }
}

function App() {
  const testRef = useRef(null);
  const h1Ref = useRef(null);

  useEffect(() => {
    console.log(testRef.current);
    console.log(h1Ref.current);
    // useEffect 在dom渲染之后执行
  }, []);
  return (
    <>
      <div>
        <TestC ref={testRef}></TestC>
        <h1 ref={h1Ref}>this is h1</h1>
      </div>
    </>
  );
}

export default App;

35-useContext使用

​ useContext类似于vue3中的 previde inject 数据的提供与注入

实现步骤

  1. 使用createContext 创建Context对象
  2. 在顶层组件通过Provider 提供数据 需要用<Context.Provider></Context.Provider>标签包裹被提供数据的组件
  3. 在底层组件通过useContext函数获取数据
import React, { createContext, useContext, useState } from "react";

const Context = createContext();

function ComA() {
  const count = useContext(Context);
  return (
    <>
      <div>
        this is ComA
        <br />
        app传过来的数据为:{count}
        <ComC></ComC>
      </div>
    </>
  );
}

function ComC() {
  const count = useContext(Context);
  return (
    <>
      <div>
        this is ComC
        <br />
        app传过来的数据为:{count}
      </div>
    </>
  );
}

function App() {
  const [count, setCount] = useState(20);
  return (
    <>
      <Context.Provider value={count}>
        <div>
          <ComA></ComA>
          <button
            onClick={() => {
              setCount(count + 1);
            }}
          >
            add+
          </button>
        </div>
      </Context.Provider>
    </>
  );
}

export default App;

mobx

mobx与react的和关系相当于vue和vueX (同类工具还有 redux、dva、recoil)

计数器案例

// 安装
npm i mobx mobx-react-lite

store 模块化

// src/store/counter.Store.js

// 编写mobox store 小案例
import { makeAutoObservable } from "mobx";

class CounterStore {
  // 1、定义数据状态
  count = 0;
  // 1--定义一个原始数据 list
  list = [1, 2, 3, 4, 5, 6];
  constructor() {
    // 2、数据响应式处理
    makeAutoObservable(this);
  }
  // 2---定义计算属性 computed
  get filterList() {
    return this.list.filter((item) => item > 2);
  }
  // 3---方法修改list
  addList = () => {
    this.list.push(7, 8, 9);
  };
  // 3、定义action函数(修改数据)
  addCount = () => {
    this.count++;
  };
}

// 4、实例化并导出实例
// const couterStore = new CounterStore();
export { CounterStore };

store index

// 组合子模块
// 封装统一导出的供业务使用的方法
import { ListStore } from "./list.Store";
import React from "react";

// 1.声明一个rootStore
class RootStore {
  constructor() {
    // 对子模块进行实例化操作
    // 实例化根store的时候
    // 根store有两个属性 分别是counterStore和listStore
    // 各自对应的值  就是我们导入的子模块实例对象
    this.couterStore = new CounterStore();
  }
}
// 实例化操作
const rootStore = new RootStore();
// 使用react conntext机制  完成统一方法封装
// Provider value={传递的数据}
// 查找机制:useContext 优先从Provider value找 如果找不到 就会找createContext方法传递过来的默认参数
const context = React.createContext(rootStore);
const useStore = () => React.useContext(context);

export { useStore };

连接react

//  src/App.js

// 1、导入countStore
import { useStore } from "./store/index";
// 2、导入中间件连接mobox react 完成响应式变化
import { observer } from "mobx-react-lite";
function App() {
  const rootStore = useStore();
  // console.log(rootStore);
  return (
    <div className="App">
      App
      {/* 把store中的count渲染一下 */}
      {rootStore.couterStore.count}
      {/* 点击事件触发action函数修改count值 */}
      <button onClick={rootStore.couterStore.addCount}>++</button>
      <br />
      {rootStore.couterStore.filterList}
      <button onClick={rootStore.couterStore.addList}>修改数组</button>
      {/*  */}
    </div>
  );
}

// 3.包裹组件让视图响应数据变化
export default observer(App);
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值