React简要总结
起步
- 创建项目: npx create-react-app my-app
- 打开项目: cd my-app
- 启动项目: npm start
- 暴露配置项: npm run eject
├── README.md ⽂文档
├── public 静态资源
│ ├── favicon.ico
│ ├── index.html
│ └── manifest.json
└── src 源码
├── App.css
├── App.js 根组件
├── App.test.js
├── index.css 全局样式
├── index.js ⼊入⼝口⽂文件
├── logo.svg
└── serviceWorker.js pwa⽀支持
├── package.json npm 依赖
JSX简介
-
jsx理解为js和xml的杂交品种,注意他不是字符串
- JSX 中可以嵌入表达式
const name = 'Josh Perez'; const element = <h1>Hello, {name}</h1>;//嵌入表达式
- JSX也可以作为表达式
function getGreeting(user) { if (user) { return <h1>Hello, {formatName(user)}!</h1>; //作为表达式 } return <h1>Hello, Stranger.</h1>;//作为表达式 }
在浏览器环境处理JSX
借助Babel 会把 JSX 转译成一个名为
React.createElement()
*(也就是vue里的常说的h函数 )*函数调用。const element = ( <h1 className="greeting"> Hello, world! </h1> );
===
const element = React.createElement(//也就是vue里的常说的h函数 'h1', {className: 'greeting'}, 'Hello, world!' );
JSX 使用注意事项
- 必须有,且只有一个顶层的包含元素 - React.Fragment
- JSX 不是html,很多属性在编写时不一样
- className
- style
- 列表渲染时,必须有 key 值
- 在 jsx 所有标签必须闭合
- 组件的首字母一定大写,标签一定要小写
元素渲染
通过
ReactDOM.render(Vnode, container[, callback])
函数,可以将jsx转变为DOM元素- element:要渲染的内容
- container:要渲染的内容存放容器
- callback:渲染后的回调函数
const element = <h1>Hello, world</h1>; //jsx表达式 ReactDOM.render(element, document.getElementById('root'));//渲染成<h1>Hello, world</h1> DOM元素
组件
可复用的功能块,允许你将 UI 拆分为独立可复用的代码片段,并对每个片段进行独立构思
从概念上类似于 JavaScript 函数。它接受任意的入参(即 “props”),并返回用于描述页面展示内容的 React 元素。
类组件
- 必须继承 React.Component
- 必须有 render 方法
import React, { Component } from 'react';
export default class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
函数组件
- 函数的名称就是组件的名称
- 函数的返回值就是组件要渲染的内容
import React from 'react'
export default function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
组件间通信
和vue类似,父传子通过props,子传父通过事件派发
<Child
name={name}
editName = {this.editName}
/>
//子组件的jsx
<p>姓名: {name}</p>
<button onClick={()=>{
editName("开课吧");
}}>修改姓名</button>
props和state
组件无论是使用函数声明还是通过 class 声明,都决不能修改自身的 props
props
外部传递给组件的响应式参数
类组件props获取
在render函数中通过this.props获得
const item ={ title: `家人`, content: [{ name: `爸爸` }, { name: `爸爸` }]};
<Dllist contentData ={item} />
class Dllist extends Component {
render() {
let { contentData } = this.props;
}
}
函数组件中props获取
const data ='传递的数据';
<Newtodo name={data}/>
export default function Newtodo(props) {
const {name} = props
}
state
组件内部的响应式参数,
state 状态,是 Component 的属性,我们会将组件相关的数据放入 state ,然后通过 state 属性 和 组件要构建的视图进行绑定,当 state 更新时,同步会更新我们的视图
state状态的修改
- setState(updater, [callback])
- updater: 更新数据 FUNCTION/OBJECT
- callback: 更新成功后的回调 FUNCTION
- 异步:react通常会集齐一批需要更新的组件,然后一次性更新来保证渲染的性能
- 浅合并 Objecr.assign()
- 调用 setState 之后,会触发生命周期,重新渲染组件
- setState为异步操作,这点和vue一样,都是为了性能考虑
- setState为浅合并
类组件state的声明和使用
class App extends Component {
state={
data:{
count: 1,
name: "kkb"
}
}
render(){
let {count,name} = this.state.data;
return <div>
<p>{name}</p>
<strong>{count} </strong>
<button onClick={()=>{
this.setState({
data: {
...this.state.data,
count: count + 1
}
});
}}>递增</button>
</div>
}
}
函数组件state的声明和使用(搭配hook使用)
组件生命周期
相比vue 生命周期的单纯,react 生命周期各种花里胡哨,真的可能会用也就是componentDidMount/componentDidUpdata/componentWillUnmount
ref
和vue的refs一样,获得DOM元素
下面是几个适合使用 refs 的情况:
- 管理焦点,文本选择或媒体播放。
- 触发强制动画。
- 集成第三方 DOM 库。
避免使用 refs 来做任何可以通过声明式实现来完成的事情。
类组件中使用ref
import React, { Component, createRef } from 'react'
export default class List extends Component {
constructor(props) {
super(props);
// 创建一个 ref 来存储 textInput 的 DOM 元素
this.textInput = React.createRef();
this.focusTextInput = this.focusTextInput.bind(this);
}
focusTextInput() {
// 直接使用原生 API 使 text 输入框获得焦点
// 注意:我们通过 "current" 来访问 DOM 节点
this.textInput.current.focus();
}
render() {
// 告诉 React 我们想把 <input> ref 关联到
// 构造器里创建的 `textInput` 上
return (
<div>
<input
type="text"
ref={this.textInput} />
<input
type="button"
value="Focus the text input"
onClick={this.focusTextInput}
/>
</div>
);
}
}
hook
Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性
Hook 是一些可以让你在函数组件里“钩入” React state 及生命周期等特性的函数
hook规则
1. 只在最顶层使用 Hook
2. 只在React函数中调用Hook
- 在 React 的函数组件中调用 Hook
- 在自定义 Hook 中调用其他 Hook
state hook — useState
useState整合了类组件的state和setState方法,函数通过在函数组件里调用它来给组件添加一些内部 state。React 会在重复渲染时保留这个 state。useState
会返回一对值:当前状态和一个让你更新它的函数,你可以在事件处理函数中或其他一些地方调用这个函数。
const [state, setState] = useState(initialState);
1. [状态,修改该状态的方法] = useState(初始值);
2. 在同一个组件中可以使用 useState 定义多个状态
3. 注意 useState 返回的 setState 方法,不会进行对象合并
4. 注意 useState 返回的 setState 方法同样是异步方法
import React, { useState } from "react";
export default function App(props) {
const [name,setName] = useState("kkb");
const [count,setCount] = useState(1);
return <div>
<p>{name}</p>
<p>{count}</p>
<button onClick={()=>{
setCount(count+1);
}}>递增</button>
</div>
}
Effect Hook — useEffect
useEffect
就是一个 Effect Hook,给函数组件增加了操作副作用的能力。它跟 class 组件中的componentDidMount
、componentDidUpdate
和componentWillUnmount
具有相同的用途,只不过被合并成了一个 API。
import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
// 相当于 componentDidMount 和 componentDidUpdate:
useEffect(() => {
// 使用浏览器的 API 更新页面标题
document.title = `You clicked ${count} times`;
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
useEffect 执行顺序
useEffetc(()=>{
console.log('这是回调函数')
return ()=>{
console.log('这是返还函数')
}
},[data])
//组件挂载完成或data修改引起的组件更新完之后执行
useEffect(()=>{},[]);// 组件挂载完成
- 挂载过程
- 组件挂载成功 --> 回调函数
- 更新过程
- 组件即将更新 --> 执行 useEffect 的返还函数 --> 组件更新 --> useEffect 的回调函数
- 卸载过程
- 执行 useEffect 的返还函数
useRef
函数组件中使用ref
import React, { useEffect, useState, useRef } from "react";
function Child(props) {
const {name,setName} = props;
const [count,setCount] = useState(1);
const countP = useRef(null);
useEffect(()=>{
console.log(countP.current);
});
return <div>
<p>{name}</p>
<button onClick={()=>{
setName("开课吧");
}}>中文名</button>
<p ref={countP}>{count}</p>
<button onClick={()=>{
setCount(count+1);
}}>递增</button>
</div>
}
export default Child;
自定义hook
- 自定义 Hook 必须以 “
use
” 开头 - 两个组件中使用相同的 Hook 不会共享 state
由于自定义hook中可以调用其他hook,那么自定义hook可以将某个重复功能进行封装并实现数据响应式,必须返回[参数,函数]
import React, { useState, useEffect } from "react";
/*
自定义 hook
要求命名必须以 use 开始
*/
function useScrollY() {
const [scrollY,setScrollY] = useState(0);
useEffect(()=>{
window.onscroll = function () {
setScrollY(window.scrollY);
}
setScrollY(window.scrollY);
return ()=>{
window.onscroll = null;
}
},[]);
return [scrollY,(y)=>{
window.scrollTo(0,y);
setScrollY(y);
}]
}
export {useScrollY}
Hook API 目录
router
提供声明性的、可访问的导航
React Router 提供了多种不同环境下的路由库
-
web:
npm i -S react-router-dom
-
native
router原理概要
实现两个组件,Link/NavLink 组件将配置转变为a标签,Router同时监听浏览器的hashchange 或者 url变更,当变更时Route组件根据当前url信息匹配到对应路由并进行渲染
Link组件
- to: string
- Link 的地址字符串表示形式,通过连接位置的 pathname, search, and hash创建。
<Link to="/about">About</Link>
-
- object可以是如下属性
pathname
: A string representing the path to link to.search
: A string representation of query parameters.hash
: A hash to put in the URL, e.g.#a-hash
.state
: State to persist to thelocation
.
<Link to={{ pathname: "/courses", search: "?sort=name", hash: "#the-hash", state: { fromDashboard: true } }} />
- object可以是如下属性
-
- 作为参数传递到的函数,它应该返回以符串或对象的形式
<Link to={location => ({ ...location, pathname: "/courses" })} /> <Link to={location => `${location.pathname}?sort=name`} />
NavLink组件
的一个特殊版本,当呈现的元素与当前URL匹配时,它将向该元素添加样式属性。
- activeClassName: string
- 当元素处于活动状态时,类名对应的样式将会执行。默认的给定类是active。这将与类名prop连接起来
<NavLink to="/faq" activeClassName="selected">
FAQs
</NavLink>
- activeStyle: object
- 当元素处于激活状态时,样式集被激活使用
<NavLink
to="/faq"
activeStyle={{
fontWeight: "bold",
color: "red"
}}
>
FAQs
</NavLink>
-
- 默认为真代表精确匹配
<NavLink
to="/events/123"
isActive={(match, location) => {
if (!match) {
return false;
}
// only consider an event active if its event id is an odd number
const eventID = parseInt(match.params.eventID);
return !isNaN(eventID) && eventID % 2 === 1;
}}
>
Event 123
</NavLink>
Route组件
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter as Router, Route } from "react-router-dom";
ReactDOM.render(
<Router>
<div>
<Route exact path="/">
<Home />
</Route>
<Route path="/news">
<NewsFeed />
</Route>
</div>
</Router>,
node
);
…后面的内容待补充
redux
redux 上手指南
-
创建store
- 定义reducer初始化state并定义state修改规则
- 通过dispatch一个action来提交对数据的修改
- action提交到reducer函数⾥里里,根据传⼊入的action的type,返回新的state
import { createStore } from "redux"; const reducer = (state = { todos: [{ id: 1, title: '任务一', completed: false }] }, action) => { switch (action.type) { case 'addTodos': return { ...state, todos:[ ...state.todos, { id:Date.now(), title:action.title, completed: false } ] } default: return statereact } } const store = createStore(reducer); export default store;
import {useDispatch} from "react-redux"; const dispatch = useDispatch(); dispatch({react type: 'addTodos', title: todo })
react-redux提供了了两个api
- Provider 为后代组件提供store
- connect 为组件提供数据和变更更⽅方法
import React from 'react' import ReactDom from 'react-dom' import App from './App' import store from './store/' import { Provider } from 'react-redux' ReactDom.render( <Provider store={store}> <App/> </Provider>, document.querySelector('#root') )
import {connect} from "react-redux"; export default connect(state => state)(App);
或者
import { useSelector } from 'react-redux' // useSelector 获取state const data = useSelector(state => state.data) // useDispatch获取dispatch const dispatch = useDispatch()
供数据和变更更⽅方法
import React from 'react'
import ReactDom from 'react-dom'
import App from './App'
import store from './store/'
import { Provider } from 'react-redux'
ReactDom.render(
<Provider store={store}>
<App/>
</Provider>,
document.querySelector('#root')
)
import {connect} from "react-redux";
export default connect(state => state)(App);
或者
import { useSelector } from 'react-redux'
// useSelector 获取state
const data = useSelector(state => state.data)
// useDispatch获取dispatch
const dispatch = useDispatch()