初面网初面网

学习React

请确保以下内容已经熟悉

  • Javascript语法
  • ES6及以后的js语法新特性

React的特点

  • React专注于视图层,所有的一切都是围绕着视图层展开。
  • 声明式编程

初学者对于这两点可以先略过,等到做过三四个项目之后会渐渐理解

使用React

  • 在HTML里引入
<script src="js/react.js"></script>
<script src="js/react-dom.js"></script>

dom文件依赖于react.js文件,所以引入顺序上一定不要颠倒。至于src的路径,可以根据实际情况进行修改。 在正式项目里,其实更多的是使用creat-react-app来自动化创建项目。此方法在后面介绍。

render

ReactDOM.render[element,container[,callback]]

说render是react的核心api也不为过,通过该api,react才能将虚拟DOM转为真实DOM。

参数说明
elementReact生成的虚拟DOM,也可叫做ReactElement,或ReactNode。可用字符串实现
container放置在element容器中,必须是一个已经存在的真实DOM节点
callback将ReactNode渲染到container之后的回调函数
// 注意这里有个div
<div id="root"></div>

<script>
  ReactDOM.render(
    "Say Hello"
    document.querySelector("#root"),
    ()=>{
      console.log("渲染成功!!")
    }
  )
</script>

实际上,React的API有很多,如findDOMNode,createPortal等,但在实际项目中不建议使用,且没有需求使用

视图渲染

视图渲染有两种实现方式:

  • 方式一

格式: React.createElement(type,config,children);

<script>
  <div id="root"></div>
  
  // 子div
  let childDiv = React.createElement("div",null,"一个子div");
  
  // 父div
  let div = React.createElement("div", null,[childDiv]);
  
  // 渲染为真实DOM
  ReactDOM.render( div,document.querySelector("#root"));
  
  // 最终应该生成
  <div>
    <div>
      一个子div
    </div>
  </div>
</script>
  • 方法二

JSX,可以直接使用html的方法书写节点,并使用 { js代码 } 这样的方式写入js代码。这种方式叫做 插值表达式

但是浏览器是不识别JSX的。需要引入babel.js,浏览器才能够识别。

<div id="root"></div>
<script src="js/babel.js"></script>
<script type="text/babel">
  let inText = "内部TEXT";
  
  // 渲染为真实DOM
  ReactDOM.render( 
    <div>
      {inText}
    </div>
  ,document.querySelector("#root"));
  
  // 最终应该生成
  <div>
    内部TEXT
  </div>
</script>

更多的JSX用法将在后续的实例里演示

重头戏:create-react-app

直接在HTML文件里引入react并进行开发将会导致很多麻烦的问题,包括但不限于各种依赖包的引入,各种错误处理。为了能够方便开发,react官方提供了一个脚手架:create-react-app,用来帮助开发者快速搭建一个项目。

所谓的脚手架可以理解为只有框架的项目,这里所说的框架,根据封装程度可复杂,可简约,但归根到底,脚手架能让开发者快速搭建好一个干净的项目环境。

  • 安装

先安装node。node的安装很简单,请读者自行搜索解决。

安装好node环境,在命令行中使用下面这行命令进行全局安装。其中,i代表install, -g 代表全局安装--global。

npm i create-react-app -g

安装好之后输入下面这行,回车,能看到版本号就说明安装成功

npm i create-react-app -V

创建好的目录结构如下所示:

my-app
├── README.md               // 项目介绍文件,markdown格式
├── node_modules            // 存放项目依赖文件的文件夹
├── package.json            // 项目的配置文件
├── .gitignore
├── public            // 图片之类的项目资源放在这里
│   ├── favicon.ico
│   ├── index.html        // html模板
│   ├── logo192.png
│   ├── logo512.png
│   ├── manifest.json
│   └── robots.txt
└── src                // src,一般项目的所有功能都会写在这里
    ├── App.css
    ├── App.js            // 主组件
    ├── App.test.js
    ├── index.css
    ├── index.js          // 项目入口
    ├── logo.svg
    ├── serviceWorker.js
    └── setupTests.js
  • 修改模板

后续修改模板会有点麻烦,建议创建项目的时候就把模板选好。

选择模板安装的命令为:

npx create-react-app my-app --template typescript

其中,my-app是项目名,typescript是模板的类。这句话的意思是:用typescript模板创建一个名为my-app的react项目。

  • 修改端口

如果想要修改端口,则需要到

\node_modules\react-scripts\scripts\start.js

文件里修改

// Tools like Cloud9 rely on this.
const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3999; // 3999原本是3000
const HOST = process.env.HOST || '0.0.0.0';

Redux

React-redux

Provider组件使整个app都能获取到store中的数据

connect连接容器组件和store

其中,Provider包裹在根组件最外层,store作为props传入,通过context向下传递。

注意:下面的方法已不推荐。可以直接看下一小节中新的创建store的方式。

// app.tsx中
import { store } from '@/store';
import { Provider } from 'react-redux';
export const App = (props) => {

  return (
    <Provider store={store}>
      <StatusBar backgroundColor={statusBarBgColor} barStyle="light-content" />
      {props.children}
    </Provider>
  );
}
// store.ts中
import rootReducer from '@/reducers';
import { createStore } from 'redux';

const store = createStore(rootReducer);

export default store;
// reducer.ts中
const rootReducer = (state = 0, action) => {
  switch (action.type) {
    case 'addNum':
      console.log('addNum')
      break;
    default:
      return state;
  }
};

export default rootReducer;

使用connect

import { View } from "@tarojs/components";

import { connect } from 'react-redux';

const ZTest = (props) => {
  return ( <> </>)
}

// 绑定属性到组件prop
const mapStateToProps = (state: RootState) => {
  return {
    compoProp: userSelectors.selectMe(state),
  };
};

// 绑定动作到组件方法中
const mapDispatchToProps = (dispatch) => {
  return dispatch({
    type: "addNum",
  });
};

export default connect(mapStateToProps, mapDispatchToProps)(ZTest);

@reduxjs/toolkit

现在不推荐使用createStore了。需要使用@reduxjs/toolkit包中的configureStore。

npm i @reduxjs/toolkit

安装好后创建store

import { createSlice, configureStore } from '@reduxjs/toolkit';

// 定义一个Redux Slice
const calculateSlice = createSlice({
  name: 'calculate',
  initialState: [],
  reducers: {
    addNum: (state, action) => {
      // 处理添加的逻辑
    },
    minusNum: (state, action) => {
      // 处理减小的逻辑
    },
  },
});

// 获取Redux状态和Actions
export const { addNum, minusNum } = calculateSlice.actions;

// 创建Redux store
const store = configureStore({
  reducer: calculateSlice.reducer,
});

// 在React组件中使用Redux Toolkit
import { useSelector, useDispatch } from 'react-redux';
import { addNum, minusNum } from './todosSlice';

const TodoList = () => {
  const toCalc = useSelector(state => state); // 使用Selector获取Redux状态
  const dispatch = useDispatch(); // 使用useDispatch Hook获取dispatch函数

  // 在组件中使用Redux Toolkit的Actions
  const handleAddCalc = (num) => {
    dispatch(addNum(num)); // dispatch addTodo Action
  };

  const handleMinusCalc = (num) => {
    dispatch(minusNum(num)); // dispatch deleteTodo Action
  };

  // 在组件中使用todos数据和Redux Toolkit的Actions
  // ...
};

更新于 2025/2/26