react学习

create-react-app 脚手架快速搭建 react 项目

1、安装 create-react-app
npm install -g create-react-app       // Windows
sudo npm install -g create-react-app  // Linux
2、检测 create-react-app 是否安装成功
create-react-app -V // 注意:V 是大写的 
3、创建 react 项目

npx create-react-app <项目名称>// 注意:名字不能包含大写字母。我的是 my-app。
cd my-app
npm start

项目结构介绍

app.js => app.vue

index.js => main.js

样式和组件是分开的,有专门的css文件

react组件分类

函数组件(相当于vue3组合式api)

组件名不大写就会认为是一个方法

function App(){
    // 函数组件的组件名 首字母定要大写
    function FnHello(){
        return(<div>hello</div>)
    }
    return (
        <FnHello></FnHello>
    )
}

class组件

class App extends React.Component {
  render() {
    return <div>123</div>;
  }
}
export default App;

react不一定要写jsx,也可以直接通过react.createElement来创建dom元素,可以在js文件下写jsx,也可以直接把文件名改成jsx,最终页面上现实的是react-element对象

jsx中渲染不同内容

类组件响应式数据的定义

1.响应式数据定义在state属性中

2.修改值需要通过setState,setstate是通过钱合并来修改数据,调用setstate会触发更新,修改state不会触发更新

3.因为setstate是异步的,我们要获取修改后的值要在setstate的第二个参数中获取

特性:

1.多次修改会合并为一次,统一更新

2.setstate返回会触发更新,重复修改同样的值也会更新

3.一定不要在render中设置setstate,PureComponent

方法一般是写成箭头函数,或者通过调用时用bind制定this

修改数组或对象时要先解除引用,通过展开运算符等方式

react表单绑定

原生表单获取输入值,可以监听input或者是change事件,获取e.target.value

要设置表单的值,通常设置value属性,选择框是checked属性

class App extends React.Component {
  state = {
    inputValue: "",
    checkedValue: ["c1"],
  };
  handleCheckBox = (e) => {
    let arr = [...this.state.checkedValue];
    if (e.target.checked) {
      arr.push(e.target.value);
    } else {
      arr.splice(arr.indexOf(e.target.value), 1);
    }
    this.setState({
      checkedValue: arr,
    });
  };
  render() {
    return (
      <div>
        {this.state.inputValue}
        <input
          value={this.state.inputValue}
          onInput={(e) => {
            this.setState({
              inputValue: e.target.value,
            });
          }}
        />
        <br></br>
        {this.state.checkedValue}
        <input
          type="checkbox"
          value="c1"
          checked={this.state.checkedValue.includes("c1")}
          onChange={this.handleCheckBox}
        />
        选项一
        <input
          type="checkbox"
          value="c2"
          checked={this.state.checkedValue.includes("c2")}
          onChange={this.handleCheckBox}
        />
        选项二
        <input
          type="checkbox"
          value="c3"
          checked={this.state.checkedValue.includes("c3")}
          onChange={this.handleCheckBox}
        />
        选项三
      </div>
    );
  }
}

props和组件间传值,插槽

一切写在组件上的属性和子节点都属于props,父子传值,插槽都是基于props

props的类型验证和静态值

插槽的本质

在jsx的加持下,可以吧html像普通字符串一样传递,插槽只要直接作为props传入就可以了

class App extends React.Component {
  state = {
    msg: 123,
  };
  render() {
    return (
      <div>
        <Son a="123" b={<div>我是b插槽</div>}>
          <div>哈哈哈</div>
          <span className="spancolor">123</span>
        </Son>
      </div>
    );
  }
}

class Son extends React.PureComponent {
  state = {};
  render() {
    console.log(this.props);
    return (
      <div>
        // 类似具名插槽
        {this.props.b}
        123{this.props.msg}
        // 这也是插槽
        {this.props.children}
      </div>
    );
  }
}

子传父

兄弟传值

子1 =》 父 =》 子2

类型验证借助proptypes库

npm install proptypes

 示例

class App extends React.Component {
  state = {
    msg: "",
  };
  changeMsg = (msg) => {
    this.setState({
      msg: msg,
    });
  };
  render() {
    return (
      <div>
        msg: {this.state.msg}
        <br></br>
        <Son
          a="123"
          scopeSlot={(scope) => {
            return <strong>{scope}</strong>;
          }}
          b={<div>我是b插槽</div>}
          changeMsg={this.changeMsg}
        >
          <div>哈哈哈</div>
          <span className="spancolor">123</span>
        </Son>
      </div>
    );
  }
}
export default App;



