Резюме этой статьи
В этой статье в основном написано об установке скаффолдинга CRA, синтаксисе React, классификации компонентов и переносе значений компонентов; если вы разработчик с богатым опытом работы с React, вы можете указать в статье на проблемы и области, которые можно улучшить. Выразите благодарность!
Это официальный сайт реакцииРеагировать на официальный сайт
Эта статья будет в основном разделена на:
- Реагировать на строительство проекта
- Синтаксис реакции
- Введение в компоненты React
- Значение передачи компонентов React
- Простой небольшой пример компонентизации
- Эта статья пока не представляет React-Router.
На прочтение полного текста у вас может уйти 10-20 минут, если вам интересно, то можете вместе набрать код
(используя редактор: VSCODE, плагин:VS Code ES7 React/Redux/React-Native/JS snippets
, этот плагин может быстро построить формат компонента, если вы хотите потренировать свои руки, не используйте быстрые инструкции)
Начните текст ниже
1. Создайте проект React с помощью скаффолдинга
Во-первых, здесь мы используем create-react-app (нужна среда nodejs) для создания этого проекта, в конце концов, это более удобно, есть и другие способы создания проектов, а также сервисы.
Найдите рабочую папку, затем откройте инструмент командной строки и введитеcreate-react-app mycode
создать папку какmycode
папка проекта, обратите внимание, что это имя проекта не поддерживает заглавные буквыхорошо, через несколько минут вам будет предложено успешно инициализировать скаффолдинг Вот несколько инструкций:
-
npm start
Откройте сервер разработки, обычно по умолчанию используется порт 3000, он появится автоматически после запуска.localhost:3000
страница -
npm run build
Создание упакованных статических файлов для производства -
npm test
Откройте тест, я его не использовал, студенты, которые его использовали, могут поделиться техническими статьями в комментариях. -
npm run eject
Eject распаковывает все инструменты (файлы конфигурации и зависимости package.json) по пути, где находится приложение.Этот процесс необратим.
Итак, давайте начнем,cd mycode
& npm start
.
2. Базовая грамматика
Два важных файла в проекте
После того, как мы начнем, мы увидим этот интерфейс, который поставляется с скаффолдингом. Пожалуйста, перейдите в редактор, здесь мы пока сосредоточимся только на двух важных файлах.-
public/index.html
Поскольку React строит спа, INDEX.html является нашей домашней страницей, которую вы также можете увидеть в файле.<div id="root"></div>
, Root — это позиция рендеринга корневого компонента. -
src/index.js
Это наш основной файл js,
Одно из выражений:render(<App></App>, window.root)
показывает, что мы используем метод рендерингаrender
,БудуApp
оказыватьroot
Посередине, что бы ни было в приложении, сколько уровней, сколько компонентов и сколько там логики, в конце остается только одна запись.
Все в React начинается здесь
Удаляем все файлы под scaffolding src и создаем пустойindex.js
, начать кодирование.
index.js
, все, что нам нужно сделать, это ввести библиотеку React, ввести react-dom, ввести корневой компонент, а затем выполнить метод рендеринга корневого компонента:
-
import React from 'react'
Обратите внимание, что React должен быть написан здесь с большой буквы. -
import {Component} from 'react'
, ввести компонентные методы, использовать{Component}
Введено деконструкцией -
import App from './App'
, введите приложение корневого компонента, мы создадим следующий шагsrc/App.js
В качестве нашего корневого компонента здесь вы можете взять любое имя в качестве корневого компонента js, я привык использовать его как приложение. -
render(<App></App>, window.root)
визуализировать компонент в корневой контейнер,render
Это основной метод рендеринга реакции, который мы будем использовать позже.
Введение в грамматику
① Введение в jsx
Согласно представлению о различных библиотеках в предыдущем разделе, мы можем изучить базовый синтаксис React, написав код в index.js.
Вкратце, язык реакцииjsx, согласно примеру в официальной документации:
const name = 'Josh Perez';
const element = <h1>Hello, {name}</h1>;
ReactDOM.render(
element,
document.getElementById('root')
);
Мы написали это под React<h1><h1>
Такие html-теги на самом деле будут отображаться на странице в соответствии с приведенным выше кодом, но как очень сладкий синтаксический сахар, нам больше не нужно писатьReactDOM.render()
, но
let el = <h1>hello <span>world</span></h1>
render(el,window.root);
Используя синтаксис javascript + xml, определите элемент, а затемrender
Рендеринг в порядке, в index.js можно закомментировать оригиналrender(<App></App>, window.root)
Это предложение, измененное на приведенный выше код, можно увидеть в localhost:3000.
② и {}
Если резюмировать одним предложением: Элемент jsx/элемент реакции помечен знаком
1) Выполнить js в {}
- переменное значение
let str = '<h1>world</h1>'
let el = (
<div>
<div>{str}</div>
</div>
)
render(el,window.root);
Эффект страницы показан на рисунке
Переменная str выполняется в {}, содержимое в середине div должно быть строкой'<h1>world</h1>'
, вместо меткиh1
- выйти
Что, если мы хотим написать комментарии в коде? Это правильно//
а нет, добавь{//}
Шерстяная ткань? О нет, вы можете увидеть в редакторе
{/*hello*/}
как замечание
-
Разбор строки в html
Это может привести к риску вставки в вредоносные сценарии выполнения.
упоминается в первом небольшом примере'<h1>world</h1>'
будет отображаться как строковое содержимое, но что, если вы действительно хотите отобразить h1 как dom?
Здесь мы используем<div dangerouslySetInnerHTML={{ __html: str }}></div>
, этот API очень длинный, правильно, мы его помечаем на контейнереdangerouslySetInnerHTML
~ опасно установить innerHTML
-
выполнить метод
function a() {
return <h3>hello function</h3>
}
let el = (
<div>
<div>{a()}</div>
</div>
)
страница:
- цикл
При добавлении ключа li лучше не использовать индекс массива.Чтобы пометить каждый элемент цикла для удобства dom-diff, обычно используется id.Поскольку пример относительно простой, мы используем индекс массива для заполнения ключа, используйте метод arr.map для обработки возврата массива
let arr = [1,2,3];
//
let el = (
arr.map((item, key) => (
<li key={key}>{item}</li>
))
)
- Несколько характеристик атрибутов html в jsx
-
class
→className
Этот случай верблюда заменяет нативный html-класс, но класс по-прежнему можно использовать, и скаффолдинг предложит вам использовать его здесь.className
-
for
→htmlFor
Это for — это for на метке html, которая используется для указания на ввод элемента управления.В jsx вместо этого мы используем htmlFor
<label htmlFor="username">用户名</label>
<input type="text" id="username" />
-
<div style="color:red">hello</div>
→<div style={{ color: 'red' }}>hello</div>
внешний{}
Указывает разметку синтаксиса js,{ color: 'red' }
является объектом -
React.Fragment
Если вы использовали vue, то должны знать, что html, возвращаемый vue, должен быть обернут корневым узлом, то есть возвращаемый dom должен быть одного, а не более одного уровня, то есть
<div>
<div></div>
<p></p>
</div>
То же самое, если мы вернем несколько одинаковых div:
реакция выдаст синтаксическую ошибку: jsx должен быть обернут закрывающим тегомНо что, если нам нужно использовать некоторые плоские элементы в определенной ситуации, например, по соображениям стиля, нам нечем обернуть div во внешний слой. В это время мы используем<React.Fragment>
чтобы обернуть элемент уровня, это<React.Fragment>
является спорным и действует как метка закрытия узла.
let el1 = (
<React.Fragment>
<div>{str1}</div>
<div>{a()}</div>
<div>{JSON.stringify(obj)}</div>
<div>{false?<span>你好</span>:void 0}</div>
</React.Fragment>
)
Так вы не получите ошибку
В общем, у React мало API, и писать jsx очень свободно. Метод js+xml позволяет разработчикам с глубокими навыками js произвольно писать логику js в html. Что пишешь, то и получаешь. Может быть, в этом прелесть реагировать.
3. Компоненты
В проекте реагирования в основном все структурные функции могут быть разделены на очень тонкие компоненты, такие как строка меню, обычно используемая на странице, которую можно разделить на: поле со списком Список, элемент списка ListItem, ссылка на список и т. д. преимущества этого:
1. Повторное использование 2. Удобное обслуживание 3. Повышение эффективности работы.
Способ, которым реакция объявляет компоненты, делится на объявление функции и объявление класса.
- функциональный декларативный компонент
Объявите компоненты функционально следующим образом
function Build(props) {
let {title,content} = props;
return (
<div>
<div>{title}</div>
<div>{content}</div>
</div>
)
}
render(<div>
<Build title="build1" content="content1"></Build>
<Build title="build2" content="content2"></Build>
<Build title="build3" content="content3"></Build>
</div>, window.root);
Если нам нужно только отображать некоторую информацию на странице и не нужно контролировать изменения, то функциональные компоненты могут быть легко реализованы
Определение компонента должно быть написано с заглавной буквы.Способ передачи значения функционального компонента состоит в том, чтобы определить имя атрибута в компоненте и написать его непосредственно на компоненте, когда компонент используется.<Build title="build3" content="content3"></Build>
1. недостаток функционального компонента не в этом 2. нет 3. жизненный цикл без сохранения состояния
Формула функции изменения времени может быть реализована с помощью компонентов значения таймера, например, в примере
function Clock(props) {
return <div> 时间更新:<span>{props.time}</span></div>
}
setInterval(()=>{
render(<Clock time={new Date().toLocaleString()} />, window.root);
},1000)
- объявление класса
Используйте es6 для создания класса для создания компонента, компонент, объявленный классом, имеет состояние, а представление обновляется через метод setState После этого все компоненты небольшого примера, который мы сделали, создаются путем объявления класса. научиться использовать
Управляемые компоненты и неуправляемые компоненты
Неконтролируемые компоненты: данные формы обрабатываются самой DOM. То есть он не контролируется setState(), аналогично традиционному вводу формы HTML, входное значение ввода отображает последнее значение (используйте ref, чтобы получить значение формы из DOM).
Контролируемые компоненты: в HTML теги<input>
,<textarea>
,<select>
Изменения значения обычно обновляются на основе пользовательского ввода. В React изменяемое состояние обычно хранится в свойстве состояния компонента и может быть обновлено только с помощью setState(), а компонент React, отображающий форму, также контролирует, что происходит в этой форме при последующем вводе пользователем, таким образом, React контролирует способ элемент формы ввода изменяет свое значение, называемое «управляемым компонентом».
Вот пишем небольшой пример неуправляемого компонента, вводимое значение отображается по клику, неуправляемые компоненты часто используются для манипулирования dom, что удобнее
import React,{Component} from 'react';
import {render} from 'react-dom';
class UnControl extends Component{
b=React.createRef();
handleClick = () =>{
alert(this.a.value); // 写法1
alert(this.b.current.value) // 写法2
}
render(){
return (<div>
<input type="text" id="username" ref={dom=>this.a=dom}/>
<input type="text" id="password" ref={this.b}/>
<button onClick={this.handleClick}>点击</button>
</div>)
}
}
render(<UnControl></UnControl>, window.root);
Далее мы реализуем небольшой пример, подобный этому:
Реализуйте компонент комментариев, аналогичный столбцу комментариев под самородками, мы разделим основные функции этого компонента на
корневой компонентApp
, компонент спискаList
, пункт спискаListItem
а такжеComment
Прокомментируйте компоненты, и во время реализации мы обсудим способ передачи данных между компонентами.
4. Как обновить вид
Во-первых, мы просто создаем приведенный выше пример, не разделяя компоненты.В структуре страницы используется загрузочный пользовательский интерфейс (npm install boostrap@3
) компоненты.
В этом примере мы используем axios(npm install axios
) для запроса исходных данных списка, инкапсулированных в виде request.js, код выглядит следующим образом:
import axios from 'axios';
axios.interceptors.response.use(function (res) {
if (res.data.code === 0) {
return res.data.users
} else {
return Promise.reject('错误');
}
})
export default axios
Запрошенный формат данных формулируется просто:
{
"code":0,
"users": [
{
"id": 1,
"avatar": "http://05.imgmini.eastday.com/mobile/20171112/20171112104845_40c4a989ba5a02f512b05336bff309f8_1.jpeg",
"username": "Jim",
"content": "Hi,你的文章很不错"
},
{
"id": 2,
"avatar": "http://05.imgmini.eastday.com/mobile/20171112/20171112104845_40c4a989ba5a02f512b05336bff309f8_1.jpeg",
"username": "Jim",
"content": "一般般的说"
}
]
}
Затем публикуем наш App.js, мы помещаем весь контент в App.js, не разделяя компоненты:
import React, { Component } from 'react';
import axios from './request'
import 'bootstrap/dist/css/bootstrap.css'
import './Common/common.css'
class App extends Component {
state = {
users: [],
count: 0,
id: 3
}
// 点赞功能
increment = () => {
this.setState({
count: this.state.count + 1
})
}
// 添加评论
addComment = (val) => {
let id = this.state.id;
let users = [...this.state.users, { avatar: "http://05.imgmini.eastday.com/mobile/20171112/20171112104845_40c4a989ba5a02f512b05336bff309f8_1.jpeg", content: val, username: 'Jim', id: id}];
this.setState({
users
});
this.state.id+=1;
}
content = React.createRef();
// 提交数据
handleSubmit = (e) => {
e.preventDefault();
this.addComment(this.content.current.value);
}
// 删除一条
removeById = (id) => {
let users = this.state.users.filter(user=>user.id!==id); // 排除列表里相同id的,即达到删除的目的
this.setState({
users
})
}
// 获取列表数据
async componentDidMount() {
let users = await axios.get('/users.json');
this.setState({
users
});
}
render() {
return (
<div className="container">
<div className="panel panel-danger">
<div className="panel-heading">
评论
</div>
<div className="panel-body">
{
this.state.users.map((user, index) => {
return (
<div className="media">
<div className="media-left">
<img className="avatar" src={user.avatar} />
</div>
<div className="media-right">
<h3>{user.username} </h3>
<div>评论:{user.content}</div>
<button className="btn btn-danger" onClick={(e)=>{
this.removeById(user.id)
}}>删除</button>
</div>
</div>
)
})
}
</div>
<div className="panel-bottom">
<form onSubmit={this.handleSubmit}>
<textarea className="form-control" required ref={this.content}></textarea>
<button type="submit" >评论</button>
</form>
</div>
</div>
</div>
);
}
}
export default App;
Эффект:
На данный момент функции, реализованные нашим кодом, включают добавление комментария или удаление комментария.В React представления управляются данными, которые мы изначально определили
state = {
users: [],
count: 0,
id: 3
}
состояниеusers
Данные будутcomponentDidMount
Когда жизненный цикл, получить список пользователей и передатьthis.setState({ users });
метод обновления представления. другие операции, аналогичныеhandleSubmit
а такжеremoveById
Также при эксплуатацииstate.users
данные для достижения цели добавления и удаления.
5. Разделить компоненты
Учитывая сложность проекта, мы можем разделить соответствующий контент в приведенном выше App.js на: компоненты спискаList
, пункт спискаListItem
а такжеComment
Комментируйте компоненты, чтобы нам не пришлось снова переписывать один и тот же код при построении других структур. Создаем новый в папке srccomponents
папку и создатьList.js
ListItem.js
Comment.js
- Компонент элемента списка:
import React, { Component } from 'react'
export default class ListItem extends Component {
state = {
users: [],
id: 100000
}
addComment = (val) => {
let id = this.state.id;
let users = [...this.state.users, { avatar: "http://05.imgmini.eastday.com/mobile/20171112/20171112104845_40c4a989ba5a02f512b05336bff309f8_1.jpeg", content: val, username: 'Jim', id: id}];
this.setState({
users
});
this.state.id+=1;
}
handleClick = (id) => {
this.props.removeById(id);
}
removeById = (id) => {
let users = this.state.users.filter(user=>user.id!==id); // 排除列表里相同id的,即达到删除的目的
this.setState({
users
})
}
render() {
let {id, avatar, content, username} = this.props;
return (
<div className="media">
<div className="media-left">
<img className="avatar" src={avatar} />
</div>
<div className="media-right">
<h3>{username} {id}</h3>
<div>评论:{content}</div>
<button className="btn btn-danger" onClick={(e)=>{
this.handleClick(id)
}}>删除</button>
</div>
</div>
)
}
}
- Компонент списка
import React, { Component } from 'react'
import ListItem from './ListItem'
export default class List extends Component {
static props = {
showComment: true
}
render() {
return (
<div>
{
this.props.users.map((user, index) => {
return (
<ListItem showComment={this.props.showComment} {...user} key={index} removeById={this.props.removeById} addComment={this.props.addComment}></ListItem>
)
})
}
</div>
)
}
}
- Компонент окна комментария
import React, { Component } from 'react'
export default class Comment extends Component {
content = React.createRef();
handleSubmit = (e) => {
e.preventDefault();
this.props.addComment(this.content.current.value);
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<textarea className="form-control" required ref={this.content}></textarea>
<button type="submit" >评论</button>
</form>
)
}
}
- App.js становится
import React, { Component } from 'react';
import axios from './request'
import 'bootstrap/dist/css/bootstrap.css'
import './Common/common.css'
import Comment from './components/Comment'
import List from './components/List'
import {Provider} from './context'
class App extends Component {
state = {
users: [],
count: 0,
id: 3
}
increment = () => {
this.setState({
count: this.state.count + 1
})
}
addComment = (val) => {
let id = this.state.id;
let users = [...this.state.users, { avatar: "http://05.imgmini.eastday.com/mobile/20171112/20171112104845_40c4a989ba5a02f512b05336bff309f8_1.jpeg", content: val, username: 'Jim', id: id}];
this.setState({
users
});
this.state.id+=1;
}
removeById = (id) => {
console.log(id)
let users = this.state.users.filter(user=>user.id!==id); // 排除列表里相同id的,即达到删除的目的
this.setState({
users
})
}
async componentDidMount() {
let users = await axios.get('/users.json');
this.setState({
users
});
}
render() {
return (
<Provider value={{increment: this.increment}}>
<div className="container">
<div className="panel panel-danger">
<div className="panel-heading">
评论
</div>
<div className="panel-body">
<List users={this.state.users} showComment={true} removeById={this.removeById} addComment={this.addComment}></List>
</div>
<div className="panel-bottom">
<br/>
<Comment addComment={this.addComment}></Comment>
获得的赞数量{this.state.count}
</div>
</div>
</div>
</Provider>
);
}
}
export default App;
Видя это, должны быть сомнения, то, что мы определили раньшеusers
данные,removeById
а такжеaddComment
метод, как использовать его на компонентах? Ниже мы объясним.
6. Перенос атрибутов между компонентами
- Способ взаимодействия данных компонента — это передача свойства, передача значения свойства или метода.
- Дочерние компоненты не могут напрямую изменять значения свойств
- Но вы можете изменить значение свойства с помощью вызова метода, переданного из родительского компонента.
- Передача данных является односторонней: родительский -> дочерний, что часто называют потоком данных с одним элементом.
- Метод получения свойств дочерними компонентами: `this.props.fn
- можно использовать
contextApi
Реализовать кросс-компонентную доставку
В компонентах, которые мы разделили в предыдущем разделе, исходный источник данных тела цикла в компоненте списка представлен какthis.state.users
изменено на использованиеthis.props.users
, и путь, пройденный в App.js,
<List users={this.state.users} showComment={true} removeById={this.removeById} addComment={this.addComment}></List>
Существует однозначное соответствие между входящим и исходящим.
Точно так же, посколькуListItem
компоненты потребностиremoveById
метод, поэтому начнем сApp.js
изList
Компонент поступаетremoveById
,существуетList
компонент называетсяListItem
, пройти еще разListItem
, это процесс от отца к сыну, от сына к внукам:
<ListItem showComment={this.props.showComment} {...user} key={index} removeById={this.props.removeById} addComment={this.props.addComment}></ListItem>
существуетListItem
компонент, у нас естьremoveById
метод в другом слое
handleClick = (id) => {
this.props.removeById(id);
}
...
<button className="btn btn-danger" onClick={(e)=>{
this.removeById(user.id)
}}>删除</button>
Здесь наш метод удаления исходит из метода, переданного от корневого компонента.После получения дочернего компонента он также передается.users
Внесите изменения для достижения цели изменения данных. Выше приведено объяснение передачи простого компонента по значению.
contextApi
Если мы хотим добавить в этот список похожую функцию, то есть любой компонент списка может понравиться, и может быть собрано общее количество лайков, В это время, если мы используем родительские-дочерние компоненты для передачи значений, код может быть более проблематичным для реализации или подверженным ошибкам, поскольку задействовано так много слоев. Поэтому мы используемcontextApiдостичь (реагировать16.3).
Способ введения (в примере я извлек это введение в context.js, поэтому мне не нужно писать деконструкцию на каждой странице):
import React from 'react'
let {Provider, Consumer} = React.createContext();
export {Provider, Consumer}
Метод, используемый в компоненте, заключается в использовании возвращаемого значения родительского компонента после того, как родительский компонент введен.Provider
упаковать и передатьvalue
Атрибуты:
import React, { Component } from 'react';
import {Provider} from './context'
class App extends Component {
state = {
users: [],
count: 0,
id: 3
}
// 点赞功能
increment = () => {
this.setState({
count: this.state.count + 1
})
}
render() {
return (
<Provider value={{increment: this.increment}}>
<div className="container">
<div className="panel panel-danger">
<div className="panel-heading">
评论
</div>
<div className="panel-body">
<List users={this.state.users} showComment={true} removeById={this.removeById} addComment={this.addComment}></List>
</div>
<div className="panel-bottom">
<br/>
<Comment addComment={this.addComment}></Comment>
获得的赞数量{this.state.count}
</div>
</div>
</div>
</Provider>
);
}
}
export default App;
В дочерних компонентах вам необходимо использовать (использовать) внешнюю оболочку возвращаемого значения.Consumer
, переданный с помощью стрелочной функцииvalue
ценность, то естьProvider
Входящие свойства, вы можете напрямую вызывать входящие свойства родительского компонента или компонентов более высокого порядка в компоненте.
import React, { Component } from 'react'
import {Consumer} from '../context'
...
export default class ListItem extends Component {
...
render() {
let {id, avatar, content, username} = this.props;
return (
<Consumer>
{(value)=>{
return <div className="media">
<div className="media-right">
...
<button className="btn btn-primary" onClick={()=>{
value.increment()
}}>赞</button>
...
</div>
</div>
}}
</Consumer>
)
}
}
Суммировать
Вышеприведенное является небольшим резюме моего введения в React, и я написал незрелый пример, чтобы потренировать свои руки. Пожалуйста, простите меня, если в выражении могут быть какие-то скачки. Код Github этого небольшого примера прилагается здесь Студенты, которым нужно узнать больше об этом, могут посмотреть:code.
Надеюсь, моя статья сможет вам помочь.