Create by jsliang on 2019-3-18 08:37:10
Recently revised in 2019-3-22 11:46:54
Привет друзья, если вы считаете, что эта статья неплохая, не забудьте датьstar, друзья моиstarЭто моя мотивация продолжать обновлять!Адрес GitHub
【2019-08-16】Привет друзья, потому чтоjsliangБиблиотека документации подверглась рефакторингу, некоторые ссылки в этой статье могут быть неработоспособны, иjsliangИзвините за отсутствие сил поддерживать старые статьи на стороне Наггетс. Для тех, кому нужно получать последние статьи, щелкните адрес GitHub выше и перейдите в библиотеку документов, чтобы просмотреть скорректированные статьи.
каталог
Чем отличается передок без закидывания от соленой рыбы?
2 Предисловие
Ознакомьтесь с процессом разработки React, написав простую демонстрацию TodoList.
три текста
Теперь приступайте к делу.
3.1 Создайте новый проект React
- Скачать Node.js
- Установите леса React:
npm i create-react-app -g
- Начать новый проект:
create-react-app todolist
cd todolist
npm start
- Открыть
localhost:3000
Просмотр страницы
3.2 Разрешение каталога проекта
- todolist
+ node_modules —————————— 项目依赖的第三方的包
- public ———————————————— 共用文件
- favicon.ico —— 网页标签左上角小图标
- index.html —— 网站首页模板
- mainfest.json —— 提供 meta 信息给项目,并与 serviceWorker.js 相呼应,进行离线 APP 定义
- src ——————————————————— 项目主要目录
- App.css —— 主组件样式
- App.js —— 主组件入口
- App.test.js —— 自动化测试文件
- index.css —— 全局 css 文件
- index.js —— 所有代码的入口
- logo.svg —— 页面的动态图
- serviceWorker.js —— PWA。帮助开发手机 APP 应用,具有缓存作用
- .gitignore ——————————— 配置文件。git 上传的时候忽略哪些文件
- package-lock.json ———— 锁定安装包的版本号,保证其他人在 npm i 的时候使用一致的 node 包
- package.json ————————— node 包文件,介绍项目以及说明一些依赖包等
- README.md ———————————— 项目介绍文件
3.3 Оптимизированная структура проекта
Для облегчения разработки исходный каталог create-react-app упрощен ниже:
- todolist
+ node_modules —————————— 项目依赖的第三方的包
- public ———————————————— 共用文件
- favicon.ico —— 网页标签左上角小图标
- index.html —— 网站首页模板
- src ——————————————————— 重要的目录
- App.js —— 主组件入口
- index.js —— 所有代码的入口
- .gitignore ——————————— 配置文件。git 上传的时候忽略哪些文件
- package.json ————————— node 包文件,介绍项目以及说明一些依赖包等
- README.md ———————————— 项目介绍文件
favicon.ico
,.gitignore
,README.md
Нам не нужно заботиться об этом, но для других файлов нам нужно упростить их код:
- index.html
Сведения о коде
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<title>Todolist</title>
</head>
<body>
<noscript>你需要允许在 APP 中运行 JavaScript</noscript>
<div id="root"></div>
</body>
</html>
- App.js
Сведения о коде
import React, { Component } from 'react';
class App extends Component {
render() {
return (
<div className="App">
Hello React!
</div>
);
}
}
export default App;
- index.js
Сведения о коде
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));
- package.json
Сведения о коде
{
"name": "todolist",
"version": "0.1.0",
"private": true,
"dependencies": {
"react": "^16.8.4",
"react-dom": "^16.8.4",
"react-scripts": "2.1.8"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
]
}
3.4 Предварительная разведка компонентов
Как и на картинке выше, при разработке страниц мы можем легко использовать навыки приготовления и распутывания коров, чтобы разделить страницы, а затем строить страницы по частям.
Чтобы дать более официальное заявление, это называется компонентизацией страницы: страница разрезается на несколько частей, что способствует сборке страницы и обслуживанию кода.
В стандартной конфигурации create-react-app App.js является компонентом, давайте посмотрим:
App.js
// 1. 引用 React 及其组件
import React, { Component } from 'react';
// 2. 定义一个叫 App 的组件继承于 Component
class App extends Component {
render() {
return (
<div className="App">
Hello React!
</div>
);
}
}
// 3. 根据 React 实例,在 App 内部编写完毕后,导出这个 App 组件
export default App;
Выше мы сослались, определили и экспортировали компонент приложения, а затем собираемся его использовать:
index.js
// 1. 引入 React、ReactDOM
import React from 'react';
import ReactDOM from 'react-dom';
// 2. 将 App.js 导入进来
import App from './App';
// 3. 通过 ReactDOM 将 App.js 以虚拟 DOM 的形式渲染/挂载到 root 根节点,该节点在 index.html 中
ReactDOM.render(<App />, document.getElementById('root'));
index.js
Сообщите нам, что он смонтирует компонент App.js в ReactDom через ReactDom.root
на этом узле, то этоroot
Где это находится? Давайте посмотрим на index.html:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="shortc ut icon" href="%PUBLIC_URL%/favicon.ico" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<title>Todolist</title>
</head>
<body>
<noscript>你需要允许在 APP 中运行 JavaScript</noscript>
<div id="root"></div>
</body>
</html>
Хорошо, нам легко понять идею: мы определяем индекс в index.htmlroot
Корневой узел, а затем мы визуализируем App.js как компонент к index.html через index.js, таким образом реализуя монтирование узла.
Дивергентное мышление: мы знаем, что окончательная комбинация index.js и App.js должна монтироваться на
id="root"
На узле, если мы откроем еще один index2.js и App2.js, смонтируем его вid="root2"
На узле будет работать? Или мы можем открыть одинid="root3"
node, где мы работаем с jQuery, это тоже возможно?
3.5 JSX
В файле create-реагировать-приложение, будь то в index.js:
ReactDOM.render(<App />, document.getElementById('root'));
Или в App.js:
class App extends React.Component {
render() {
return (
<div className="App">
Hello React!
</div>
);
}
}
Для рендеринга этих DOM требуется JSX, поэтому необходимо представить React:
import React from 'react';
- Определение JSX:
Итак, что такое JSX?
Одним из основных механизмов React является возможность создавать виртуальные элементы DOM в памяти. React использует виртуальный DOM для повышения производительности за счет сокращения манипуляций с реальным DOM.
JSX — это формат, сочетающий в себе JavaScript и XML.
React изобрел JSX, который использует синтаксис HTML для создания виртуального DOM. при встрече<
, JSX используется для парсинга HTML, встречая{
Так же, как парсинг JavaScript.
- Использование JSX:
В синтаксисе JSX, если нам нужно использовать компонент, созданный нами, мы можем напрямую использовать его имя определения, например:
index.js
// 1. 引入 React、ReactDOM
import React from 'react';
import ReactDOM from 'react-dom';
// 2. 将 App.js 导入进来
import App from './App';
// 3. 通过 ReactDOM 将 App.js 以虚拟 DOM 的形式渲染/挂载到 root 根节点,该节点在 index.html 中
ReactDOM.render(<App />, document.getElementById('root'));
Третий момент заключается в том, что пользовательский компонент отображается в корневом узле.
Совет: в React, если вам нужно использовать пользовательский компонент, компонент не должен начинаться с нижнего регистра.
app, вместо этого используйтеApp
Такая заглавная начальная форма.
3.6 События и двусторонняя привязка данных
Вот наша сокращенная структура каталогов:
Изменяем структуру каталогов и начинаем писать TodoList:
первый, мы меняем App.js на TodoList.js:
App.jsTodoList.js
import React, { Component } from 'react';
class TodoList extends Component {
render() {
return (
<div className="TodoList">
Hello React!
</div>
);
}
}
export default TodoList;
потом, мы изменяем компонент, подключенный к index.html в index.js, на TodoList:
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import TodoList from './TodoList';
// 3. 通过 ReactDOM 将 App.js 以虚拟 DOM 的形式渲染/挂载到 root 根节点,该节点在 index.html 中
ReactDOM.render(<TodoList />, document.getElementById('root'));
После модификации друзья могут перезапустить порт 3000, чтобы посмотреть, сможет ли наш React нормально запуститься.
На этом шаге мы просто изменим App.js на TodoList.js, чтобы index.js был подключен к
root
является TodoList.js, и больше ничего не делается.
наконец, если проблем нет, то далее пишем TodoList, получаем значение поля ввода и рендерим в список:
TodoList.js
Сведения о коде
// Fragment 是一种占位符形式,类似于 Vue 的 Template
import React, { Component, Fragment } from 'react';
class TodoList extends Component {
constructor(props) {
super(props);
this.state = {
inputValue: '',
list: []
}
}
render() {
return (
<Fragment>
<div>
{/* 单项数据绑定 */}
<input
type="text"
value={this.state.inputValue}
onChange={this.handleInputChange.bind(this)}
/>
<button>提交</button>
</div>
<ul>
<li>
<span>吃饭</span>
<span>X</span>
</li>
<li>
<span>睡觉</span>
<span>X</span>
</li>
<li>
<span>打豆豆</span>
<span>X</span>
</li>
</ul>
</Fragment>
)
}
handleInputChange(e) {
console.log(e.target.value);
this.setState({
inputValue: e.target.value
})
}
}
export default TodoList;
Давайте сначала проверим демо:
Хорошо, чтобы каждый раз, когда мы вводим символ, мы могли сразу получить соответствующие данные.В это время реализован односторонний поток данных: поле ввода -> JS-память.
Есть 3 балла, чтобы объяснить:
-
Fragment
это заполнитель, предоставленный React, который выглядит как<input>
,<span>
То же, что и метка, но не появляется при фактическом рендеринге. Поскольку первый уровень JSX React должен иметь теги, то, если вы используете<div>
и т. д. будет занимать уровень, поэтому, подобно VueTemplate
, который использует ReactFragment
Этот пустой ярлык. -
constructor
Представляет конструктор родительского класса, в ES6 конструкторconstructor
Эквивалентен его конструктору, используемому для создания нового родительского класса.this
объект иsuper(props)
используется для исправленияthis
указал на. Короче говоря, здесь мы можем определить данные и использовать их во всем файле js. -
onChange
Этот метод записи — это метод записи, указанный React, напримерonClick
и т. д., в нативном JS, используяonclick
, а в React, чтобы различать, нужно писать название события в полуверблюжьем регистре. В то же время связанныйhandleInputChange
, что может быть непосредственноrender
Пишите ниже.
использованная литература:«Что такое конструктор() и супер() в реакции? 》
Таким образом, у нас есть предварительное представление о данных и событиях React.Давайте добавим кнопку и нажмите, чтобы добавить событие списка и нажмитеX
Удалить событие списка.
TodoList.js
Сведения о коде
// Fragment 是一种占位符形式,类似于 Vue 的 Template
import React, { Component, Fragment } from 'react';
class TodoList extends Component {
// 构造函数
constructor(props) {
super(props);
// 定义数据
this.state = {
inputValue: '',
list: []
}
}
// 渲染页面
render() {
let closeStyle = {
fontSize: '1.2em',
color: 'deepskyblue',
marginLeft: '10px'
}
return (
<Fragment>
<div>
{/* 单项数据绑定 */}
{/* 在 React 中,绑定时间的,一般为半驼峰形式 */}
<input
type="text"
value={this.state.inputValue}
onChange={this.handleInputChange.bind(this)}
/>
<button onClick={this.handleBtnClick.bind(this)}>提交</button>
</div>
<ul>
{
this.state.list.map( (item, index) => {
return <li key={index}>
<span>{index}. {item}</span>
<span style={closeStyle} onClick={this.handleItemDelete.bind(this, index)}>X</span>
</li>
})
}
</ul>
</Fragment>
)
}
// 方法体 - 输入内容
handleInputChange(e) {
this.setState({
inputValue: e.target.value
})
}
// 方法体 - 点击提交
handleBtnClick() {
this.setState({
list: [...this.state.list, this.state.inputValue],
inputValue: ''
})
}
// 方法体 - 删除项目
handleItemDelete(index) {
const list = [...this.state.list];
list.splice(index, 1);
this.setState({
list: list
})
}
}
export default TodoList;
В этой части нам нужно понять 3 точки знаний:
- существует
render
серединаcloseStyle
Эту переменную мы используем для определения свойств CSS, а затем передаемstyle={closeStyle}
, напрямую написал встроенный стиль (мы извлечем его ниже) - О обходе JSX вывода формы:
{
this.state.list.map( (item, index) => {
return <li key={index}>
<span>{index}. {item}</span>
<span style={closeStyle} onClick={this.handleItemDelete.bind(this, index)}>X</span>
</li>
})
}
мы проходим{}
Внутренние узлы вывода DOM цикла. Если вы изучили jQuery, вы можете представить его как составную строку; если вы изучили Vue, вы можете представить его какv-for
Изменена орфография.
Здесь нам не нужно беспокоиться о том, почему это написано именно так, давайте сначала примем этот способ написания.
- об изменении
constructor
В данных мы используем:
this.setState({
list: list
})
эта форма. На самом деле это тоже навык памяти.Вы должны знать, что когда мы определяем данные, мы используем:
// 定义数据
this.state = {
inputValue: '',
list: []
}
который:this.state
, то нам нужно изменить данные, т.е.this.setState
.
На данный момент наш простой TodoList реализован, давайте дальше оптимизировать и дополнительно извлекать CSS и JS.
3.7 Оптимизация — извлечение CSS
Выше мы упоминалиcloseStyle
является встроенным письмом, какидеальный программист, надо не терпеть, начнем отрываться:
TodoList.js
import React, { Component, Fragment } from 'react';
import './style.css'
// ... 省略中间代码
<ul>
{
this.state.list.map( (item, index) => {
return <li key={index}>
<span>{index}. {item}</span>
<span className="icon-close" onClick={this.handleItemDelete.bind(this, index)}>X</span>
</li>
})
}
</ul>
Здесь нам нужно знать: мы можем пройтиimport
форма, непосредственно импортировать файл CSS напрямую, а затем, мы называемclass
, потому что React боится JSclass
с HTMLclass
конфликт, поэтому нам нужно использоватьclassName
.
Наконец, давайте напишем файл CSS:
.icon-close {
font-size: 1.2em;
color: deepskyblue;
margin-left: 10px;
}
Таким образом, мы добились извлечения CSS.
3.8 Оптимизация — извлечение JS
Во введении к компонентам в главе 4 мы упомянули, что некоторые сложные JS можно извлечь и встроить в то место, где их нужно разместить в виде компонентов.
Итак, когда мы пишем все больше и больше JSX, можем ли мы выделить часть рендеринга списка, чтобы упростить JSX?
Ответ положительный, давайте посмотрим на реализацию:
TodoList.js
Сведения о коде
// Fragment 是一种占位符形式,类似于 Vue 的 Template
import React, { Component, Fragment } from 'react';
// 引入组件
import TodoItem from './TodoItem';
// 引用样式
import './style.css';
class TodoList extends Component {
// 构造函数
constructor(props) {
super(props);
// 定义数据
this.state = {
inputValue: '',
list: []
}
this.handleInputChange = this.handleInputChange.bind(this);
this.handleBtnClick = this.handleBtnClick.bind(this);
this.handleItemDelete = this.handleItemDelete.bind(this);
}
// 渲染页面
render() {
return (
<Fragment>
<div>
<label htmlFor="insertArea">输入内容:</label>
{/* 单项数据绑定 */}
{/* 在 React 中,绑定时间的,一般为半驼峰形式 */}
<input
id="insertArea"
type="text"
value={this.state.inputValue}
onChange={this.handleInputChange}
/>
<button onClick={this.handleBtnClick}>提交</button>
</div>
<ul>
{/* 精简 JSX,将部分抽取出来 */}
{ this.getTodoItem() }
</ul>
</Fragment>
)
}
// 获取单独项
getTodoItem() {
return this.state.list.map( (item, index) => {
return (
<TodoItem
key={index}
item={item}
index={index}
handleItemDelete={this.handleItemDelete}
/>
)
})
}
// 方法体 - 输入内容
handleInputChange(e) {
const value = e.target.value;
this.setState( () => ({
inputValue: value
}))
}
// 方法体 - 点击提交
handleBtnClick() {
const list = this.state.list,
inputValue = this.state.inputValue;
this.setState( () => ({
list: [...list, inputValue],
inputValue: ''
}))
}
// 方法体 - 删除项目
handleItemDelete(index) {
// immutable - state 不允许做任何改变
const list = [...this.state.list];
list.splice(index, 1);
this.setState( () => ({
list: list
}))
}
}
export default TodoList;
Давайте сосредоточимся на изменениях в TodoList.js:
- мы в
constructor
, метод определен заранее:
this.handleInputChange = this.handleInputChange.bind(this);
Таким образом, нам не нужно писать ниже.bind(this)
форма.
- Мы изменили
this.setState()
форма:
Оригинальное написание:
this.setState({
list: list
})
Пишу сейчас:
this.setState( () => ({
list: list
}))
Поскольку версия React 16 была обновлена, использование этого способа записи лучше, чем предыдущего.Что касается хорошего, нас это не волнует в первую очередь, и мы будем использовать этот способ записи в будущем.
- Мы ссылались на компонент:
import TodoItem from './TodoItem';
И поместите компонент в тело метода:this.getTodoItem()
в, покаthis.getTodoItem()
Определение:
// 获取单独项
getTodoItem() {
return this.state.list.map( (item, index) => {
return (
<TodoItem
key={index}
item={item}
index={index}
handleItemDelete={this.handleItemDelete}
/>
)
})
}
Здесь мы видим, что мы передаем данные в виде пользовательских значений.key
,item
,index
передается дочерним компонентамTodoItem
. В то же время черезhandleItemDelete
, передать собственный метод дочернему компоненту, чтобы дочерний компонент мог вызвать метод родительского компонента:
TodoItem.js
Сведения о коде
import React, { Component } from 'react'
class TodoItem extends Component {
constructor(props) {
super(props);
// 这种写法可以节省性能
this.handleClick = this.handleClick.bind(this);
}
render() {
const { item } = this.props;
return (
<li>
<span>{item}</span>
<span className="icon-close" onClick={this.handleClick}>X</span>
</li>
)
}
handleClick() {
const { handleItemDelete, index } = this.props;
handleItemDelete(index);
}
}
export default TodoItem;
Таким образом, мы завершили извлечение компонентов и узнали
- Родительский компонент передает значение дочернему компоненту
- Дочерний компонент вызывает метод родительского компонента
Исходя из этого, мы можем писать более богатые и надежные проекты в будущем.
Кодовый адрес этой статьи:Адрес источника серии React
Четыре резюме
На любом языке, который мы изучаем, большинство из них нужно начинать с программирования «Hello World!»~
Затем, когда мы занимаемся небольшими делами, нам всем нравится иметь TodoList, потому что он может прояснить некоторые основные моменты знаний.
Теперь давайте рассмотрим, что мы получили от разработки React TodoList:
- Установка и разработка create-react-app.
- Идея компонентизации и применение компонентизации в Create-React-App.
- React определяет и использует данные и методы, а также то, как выполнить двустороннюю привязку данных.
- Разделите большие компоненты на маленькие компоненты и реализуйте взаимодействие между родительскими и дочерними компонентами (родительские компоненты передают параметры дочерним компонентам, а дочерние компоненты вызывают методы родительских компонентов).
Слишком далеко,jsliangЯ хорошо разбираюсь в jQuery, Vue, React, чтобы писать TodoList, ха-ха!
5 ссылок
- «React.Component и React.PureComponent (оптимизация производительности React)»
- "Код Visual Studio + построение среды разработки React"
- «Что такое конструктор() и супер() в реакции? 》
jsliangРекламный толчок:
Может быть, друг хочет узнать об облачных серверах
Или друг хочет купить облачный сервер
Или маленькому партнеру необходимо обновить облачный сервер
Добро пожаловать, чтобы нажатьПродвижение облачного сервераПроверить!
библиотека документации jsliangЗависит отЛян ЦзюньронгиспользоватьCreative Commons Attribution-NonCommercial-ShareAlike 4.0 Международная лицензияЛицензия.
на основеGitHub.com/l ian Jun Ron…Создание работ выше.
Права на использование, отличные от разрешенных в настоящем Лицензионном соглашении, могут быть получены отCreative Commons.org/licenses/не…получено в.