class Son extends React.PureComponent {
  state = {};
  render() {
    console.log(this.props);
    return (
      <div>
        {this.props.b}
        123{this.props.msg}
        {this.props.children}
        {this.props.scopeSlot("我是子组件传过来的值")}
        <br></br>
        子传父
        <button
          onClick={() => {
            this.props.changeMsg("hello father");
          }}
        >
          子传父传值
        </button>
      </div>
    );
  }
}
Son.propTypes = {
  msg: proptypes.string,
};
Son.defaultProps = {
  msg: "i am son msg",
};

样式操作

这样引入样式是全局生效的,文件名要改成 App.module.css 才是只在对应组件内生效

// 全局生效
import "./App.css";

下载classnames库可以实现动态绑定类名

 npm i classnames
import classNames from "classnames";

// 相当于app.vue
class App extends React.Component {
  state = {
    hasson1: false,
  };
  render() {
    return (
      <div>
        <span
          className={classNames({
            spancolor: true,
            spanstyle: this.state.hasson1,
          })}
          style={{ fontSize: "30px" }}
        >
          hello
        </span>
        <button
          onClick={() => {
            this.setState({
              hasson1: !this.state.hasson1,
            });
          }}
        >
          修改classname
        </button>
        <Son></Son>
      </div>
    );
  }
}

如果要配合模块化,要引入classnames/bind文件

import sonStyle from "./Son.module.css";

// 如果要配合模块化,要引入classnames/bind文件
import classNames from "classnames/bind";
let bindClassName = classNames.bind(sonStyle);
console.log("sss", sonStyle);
class Son extends React.PureComponent {
  state = {};
  render() {
    return (
      <div>
        <span
          className={bindClassName({
            son: true,
            son1: true,
          })}
        >
          我是儿子
        </span>
      </div>
    );
  }
}



生命周期

函数组件和hook

下面例举的是常用的hook,也可以hook自定义

hook只能用于函数组件,用在其他地方会报错

函数组件

1.没有生命周期函数

2.没有this

3.

useState

生命响应式变量

useEffect

模拟生命周期,或者是监听属性

useMemo

类似计算属性,让一个属性不再被重复创建

useCallback

让一个方法不再被重复创建,用于性能优化

useContext 

相当于provirde/inject

export let Context1 = React.createContext();
import Son from "./Son";

function App() {
  // return 的内容相当于组件的html
  return (
    <div>
      <Context1.Provider value="i am a context value">
        <Son fatherMsg="i am father"></Son>
      </Context1.Provider>
    </div>
  );
}




// son.js
import { useContext } from "react";
import { Context1 } from "./App";

function Son() {
  let value = useContext(Context1);
  return <div>{value}</div>;
}
export default Son;

高阶组件Hoc

单纯的逻辑复用,相当于mixin和自定义指令

使用:使用高阶组件实现PureComponent作用(父组件更新数据,与子组件无关的数据,子组件不更新)

react性能优化

1.父组件数据更新导致子组件更新

vue可以进行依赖收集,做到了最小范围的更新;react要优化是时间切片,先计算一部分更新,然后让渡给渲染进程,在进行下一部分的更新,这样就不会导致页面长时间白屏了

fiber(数据结构):为了能支持时间切片,每一个组件会被转化为一个fiber结构的对象,组成一个个单元,fiber让我们有回去上一次中断计算进度的能力

(1)避免state相同的值产生更新:

类组件可以使用purecomponent;函数组件本身就会判断

(2)props更新导致

类组件可以使用purecomponent;

函数组件React.memo包裹子组件,使用useCallback包裹方法,useMemo包裹对象作为props传递



React-router 

react-router 服务端渲染

react-route-dom 浏览器渲染

react-router-native react-native 混合开发使用

其他路由组件:

navigate  路由重定向

outlet  嵌套路由的子路由显示处

获取路由参数

location通常用来获取当前路径

import { useParams, useSearchParams, useLocation } from "react-router-dom";

function Page1() {
  let [searchParams, setSearchParams] = useSearchParams();
  // console.log(searchParams.get("b"));
  let params = useParams();
  // console.log(params);
  let location = useLocation();
  // console.log(location);

  return (
    <div>
      hello i am page1
      <button
        onClick={() => {
          setSearchParams({
            b: 666,
            a: 888,
          });
        }}
      >
        修改query参数的值
      </button>
    </div>
  );
}
export default Page1;

