Appearance
学习React
请确保以下内容已经熟悉
- Javascript语法
- ES6及以后的js语法新特性
React的特点
- React专注于视图层,所有的一切都是围绕着视图层展开。
- 声明式编程
初学者对于这两点可以先略过,等到做过三四个项目之后会渐渐理解
使用React
- 在HTML里引入
html
<script src="js/react.js"></script>
<script src="js/react-dom.js"></script>
dom文件依赖于react.js文件,所以引入顺序上一定不要颠倒。至于src的路径,可以根据实际情况进行修改。 在正式项目里,其实更多的是使用creat-react-app来自动化创建项目。此方法在后面介绍。
render
javascript
ReactDOM.render[element,container[,callback]]
说render是react的核心api也不为过,通过该api,react才能将虚拟DOM转为真实DOM。
参数 | 说明 |
---|---|
element | React生成的虚拟DOM,也可叫做ReactElement,或ReactNode。可用字符串实现 |
container | 放置在element容器中,必须是一个已经存在的真实DOM节点 |
callback | 将ReactNode渲染到container之后的回调函数 |
javascript
// 注意这里有个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);
javascript
<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,浏览器才能够识别。
javascript
<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。
javascript
npm i create-react-app -g
安装好之后输入下面这行,回车,能看到版本号就说明安装成功
javascript
npm i create-react-app -V
创建好的目录结构如下所示:
javascript
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
- 修改模板
后续修改模板会有点麻烦,建议创建项目的时候就把模板选好。
选择模板安装的命令为:
javascript
npx create-react-app my-app --template typescript
其中,my-app是项目名,typescript是模板的类。这句话的意思是:用typescript模板创建一个名为my-app的react项目。
- 修改端口
如果想要修改端口,则需要到
\node_modules\react-scripts\scripts\start.js
文件里修改
javascript
// 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的方式。
tsx
// 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>
);
}
ts
// store.ts中
import rootReducer from '@/reducers';
import { createStore } from 'redux';
const store = createStore(rootReducer);
export default store;
ts
// reducer.ts中
const rootReducer = (state = 0, action) => {
switch (action.type) {
case 'addNum':
console.log('addNum')
break;
default:
return state;
}
};
export default rootReducer;
使用connect
tsx
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
ts
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
// ...
};