react 合并数组_React快速上手
Quick Start
可以使用 create-react-app 快速創(chuàng)建 react 項目,里面已經(jīng)封裝好了常用的 webpack 的配置。這個工具其實就和 Vue 里面的 vue-cli 一樣,都是用來快速創(chuàng)建腳手架的
npm install -g create-react-app初始化一個項目
create-react-app democd demonpm run start如果你需要定制 webpack 的配置可以執(zhí)行 run run eject ,字面意思就是彈射出 webpack 配置。注意這個操作書不可逆向的,如果需要回退,不僅僅是代碼的回退,還需要刪除 node_modules 文件夾進行重新安裝
JSX 語法
這個就不多說了,在 Vue 里面也用過 JXS 語法,兩者用法是一致的,使用三元表達式或者使用與運算的懶惰特性來動態(tài)顯示隱藏節(jié)點,使用 map 函數(shù)來循環(huán)輸出節(jié)點
對于在元素上聲明的屬性可以在組件的 props 中拿到,對于 class 屬性,建議使用 className 屬性來定義,以此來和原生定義進行區(qū)分
對于 Vue 中的 slot,在 React 是把它當作一個 props 來處理的,在 props 中有個 children 存放著組件的一級子節(jié)點。這種定義方式似乎很靈活,缺點就是不夠語義化
{this.props.children[0]} {this.props.children[1]}你看,通過簡單的定義就實現(xiàn)了 Vue 中的具名插槽
{this.props.children.find(v => v.props.name === '1')} {this.props.children.find(v => v.props.name === '2')}本質(zhì)上,JSX 是 React.createElement 的語法糖,最終都會編譯為 React.createElement。
更多 React 中使用 JSX 的語法可以參考 深入 JSX
組件
分為函數(shù)組件和 Class 組件
function App(props) { return ({props.title}
)}上面的函數(shù)組件可以改寫為 Class 組件。在開發(fā)的過程中肯定是推薦使用使用 Class 組件的,因為可以在里面定義各種生命周期函數(shù)和點擊事件
這里關(guān)于點擊事件有一個 this 指向的坑,解決方案是使用 bind 或者箭頭函數(shù),不然的事件處理函數(shù)內(nèi)拿到的 this 是 undefined
關(guān)于使用 bind 也有好幾種方式,可以在 constructor 中 bind,也可以在事件發(fā)生時 bind
class App extends React.Component { divClick = () => { console.log(this) } spanClick = function () { console.log(this) } render() { return ({this.props.title}
123 456 ) }}組件數(shù)據(jù)
組件的數(shù)據(jù)有兩種 props 和 state。props 是外部傳進來的,肯定是不能去變它的,參考 Vue 的單向數(shù)據(jù)流。組件自身的數(shù)據(jù)是通過 state 來定義的
Vue 中實現(xiàn)數(shù)據(jù)綁定靠的是數(shù)據(jù)劫持(Object.defineProperty())和發(fā)布訂閱模式,一切都是自動的。在 React 中,需要顯式地去調(diào)用 setState 去改變 state 中的數(shù)據(jù)
出于性能考慮,React 可能會把多個 setState() 調(diào)用合并成一個調(diào)用,他是異步的,比如下面的代碼可能會得不到預(yù)期的結(jié)果
// num 5this.setState({ num: 0 })// 在這一步,this.state.num的值可能是5this.setState({ num: this.state.num + 1 })如果你在更新 state 時依賴原有 state 的內(nèi)容,為了解決這一問題,官方建議使用下面的寫法
this.setState((state, props) => { return { num: state.num + 1 }})還有一個就是 state 初始化,一般都是在 constructor 構(gòu)造函數(shù)中完成,但是如果 state 中的數(shù)據(jù)依賴 props 中的數(shù)據(jù),后續(xù) props 改變時 state 時不會變化的。
若期望跟著變化,可以實現(xiàn)生命周期中的 getDerivedStateFromProps。注意這里的方法是靜態(tài)的拿不到 this
class App2 extends React.Component { constructor(props) { super(props) this.state = { num: props.num } } static getDerivedStateFromProps(nextProps, prevState) { if (nextProps.num !== prevState.num) { return { num: nextProps.num } } return null } render() { return }}setState 基本使用
修改 object 中某項
this.setState({ object: { ...object, key: value }})數(shù)組操作
array.splice(index, 1)array.push(99)this.setState({ array: array})復(fù)雜類型修改,不建議使用
this.setState(prevState => return newState)如果上面的都不好使,可以使用 forceUpdate
props 校驗/默認值
通過 propTypes 中聲明的校驗器對 propName 進行校驗,建議每個組件都設(shè)置 propTypes,別人通過看 propTypes 就能知道該組件可以傳入哪些 props
class App2 extends React.Component { render() { return {this.props.age} }}App2.propTypes = { age: function (props, propName, componentName) { if (typeof props[propName] != 'number') { return new Error(`${componentName} props[${propName}] must be number`) } }}對于一些常用的類型判斷,可以導(dǎo)入 prop-types 來判斷
import PropTypes from 'prop-types'App2.propTypes = { age: PropTypes.number}對于默認值,除了在使用的時候判斷還可以使用 defaultProps
App2.defaultProps = { age: 18}另外上述在 Class 外聲明的屬性都是靜態(tài)屬性,目前 ES6 明確規(guī)定,Class 內(nèi)部只有靜態(tài)方法,沒有靜態(tài)屬性,但是有 Babel 去處理,如下寫法也可以
class App2 extends React.Component { static defaultProps = { age: 20 } render() { return {this.props.age} }}表單雙向綁定
這里的雙向綁定和 Vue 中的 v-model 差的太多了,React 實現(xiàn)雙向綁定都是監(jiān)聽 input 事件手動去 setState
這里有個坑,傳入的 event 是 React 包裝過的,當函數(shù)執(zhí)行完畢,里面的東西就沒了,所以在控制臺打印的 event 里面的 target 是 null,解決這個問題手動調(diào)用下 event.persist() 就好了
handleChange = event => { this.setState({ num: Number(event.target.value) })}render() { return (還有一類表單是文件,它的值是只讀的,無法通過 value 去改變他,在 React 中稱為非受控組件。處理的方式和 Vue 一樣,就是使用 ref 拿到 DOM 節(jié)點
constructor(props) { super(props) this.file = React.createRef()}render() { return (數(shù)據(jù)共享和組件通信
方案一,層層傳遞 props
在非父子組件時,無法向下流動 props 了,官方的做法是狀態(tài)提升,因為這兩個組件雖然無法形成父子組件,但是他們一定有公共的父組件,所以就把數(shù)據(jù)定義在公共的父組件里,公共父組件定義修改 state 的方法,然后將此方法調(diào)用 prop 傳遞到子組件
這種通信方式和 Vue 的 emit 的方式一樣
class App2 extends React.Component { handleChange = event => { this.props.emitChange(event.target.value) } render() { return }}class App3 extends React.Component { render() { return {this.props.text} }}class App extends React.Component { constructor(props) { super(props) this.state = { text: 'text' } } emitChange = v => { this.setState({ text: v }) } render() { return (方案二,使用 Context
要通信的兩個組件和他們的公共父組件相距太遠時,需要為中間每一個中間組件傳遞 props 是很麻煩的。使用 context, 我們可以避免通過中間元素傳遞 props
聲明一個 Context, React.createContext() 接收一個參數(shù),當使用 Consumer 時,會找到離他最近的 Provider,未找到 Provider,未找到時該默認值
const ThemeContext = React.createContext()使用 Provider 包裹后,里面的組件若使用 Consumer,則可以拿到 Provider 中的 value
class App extends React.Component { constructor(props) { super(props) this.state = { theme: { now: 'light', light: {}, dark: {}, toggle: this.toggleTheme } } } toggleTheme = () => { let now = this.state.theme.now let next = now === 'dark' ? 'light' : 'dark' this.setState({ theme: { ...this.state.theme, now: next } }) } render() { return (組件使用 Consumer 來訂閱 Context 的變動
class App3 extends React.Component { render() { return ( {({ now, toggle }) => (當前主題:{now}
切換主題 )} ) }}使用了 contextType 后,上面的寫法可以簡化為如下寫法,同時在各個生命周期函數(shù)中都可以通過 this 拿到 Context。同時也說明了一個問題,一個組件可能會消費多個 context,但是最好還是消費一個 context
class App3 extends React.Component { render() { let ctx = this.context return (當前主題:{ctx.now}
切換主題 ) }}App3.contextType = ThemeContext組件生命周期
生命周期速查表
當組件實例被創(chuàng)建并插入 DOM 中時,其生命周期調(diào)用順序如下:
當組件的 props 或 state 發(fā)生變化時會觸發(fā)更新。組件更新的生命周期調(diào)用順序如下:
當組件從 DOM 中移除時會調(diào)用如下方法
CSS 樣式
一般是通過 import 進來的 css 是全局的
import './index.css'為了防止 css 全局污染,除了使用 BEM 命名規(guī)則盡可能的規(guī)范命名外,根本的解決方式就是模塊化使用 CSS
一種寫法是聲明行內(nèi)樣式。缺點也很明顯:大量的樣式, 代碼混亂,一些子選擇器,偽類和一些動畫沒法用這種方式實現(xiàn)
const style1 = { fontSize: '15px', color: 'pink'}{this.props.age}
{this.state.value}
另一種寫法是使用 CSS Modules
create-react-app 腳手架都配置好了,當導(dǎo)入 .module.css/.module.less/.module.scss 結(jié)尾的文件時,它會自動重命名 class 的類名,默認情況下重命名的規(guī)則是 組件名_類名__hash 。看起來不錯,假如有個類命名帶橫線時 .main-title 就沒辦法取出了
app.module.css
/*等價于:local(.s1)*/.s1 { color: pink;}.s1 span { color: blue;}.s3 { composes: s1; /*繼承s1, 也可以引入其他css文件選擇去繼承某個class*/ font-size: 15px;}/*不會被css-loader重命名*/:global(.s2) { color: red;}使用
import style from './app.module.css'render() { return ({this.props.age}
{this.state.value}
)}還有一種方案是 CSS in JS,CSS 由 JavaScript 生成而不是在外部文件中定義。改功能并不是 React 的一部分,而是由第三方庫提供,比如 styled-components
其他知識點
- 組件渲染失敗的處理在父組件/根組件使用 componentDidCatch 方法監(jiān)聽失敗錯誤,用于記錄日志。用 getDerivedStateFromError 方法來更新 state 的狀態(tài),一般是使一些錯誤提示組件取消隱藏
- 組件可以沒有根元素在 render 函數(shù)中,必須要有一個根元素,一般都是 div。在 DOM 節(jié)點如果不需要這個根節(jié)點,可以使用 包裹,或者使用 <> > 包裹
- 使用 jQuery這一點和 Vue 一樣,都是使用 ref。需要注意的是的,在 componentWillUnmount 階段,記得調(diào)用一些 jQuery 插件的銷毀時間
- Portals默認都是在父組件內(nèi)渲染,使用 Portals 可以指定渲染的位置import ReactDOM from 'react-dom' class App4 extends React.Component { constructor(props) { super(props) this.slot = document.querySelector('#outer') if (!this.slot) { this.slot = document.createElement('div') this.slot.setAttribute('id', 'outer') document.body.appendChild(this.slot) } } render() { let node = node return ReactDOM.createPortal(node, this.slot) } }
- Profiler一個工具節(jié)點,可以計算子子組件的渲染消耗
Hook
Hook 就是 JavaScript 函數(shù),它可以讓你在不編寫 class 的情況下使用 state 以及其他的 React 特性。簡單來說 Hook 就是函數(shù)組件的拓展,達到和 class 組件相同的功能,同時寫法上也更加簡單
useState:返回一個數(shù)組,第一個是值,第二個更新值的函數(shù)。同時 React 會在重復(fù)渲染時保留這個 state。在一個函數(shù)組件 useState 可以多次調(diào)用,創(chuàng)建多個 state,另外 useState 也可以傳入對象和數(shù)組
useEffect:它跟 class 組件中的 componentDidMount、componentDidUpdate 和 componentWillUnmount 具有相同的用途,只不過被合并成了一個 API,相當于聲明了一個回調(diào)函數(shù),默認情況下,它在第一次渲染之后和每次更新之后都會執(zhí)行。useEffect 可以調(diào)用多次
useContext:不用被 Consumer 包裹,也可以在 jsx 外拿到 Context
import React, { useState } from 'react'function Example(props) { // 數(shù)組的解構(gòu)賦值的語法, useState 返回一個數(shù)組 const [count, setCount] = useState(0) const [value, setValue] = useState(0) // 在useEffect內(nèi)調(diào)用update時,要給定 dependences 列表,防止無限更新 useEffect(() => { setValue(count * count) }, [count]) return (You clicked {count} computed: {value}
setCount(count + 1)}>Click me )}總結(jié)
大致了解下 React 后發(fā)現(xiàn)還是 Vue 香
感覺 React 的一些概念很難搞懂,比如 Render Props、Hook。相比較而言還是 Vue 的一些概念簡單易懂,也可能是 Vue 的中文文檔寫的比較好吧。
其次就是腳手架,官方的 create-react-app 可以說沒留給用戶配置的地方,除非你把 webpack 的配置給彈射出來去手動配置,相比較之下 Vue-cli 真的是非常人性化了。不過還好可以使用 UmiJS 這類的第三方腳手架
總結(jié)
以上是生活随笔為你收集整理的react 合并数组_React快速上手的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 获取的官方例程后怎么开发_开发商败诉后拒
- 下一篇: sam机架和kx连线图_「声卡跳线」雅马