js控制跳转地址

v6- useNavigate创建跳转方法

v5- this.props.history.push()

let nav = useNavigate();

  return (
    <div>
      <button
        onClick={() => {
          nav("/page2", {
            state: {
              state1: "123",
            },
          });
        }}
      >
        跳转到page2
      </button>

权限控制

通过navigate,直接不生成

异步路由

let lazyPage2 = lazy(() => {
  return import("./Page2");
});
function App() {
  return (
    <div>
      <Link to="/page1">page1</Link>
      <Suspense fallback={<h2>加载中</h2>}>
        <Routes>
          <Route path="/page1/:id" Component={Page1}></Route>
          <Route path="/page2" Component={lazyPage2}></Route>
        </Routes>
      </Suspense>
    </div>
  );
}

react状态管理

1.创建全局数据管理对象

2.通过某个组件连接到react

redux创建仓库

编写reducer方法 

let defaultState = {
  mes: "hello",
};
function mesReducer(state = defaultState, action) {
  // 具体修改数据的行为
  switch (action.type) {
    case "changeMes":
      state.mes = action.payload;
      // 字后一定要return state,并且接解除引用
      return { ...state };
    default:
      return state;
  }
}
export default mesReducer;

给state默认值作为初始数据

判断type修改数据

调用createStore创建仓库  

import {
  legacy_createStore as createStore,
  combineReducersbineReducers,
} from "redux";
import mesReducer from "./mesReducer";
import numReducer from "./numReducer";
let reducer = combineReducersbineReducers({
  mesReducer,
  numReducer,
});
let store = createStore(reducer);
export default store;

react-redux

通过provider组件,把store关联到目标项目

import { Provider } from "react-redux";
import store from "./store";

// 相当于main.js  把项目挂在到指定的dom
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  // react的严格模式 可去掉
  // <React.StrictMode>
  <BrowserRouter>
    <Provider store={store}>
      <App />
    </Provider>
  </BrowserRouter>

  // </React.StrictMode>
);

利用connet连接到某组件

编写映射关系

import { connect } from "react-redux";

function App(props) {
  console.log(props);
  return (
    <div>
      {props.mes}
      <button
        onClick={() => {
          props.changeMes();
          console.log(props);
        }}
      >
        修改msg
      </button>
    </div>
  );
}
// connet第一个参数state的映射,你要把那些state映射到该组件的props中
// connet第二个参数方法映射,你要给props加入什么方法
export default connect(
  (state) => {
    // 一定要return 一个对象
    return {
      // 分模块就是先取模块,再取值
      mes: state.mesReducer.mes,
    };
  },
  (dispatch) => {
    return {
      changeMes() {
        dispatch({
          type: "changeMes",
          payload: "888",
        });
      },
    };
  }
)(App);

现在常用的是@reduxjs/toolkit  

创建切片

整合切片,创建仓库

react-redux连接到react

npm install @reduxjs/toolkit

vue和react的区别

1.更新方式不同

vue可以进行依赖收集,做到了最小范围的更新;

react父组件更新会让子组件也更新,所以要优化做时间切片(先计算一部分更新,然后让渡给渲染进程,在进行下一部分的更新,这样就不会导致页面长时间白屏了)

2.全局插件使用方式不同

react中没有vue那样的vue.use方法,

react使用一个插件或者是库,都是引入一个组件,然后把要使用该插件的地方包起来

React学习路线图是一个指导学习React的图表,它提供了一条学习React所需的知识和技能的路径。这个路线图包括了React的基础知识和重要概念,以及一些额外的学习资源和库。你可以使用这个路线图作为学习React的指南,帮助你更好地了解React学习路径和学习顺序。如果你对React完全不了解,我建议你先阅读React的入门教程,例如React官方推荐的入门教程《React入门教程 – 概述和实际演练》和2018年学习React.js的综合指南。这些教程将介绍React的基本概念和实践,帮助你建立起对React的基本理解。之后,你可以根据React开发者线路图中的学习路径,逐步深入学习React的相关知识和技能。这个路线图将指导你学习React的核心部分和重要的知识点,以及一些额外的学习资源和库,帮助你更好地成为一名React开发人员。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [(转)2019年 React 新手学习指南 – 从 React 学习线路图说开去](https://blog.csdn.net/weixin_30544657/article/details/101470289)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值