Эта статья включена в githubGitHub.com/Майкл-Ли Чжиган…
Особенности Реакта
- Создавайте компоненты с использованием синтаксиса JSX, внедряйте разработку на основе компонентов и открывайте двери для функционального программирования пользовательского интерфейса.
- Высокая производительность приветствуется: эффективное обновление представлений с помощью алгоритма сравнения и виртуального DOM.
Зачем использовать Реакт
- Используйте компонентные методы разработки в соответствии с тенденцией современной веб-разработки.
- Зрелая технология, полное сообщество, полные аксессуары, подходящие для крупномасштабных веб-проектов (звуковая экосистема)
- Поддерживается специальной командой Facebook с надежной технической поддержкой
- ReactNative - Learn once, write anywhere: Build mobile apps with React
- Простое использование, очень высокая производительность, поддержка рендеринга на стороне сервера
- React очень популярен, с технической точки зрения он может удовлетворить любопытство и повысить технический уровень, с профессиональной точки зрения он способствует поиску работы и продвижению по службе, а также способствует участию в проектах с высоким потенциалом.
Два способа создания компонентов
- Создано с помощью функций JS (компоненты без состояния)
- Создано классом (компоненты с отслеживанием состояния)
создание JS-функции
- Имя функции должно начинаться с заглавной буквы.React использует эту функцию, чтобы определить, является ли она компонентом.
- Функция должна иметь возвращаемое значение, возвращаемое значение может быть: объект JSX или null
- Возвращаемый JSX, должен иметь корневой элемент
- Возвращаемое значение компонента заключено в (), чтобы избежать разрывов строк.
function LearningList(props) {
return (
<div className="list">
<h1>LearningList for {props.name}</h1>
<ul>
<li>Vue</li>
<li>React</li>
<li>Angular</li>
</ul>
</div>
)
}
ReactDOM.render(<Welcome name="lzg" />, document.getElementById('app'))
создание класса
В es6 класс — это просто синтаксический сахар, а не настоящий класс, по сути, это конструктор + прототип для достижения наследования.
class LearningList extends React.Component {
constructor(props) {
super(props)
}
// class创建的组件中 必须有render方法 且显示return一个react对象或者null
render() {
return (
<div className="list">
<h1>LearningList for {props.name}</h1>
<ul>
<li>Vue</li>
<li>React</li>
<li>Angular</li>
</ul>
</div>
)
}
}
синтаксис jsx
Синтаксис jsx — это расширение синтаксиса JavaScript, которое удобно использовать в React для описания пользовательского интерфейса. Например, следующий синтаксис jsx
const element = <h1>Hello, world!</h1>
Практически эквивалентно приведенному выше коду:
var element = React.createElement('h1', null, 'Hello, world!')
спецификация написания jsx
- Верхний уровень jsx может иметь только один корневой элемент, поэтому мы часто оборачиваем div (или используем Fragment) во внешний слой.
- Тег в jsx может быть одинарным или двойным; если это одиночный тег, он должен заканчиваться на />
- Внешний слой jsx заключен в круглую скобку (), которая легко читается, а jsx можно писать с переводом строки
- Внутри {} вы можете написать любой код, соответствующий спецификации JS; если вы хотите написать комментарии, комментарии должны быть размещены внутри {}
Встроить выражения в jsx
В синтаксисе jsx вы можете поместить любое допустимое выражение JavaScript в фигурные скобки, это может быть
- выражение операции
- Тернарный оператор
- выполнить функцию
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
firstName: 'kobe',
lastName: 'bryant',
age: 20,
}
}
sayHello(name) {
return 'Hello ' + name
}
render() {
return (
<div>
<h2>{this.state.firstName + ' ' + this.state.lastName}</h2>
<h2>{this.state.age >= 18 ? '成年人' : '未成年人'}</h2>
<h2>{this.sayHello('lzg')}</h2>
</div>
)
}
}
условный рендеринг jsx
1. Отрисовка двух компонентов попеременно
class HelloMessage extends React.Component {
render() {
let userMessage
if (this.props.loggedIn) {
userMessage = (
<h1>Welcome back!</h1>
)
} else {
userMessage = (
<h1>Please sign up.</h1>;
)
}
return (
<div>
<h1>My Super React App</h1>
{userMessage}
</div>
)
}
}
2, компонент с рендерингом или без него
function MessageList(props) {
const unreadMessages = props.unreadMessages
return (
<div>
<h1>Hello!</h1>
{unreadMessages.length > 0 && <h2>You have {unreadMessages.length} unread messages.</h2>}
</div>
)
}
цикл списка jsx
В синтаксисе jsx рендеринг цикла заключается в использовании карты обхода массива(). Метод возвращает коллекцию.
Во время обхода должен быть уникальный ключ индекса, чтобы повысить эффективность обхода. Ключ элемента предпочтительно представляет собой уникальную строку, которая есть у элемента в списке, а индекс можно использовать в крайнем случае.
class Admin extends Component {
constructor(props) {
super(props)
this.state = {
menus: [
{ icon: require('../imag/home/ic_noti_block@2x.png'), title: '菜单1' },
{ icon: require('../imag/home/ic_noti_block@2x.png'), title: '菜单2' },
{ icon: require('../imag/home/ic_noti_block@2x.png'), title: '菜单3' },
{ icon: require('../imag/home/ic_noti_block@2x.png'), title: '菜单4' },
],
}
}
renderList(value, index) {
return (
<li key={index}>
<p>张三</p>
<p>18岁</p>
</li>
)
}
render() {
return (
<div>
<ul>
{[1, 2, 3, 4, 5].map((value, index) => {
return this.renderList(value, index)
})}
</ul>
<ul>
{this.state.menus.map((value, index) => {
return (
<li key={index}>
<img src={value.icon} width="30" />
<div>{value.title}</div>
</li>
)
})}
</ul>
</div>
)
}
}
получить реквизиты данных
Мы хотим передавать значения между компонентами, поэтому эту роль играет атрибут props. Каждый компонент реакции может принимать параметр props, который представляет собой объект, содержащий всю вашу конфигурацию для компонента.
Функции
- React преобразует свойство, переданное компоненту, в объект и передает его свойствам.
- реквизит доступен только для чтения, вы не можете добавлять или изменять свойства реквизита
function Person(props) {
return (
<ul>
<li>姓名: {props.name}</li>
<li>年龄: {props.age}</li>
</ul>
)
}
ReactDOM.render(<Welcome name="lzg" age="18" />, document.getElementById('app'))
состояние компонента
Если вам нужно определить пользовательские свойства компонента, вам необходимо определить состояние в конструкторе конструктора компонента.
Функции
- Только компоненты, созданные с помощью класса, имеют состояние
- состояние является частным и полностью контролируется компонентом
- Не добавляйте ненужные данные в метод render() в состояние, это повлияет на производительность рендеринга!
- Не вызывайте метод setState() в методе render() для изменения значения состояния.
Разница между государством и реквизитом
props — внешний интерфейс компонента, а state — внутренний интерфейс компонента. Основное различие между ними: состояние является изменяемым и представляет собой набор компонентов, которые возвращают компоненты пользовательского интерфейса, поддерживаемые внутри компонента, в то время как реквизиты являются свойством компонента только для чтения.Реквизиты не могут быть изменены непосредственно в компоненте, но могут только изменяться на верхнем уровне компонента.
создать состояние
Если вам нужно определить пользовательские свойства компонента, определите состояние в конструкторе конструктора компонента.
class Mycom extends React.Component {
constructor(props) {
super(props)
//给this.state赋值一个对象,对象的属性就是组件的自定义属性
this.state = {
name: 'lzg',
}
}
}
изменить состояние
Вы не можете напрямую изменить значение состояния, иначе данные не могут управлять ассоциацией, вам нужно использовать setState, метод setState получает параметр, а параметр является объектом, аналогичным родному setData апплета.
// 错误方式
this.state.name = 'lzg'
// 正确方式
this.setState({ name: 'lzg' })
Всегда безопаснее использовать вторую форму this.setState(), потому что обновленные свойства и состояние являются асинхронными. Здесь мы обновляем состояние на основе этих реквизитов.
// 错误方式
this.setState({
total: this.state.total + this.props.count,
})
// 正确方式
this.setState((state, props) => {
total: state.total + props.count
})
Кроме того, SetState также может получать второй параметр, второй параметр является функцией обратного вызова.
this.setState(
{
name: 'lzg',
},
() => {
console.log('state值修改成功,现在的name值为' + this.state.name)
}
)
Почему вы не можете изменять состояние напрямую, вам нужно setState? Какой SetState делает не только для изменения значения этого .state, но самое главное, что он будет вызвать механизм обновления реагирования, который будет работать, а затем обновлять патча до настоящего DOM.
привязка события
1. Используйте привязку, чтобы связать это при вызове
class Foo extends React.Component {
handleClick() {
this.setState({ name: 'lzg' })
}
render() {
return <button onClick={this.handleClick.bind(this)}>Click me</button>
}
}
2. Используйте привязку, чтобы связать это в конструкторе
class Foo extends React.Component {
constuctor(props) {
super(props)
this.handleClick = this.handleClick.bind(this)
}
handleClick() {
this.setState({ name: 'lzg' })
}
render() {
return <button onClick={this.handleClick}>Click me</button>
}
}
3. Используйте функции стрелок, чтобы связать это
class Foo extends React.Component {
handleClick() {
this.setState({ name: 'lzg' })
}
render() {
return <button onClick={(e) => this.handleClick(e)}>Click me</button>
}
}
4. тип полей публичного класса
class Foo extends React.Component {
handleClick = () => {
this.setState({ name: 'lzg' })
}
render() {
return <button onClick={this.handleClick}>Click me</button>
}
}
реактивный стиль
- Пишите встроенные стили напрямую:
export const Footer = () => {
return <div style={{{color:'orange', fontSize:'12px'}}>All Rights Reserved 2019</div>
}
- абстрагируется в объектную форму
import React from 'react'
const footerStyle = {
backgroundColor: 'green',
fontSize: '12px',
color: 'orange',
fontWeight: 'bold',
}
export const Footer = () => {
return <div style={footerStyle}>All Rights Reserved 2019</div>
}
- Используйте таблицы стилей для определения стилей:
import '../css/comment.css'
export const Footer = () => {
return <div className="footer">All Rights Reserved 2019</div>
}
функция жизненного цикла
Жизненный цикл компонента состоит из трех фаз: фаза создания (монтирование), фаза запуска и взаимодействия (обновление) и фаза размонтирования (размонтирование).
-
Монтаж, в свою очередь, вызывает следующие функции
- конструктор(): конструктор для классов ES6 (для инициализации состояния или привязки этого)
- getInitialState(): Инициализировать состояние в ES5.
- getDefaultProps(): Инициализировать свойства в ES5. Используйте метод defaultProps() в ES6.
- componentWillMount(): вызывается перед монтированием компонента. Выполнить только один раз.
- render(): для рендеринга компонентов этот метод должен быть реализован.
- componentDidMount(): вызывается после монтирования компонента. На данный момент настоящий узел DOM сгенерирован. Выполнить только один раз.
-
Обновление последовательно вызывает следующие функции
- КомпонентWillReceiveProps () компонент получен до новых реквизитов, которые вызвали этот метод
- shouldComponentUpdate() решает, следует ли повторно отображать компонент в соответствии с возвращаемым значением этого метода, возвращает true для повторного отображения, в противном случае он не отображается
- componentWillUpdate() компонент будет обновлен
- render() повторно отображает компонент, что является той же функцией, что и рендеринг на этапе монтирования.
- componentDidUpdate() компонент был обновлен
-
Unmounting
- componentWillUnmount() размонтирует компонент, сбрасывает таймер, очищает дом
PropTypes
Приложения со временем становятся больше, поэтому проверка типов очень важна. PropTypes обеспечивает проверку типов для компонентов и предоставляет хорошую документацию для других разработчиков. Если реактивный проект не использует Typescript, рекомендуется добавить в компонент PropTypes.
// 旧的写法
class PropTypeOne extends React.Component {
render() {
return (
<div>
<div>{this.props.name}</div>
<div>{this.props.email}</div>
</div>
)
}
}
PropTypeOne.propTypes = {
name: PropTypes.string,
email: function (props, propName, componentName) {
if (!/^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/.test(props[propName])) {
return new Error('组件' + componentName + '里的属性' + propName + '不符合邮箱的格式')
}
},
}
// 新的写法
class PropTypeTwo extends React.Component {
static propTypes = {
name: PropTypes.string,
}
render() {
return (
<div>
<div>{this.props.name}</div>
</div>
)
}
}
Консоль JavaScript отобразит предупреждение, когда будет передано неверное значение реквизита. Из соображений производительности propTypes проверяются только в режиме разработки.
Вы можете определить значения по умолчанию для реквизита, настроив определенные свойства defaultProps:
class Greeting extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>
}
}
// 指定 props 的默认值:
Greeting.defaultProps = {
name: 'Stranger',
}
// 渲染出 "Hello, Stranger":
ReactDOM.render(<Greeting />, document.getElementById('app'))
Контролируемые и неконтролируемые компоненты
Управляемые компоненты
Мы будем часто использовать формы для сбора пользовательского ввода, например <input>
<select>
<textearea>
При изменении состояния формы будет инициировано событие onChange для обновления состояния компонента. Этот тип компонента называется контролируемым компонентом в React. В контролируемом компоненте состояние, отображаемое компонентом, соответствует его значению или проверенному свойству. Таким образом, React устраняет локальное состояние компонента, делая доступным все состояние. . Официальный представитель React также рекомендует использовать компоненты контролируемой формы.
import React, { Component } from 'react'
export default class MyInput extends Component {
handleContentChange = (e) => {
this.setState({
content: e.target.value,
})
}
render() {
return (
<div>
<input type="text" value={this.state.value} onChange={this.handleContentChange} />
</div>
)
}
}
Процесс обновления состояния контролируемого компонента:
- Значение формы по умолчанию можно установить через начальное состояние
- Всякий раз, когда значение формы изменяется, вызывайте обработчик события onChange
- Обработчик события получает измененное состояние через объект события e и обновляет состояние компонента.
- Как только состояние будет обновлено с помощью метода setState, представление будет повторно отображено для завершения обновления компонента формы.
Данные в реакции передаются в одном элементе.Из примера мы видим, что данные формы поступают из состояния компонента и передаются через реквизит, который также называетсяОдносторонняя привязка данных. Затем мы записываем новые данные обратно в состояние через обработчик события onChange, и все готово.двусторонняя привязка данных.
неконтролируемые компоненты
Если компонент формы не имеет реквизита значения (проверенные реквизиты для переключателей и кнопок проверки), его можно назвать неконтролируемым компонентом.В неконтролируемом компоненте мы можем использовать ссылку, чтобы получить значение формы из DOM. Вместо того, чтобы писать обработчик событий для каждого обновления состояния.
class NameForm extends React.Component {
constructor(props) {
super(props)
this.handleSubmit = this.handleSubmit.bind(this)
}
handleSubmit(event) {
alert('A name was submitted: ' + this.input.value)
event.preventDefault()
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" ref={(input) => (this.input = input)} />
</label>
<input type="submit" value="Submit" />
</form>
)
}
}
ref
React поддерживает очень специальное свойство Ref, которое вы можете использовать для привязки к любому выводу компонента с помощью render().
Использование строки
пройти черезthis.refs['inputRef']
посетить
<input ref="inputRef" />
ref как функция обратного вызова
class AutoFocusTextInput extends Component {
componentDidMount(){
this.textInput.focus();
}
render(){
return (
<Input ref={(input) => { this.textInput = input }}>
)
}
}
Функция обратного вызова ref родительского компонента может использовать DOM дочернего компонента.
function CustomTextInput(props) {
return (
<div>
<input ref={props.inputRef} />
</div>
)
}
class Parent extends React.Component {
render() {
return <CustomTextInput inputRef={(el) => (this.inputElement = el)} />
}
}
React.createRef()
После версии React 16.3 используйте этот метод для создания ref. Который присваивается переменной, узлу ref dom или компоненту монтирования, атрибуту ref текущего Узел Dom сможет получить или экземпляр компонента
class Child extends React.Component {
constructor(props) {
super(props)
this.myRef = React.createRef()
}
componentDidMount() {
console.log(this.myRef.current)
}
render() {
return <input ref={this.myRef} />
}
}
react-router
react-router-dom — это библиотека для маршрутизации в приложении. Функционала маршрутизации в библиотеке React нет, вам нужно установить react-router-dom отдельно.
react-router-dom предоставляет два маршрутизатора BrowserRouter и HashRoauter. Первый основан на сегменте имени пути URL-адреса, а второй основан на сегменте хеша.
Основное использование:
npm install react-router-dom --save
import { BrowserRouter, Route, Link, Redirect } from 'react-router-dom'
class MyRouter extends React.Component {
render() {
return (
<BrowserRouter>
<Link to="/">router1</Link>
<Link to="/router2">router2</Link>
<Link to="/router3">router3</Link>
<hr />
<Redirect exact from="/" to="/router1" />
<Route path="/router1" component={router1}></Route>
<Route path="/router2" component={router2}></Route>
<Route path="/router3" component={router3}></Route>
</BrowserRouter>
)
}
}
прыжок по маршруту
1. Перейти с тегом Link
import { BrowserRouter, Route, Link, Redirect } from 'react-router-dom'
class MyRouter extends React.Component {
render() {
return (
<BrowserRouter>
<Link to="/">router1</Link>
<Link to="/router2">router2</Link>
<Link to="/router3">router3</Link>
<hr />
<Redirect exact from="/" to="/router1" />
<Route path="/router1" component={router1}></Route>
<Route path="/router2" component={router2}></Route>
<Route path="/router3" component={router3}></Route>
</BrowserRouter>
)
}
}
2. Программная навигация
- Компоненты маршрутизации могут получать историю непосредственно из this.props.history.
- Компоненты без маршрутизации не могут получить историю напрямую и должны взаимодействовать с withRouter.
this.props.history.push(url)
this.props.history.go(-1)
параметры маршрутизации
1.params
<Route path='/path/:name' component={Path}/>
<link to="/path/123">xxx</Link>
this.props.history.push({pathname:"/path/" + name});
// 读取参数用:this.props.match.params.name
2.query
<Route path='/query' component={Query}/>
<Link to={{ pathname : '/query' , query : { name : 'sunny' }}}></Link>
this.props.history.push({pathname:"/query",query: { name : 'sunny' }});
// 读取参数用:this.props.location.query.name
3.state
<Route path='/sort ' component={Sort}/>
<Link to={{ pathname : '/sort ' , state : { name : 'sunny' }}}></Link>
this.props.history.push({pathname:"/sort ",state : { name : 'sunny' }});
// 读取参数用: this.props.location.query.state
4.search
<Route path='/web/search ' component={Search}/>
<link to="web/search?id=12121212">xxx</Link>
this.props.history.push({pathname:`/web/search?id ${row.id}`});
// 读取参数用: this.props.location.search
охранник маршрута
Компонент Route может получать компонент Component, и когда путь совпадает, компонент Route будет отображаться. Мы также можем сделать что-то после сопоставления пути, подобно охранникам маршрута в Vue.
Компонент Route по-прежнему используется, но на этот раз компонент передает данные не через Component, а через атрибут рендеринга.
import { Route } from 'react-router-dom'
function Custom() {
return (
<Route
path="/index"
Render={() => {
//isLogin判断用户是否登录,如果登录了渲染首页,没有登录渲染登录
if (isLogin) {
return <Index></Index>
} else {
return <Login></Login>
}
}}
/>
)
}
withRouter
Функция withRouter в компонентах более высокого порядка состоит в том, чтобы обернуть компонент в Route, а затем три объекта react-router, history, location и match будут помещены в свойство props этого компонента.
По умолчанию существует только компоненты, которые были отображены по сопоставлению маршрута.this.props
, иметь только параметры маршрутизации, может использовать метод записи программной навигации, выполнятьthis.props.history.push('/detail')
Перейти на страницу соответствующего маршрута, но не все компоненты напрямую подключены к маршруту (перейти к этому компоненту через маршрут).Когда этим компонентам нужны параметры маршрутизации, вы можете использовать withRouter для передачи параметров маршрута этому компоненту. В это время просто используйте this.props.
import React,{Component} from 'react'
import {Switch,Route,NavLink,Redirect,withRouter} from 'react-router-dom' //引入withRouter
import One from './One'
import NotFound from './NotFound'
class App extends Component{
//此时才能获取this.props,包含(history, match, location)三个对象
console.log(this.props); //输出{match: {…}, location: {…}, history: {…}, 等}
render(){
return (<div className='app'>
<NavLink to='/one/users'>用户列表</NavLink>
<NavLink to='/one/companies'>公司列表</NavLink>
<Switch>
<Route path='/one/:type?' component={One} />
<Redirect from='/' to='/one' exact />
<Route component={NotFound} />
</Switch>
</div>)
}
}
export default withRouter(App); //这里要执行一下WithRouter