1. Introdução
Componentes e tecnologias de reutilização são ferramentas necessárias para a criação de aplicativos em grande escala.Estruturas como Vue e Reactjs suportam muito bem o desenvolvimento de componentes. Este capítulo se concentra no aprendizado da componenteização do Reactjs. A seguir, é apresentada uma demonstração da página de pesquisa:
Segundo, o método de embalagem do componente
Os componentes do Vue usam o método Vue.component () para criar componentes globais.Para Reactjs, existem duas maneiras:
1. Modo de função
Este modo é para definir um componente através da função js, e também é o modo mais simples. Por exemplo, o método App definido no App.js da demonstração padrão.
function App() {
return (
<div className="App">
<header className="App-header">
...
</header>
</div>
);
}
Este método retorna o elemento React (uma parte do código JSX).
2. Modo de classe
Este modelo usa componentes de definição de classe ES6, reescrevemos o exemplo acima:
class App extends React.Component {
render(){
return (
<div className="App">
<header className="App-header">
...
</header>
</div>
);
}
};
Comparado aos componentes funcionais, o primeiro é uma classe pai que herda React.Component, que define o método render (), e o segmento de código de retorno é agrupado no método render (). Para distinguir os componentes padrão do W3C, a primeira letra do componente personalizado do Reactjs precisa ser maiúscula.
Os dois padrões de componentes são equivalentes no React. Recomendamos a criação do padrão de classe aqui.Os componentes criados são algumas instâncias.O padrão de classe possui alguns recursos adicionais, como estado e ciclo de vida.
Abaixo, uso o modelo de classe para criar um componente de demonstração. Do ponto de vista da composição da página, ele é dividido em três subcomponentes, o componente SearchBox da barra de pesquisa, o componente SearchHot da barra de pesquisa ativa e o componente SearchList do resultado da pesquisa.Estes subcomponentes estão incluídos no componente pai App.
Crie um novo SearchBox.js, crie um componente SearchBox e exporte-o.
import React from 'react';
class SearchBox extends React.Component{
render(){
return(
<div style={{width:300}}>
<input type="text"></input> <button>搜索</button>
</div>
)
}
}
export default SearchBox
Crie um novo SearchList.js e crie um componente SearchList.
import React from 'react';
import './SearchList.css';
class SearchList extends React.Component{
render(){
return(
<div className="d">
<div className="s">搜索结果:</div>
<ul className="u">
</ul>
</div>
)
}
};
export default SearchList;
Crie um novo SearchHot.js e crie componentes SearcHot.
import React from 'react';
import './SearchHot.css';
class SearchHot extends React.Component{
render(){
return (
<div className="d">
<div className="s">大家都在搜:</div>
<ul className="su">
</ul>
</div>
)
}
}
export default SearchHot;
O código App.js é o seguinte, primeiro importe os componentes SearchList, SearchBox, SearchHot e, em seguida, chame e torne semelhante às tags nativas.
import React from 'react';
import logo from './logo.svg';
import './App.css';
//导入两个组件
import SearchList from './SearchList.js';
import SearchBox from './SearchBox.js';
import SearchHot from './SearchHot.js'
class App extends React.Component {
render(){
return (
<div className="App">
{/* 引入组件 */}
<SearchBox />
<SearchHot />
<SearchList />
</div>
);
}
};
export default App;
O efeito final é o seguinte:
Apenas o esboço do quadro de demonstração é desenhado aqui.A seguir, adicionaremos dados e respostas relevantes.
Três estado
O estado pode ser considerado como a máquina de estado do Reactjs, que salva os dados e variáveis relevantes do componente.O escopo do estado é apenas dentro do componente , que pode ser comparado aos dados do Vue. Estamos no módulo "todos estão pesquisando", usando o estado para construir um conjunto de dados de pesquisa quentes e renderizá-los.
1. Inicialize estado
Deve-se observar que apenas os componentes do modo de classe suportam o estado.Em primeiro lugar, adicionamos uma função construtora ao componente SearchHot e inicializamos o objeto de estado.
constructor(props){
// 1、调用父类构造方法
super(props);
//2、初始化state对象
this.state = {hotItem:['口罩','手套','酒精']}
}
O parâmetro de entrada desse método de construção é props, que pode ser usado para transferir dados entre componentes pai e filho.Explicaremos em detalhes na próxima seção.
1. Chame o super método para implementar a chamada do construtor da classe pai (React.Component).
2. Inicialize o objeto state.Para simplificar o processo, escreveremos temporariamente dados mortos.
Em seguida, renderizaremos os dados do estado na área da página, definiremos o objeto hostList, obteremos os dados do estado e reuniremos a lista li (descreveremos a lista cuidadosamente nos próximos capítulos e a ignoraremos por enquanto).
const hotList = this.state.hotItem.map((value)=>
(
<li key={value.toString()}>
{value}
</li>
)
)
Introduza esta expressão de objeto em JSX.
return (
<div className="d">
<div className="s">大家都在搜:</div>
<ul className="su">
{/*引用变量表达式 */}
{hotList}
</ul>
</div>
)
O código completo é o seguinte:
import React from 'react';
import './SearchHot.css';
class SearchHot extends React.Component{
constructor(props){
super(props);
this.state = {hotItem:['口罩','手套','酒精']}
}
render(){
const hotList = this.state.hotItem.map((value)=>
(
<li key={value.toString()}>
{value}
</li>
)
)
return (
<div className="d">
<div className="s">大家都在搜:</div>
<ul className="su">
{hotList}
</ul>
</div>
)
}
}
export default SearchHot;
O efeito é o seguinte:
2. Estado da atualização
Vue e Reactjs como modo MVVM, atualização e renderização DOM orientada a dados. No Vue, sabemos que, ao monitorar alterações nos dados, o algoritmo diff do VDOM, que eventualmente mapeia para atualizações DOM reais. No Reactjs, o processo é semelhante, vamos ver como alcançá-lo.
Em "Todos estão pesquisando", adicionamos a função "próximo lote", quando clicada, a matriz hotList é atualizada e o DOM da página também é atualizado com o tempo. O efeito é o seguinte:
Adicione um botão de tag no JSX. Quando clicado, chame o método changeHot (foque nos eventos reactjs, que serão introduzidos nos próximos capítulos).
<div className="s">大家都在搜:<a href="#" onClick={this.changeHot} style={{marginLeft:100}}>下一批</a></div>
Atualize os dados hotList no método changeHot.
changeHot(){
this.setState({hotItem:['电视','手机','电脑','平板']})
}
Deve-se observar aqui que você precisa chamar o método setState para atualizar; não é possível atribuir diretamente um valor ao estado this.state = {hotItem: ['TV', 'celular', 'computador', 'tablet']} não terá efeito. Isso é diferente do vue, que pode definir propriedades diretamente.
Nesse ponto, todos clicam no botão "Próximo lote" e encontram um erro.
SetState não está definido, o que diabos é isso, porque o método de retorno de chamada não está vinculado a esse objeto e o 'this' em changeHot está indefinido no momento. Existem duas maneiras de resolvê-lo.
O primeiro método é vincular isso no construtor
constructor(props){
// 1、调用父类构造方法
super(props);
//2、初始化state对象
this.state = {hotItem:['口罩','手套','酒精',]};
//绑定this
this.changeHot = this.changeHot.bind(this);
}
O segundo método transforma changeHot em uma função de seta, sabemos que essa função aponta para o objeto de função.
changeHot = () =>this.setState({hotItem:['电视','手机','电脑','平板']});
Neste ponto, clique em "Próximo lote", você pode ver a atualização da página.
Vamos fazer outro experimento: depois de chamar setSate para definir o hotItem, o valor será impresso imediatamente.
changeHot(){
this.setState({hotItem:['电视','手机','电脑','平板']
})
console.log(this.state.hotItem)
}
O resultado é o seguinte:
Não atualizado, por quê? Isso ocorre porque setState é uma operação assíncrona (isso é diferente do vue, o vue atualiza o modelo de forma síncrona e atualiza a exibição de forma assíncrona. Se você estiver interessado, pode aprender sobre o mecanismo nexttick do vue), pode pensar nisso O objetivo de fazer isso, se for síncrono, cada atualização de estado causará imediatamente a atualização do DOM, a eficiência será muito baixa; se for assíncrona, você poderá executar operações em lote no estado definido, também poderá mesclar algumas operações, muito Melhore a eficiência. De fato, a atualização assíncrona da visão do vue também é a mesma, mas o mecanismo e o estágio dos dois são diferentes.
Como obter o valor atualizado, setState fornece um método para definir o retorno de chamada.
changeHot(){
this.setState({hotItem:['电视','手机','电脑','平板']
},()=>{
console.log(this.state.hotItem)
})
}
Dessa forma, o valor atualizado pode ser obtido corretamente.
O código completo é o seguinte:
import React from 'react';
import './SearchHot.css';
class SearchHot extends React.Component{
constructor(props){
// 1、调用父类构造方法
super(props);
//2、初始化state对象
this.state = {hotItem:['口罩','手套','酒精',]};
//绑定this
this.changeHot = this.changeHot.bind(this);
}
changeHot(){
this.setState({hotItem:['电视','手机','电脑','平板']
})
}
//箭头函数
//changeHot = () =>this.setState({hotItem:['电视','手机','电脑','平板']});
render(){
//1、定义变量,使用state对象数据,构造列表
const hotList = this.state.hotItem.map((value)=>
(<li key={value.toString()}>
{value}
</li>)
)
return (
<div className="d">
<div className="s">大家都在搜:<a href="#" onClick={this.changeHot} style={{marginLeft:100}}>下一批</a></div>
<ul className="su">
{/*引用变量表达式 */}
{hotList}
</ul>
</div>
)
}
}
export default SearchHot;
Quatro, adereços
Como mencionado acima, state é a máquina de estados dentro do componente e seu escopo também está dentro do componente. Para componentes, a interação entre componentes pai e filho, a transferência de dados é uma função básica, obviamente, o estado não tem a capacidade de atingir essa função.
Vamos revisar o processo de interação entre os componentes no Vue. O componente pai vincula a tag de propriedade a ser passada pelo v-bind e o componente filho recebe dados através da propriedade props; o componente filho chama a função do componente pai através do método emit para realizar o componente filho Transmissão de dados. O processo de Reactjs também é semelhante: mencionamos o parâmetro de entrada props no construtor de componentes na seção anterior.O componente pai passa os dados para o componente filho através dos props, e o componente filho chama o componente pai para implementar o upload de dados.
Abaixo, usamos o módulo de resultados da pesquisa para apresentar o fluxo de dados dos componentes pai e filho.O diagrama esquemático do processo é o seguinte:
1. O componente filho SearchBox é responsável por procurar a entrada de palavra-chave, salvá-la no estado e transmitir o valor de entrada searchVal para o aplicativo pai componente chamando de volta o método changeSearchVal do aplicativo pai componente.
2. Depois que o componente pai do aplicativo recebe o searchVal, ele consulta os resultados da pesquisa e salva os resultados no searchListVal do estado.
3. O componente pai App transmite o valor para o componente filho SearchList por meio de adereços, e o componente filho SearchList recebe o searchListVal passado e o renderiza.
Os dois componentes filhos, SearchBox e SearchList, não interagem diretamente, mas são processados e encaminhados por meio do aplicativo pai comum.
- Componente SearchBox
(1) A entrada onChange monitora o valor de entrada e liga o método handleChange.
<input type="text" style={{width:150}} onChange={this.handleChange}></input>
handleChange atualiza o valor de entrada para o searchVal no estado (também pode ser obtido pelo método ref de componentes não controlados, sobre o qual falaremos mais adiante)
//获取input输入的值,保存到state
handleChange(e){
this.setState({searchVal:e.target.value});
}
(2) O botão adiciona um evento ao clicar,
<button onClick={this.onSearchClick}>搜索</button>
Obtenha o valor searchVal no estado e passe-o para o componente pai chamando de volta o changeSearchVal do componente pai.
//回调changeSearchVal,将searchVal传递给父组件
onSearchClick(){
this.props.changeSearchVal(this.state.searchVal);
}
Vemos que this.props.changeSearchVal é usado, definido no componente pai App e passado para o componente filho SearchBox por meio de adereços (os adereços podem não apenas passar valores de propriedade, mas também funções).
O código completo do SearchBox.js:
import React from 'react';
class SearchBox extends React.Component{
constructor(props){
super(props);
this.state = {searchVal:""};
this.onSearchClick = this.onSearchClick.bind(this);
this.handleChange = this.handleChange.bind(this);
}
//1、获取input输入的值,保存到state
handleChange(e){
this.setState({searchVal:e.target.value});
}
//2、回调changeSearchVal,将searchVal传递给父组件
onSearchClick(){
this.props.changeSearchVal(this.state.searchVal);
}
render(){
return(
<div style={{width:300,margin:10}}>
<input type="text" style={{width:150}} onChange={this.handleChange}></input> <button onClick={this.onSearchClick}>搜索</button>
</div>
)
}
}
export default SearchBox
- Componentes do aplicativo
Como passar o método changeSearchVal para o subcomponente SearchaBox no aplicativo? Ao se referir a SeachBox no App.js, a propriedade changeSearchVal é adicionada (o subcomponente é obtido por meio de this.props.changeSearchVal) e seu valor é a referência do método.
<SearchBox changeSearchVal = {this.changeSearchVal}/>
A implementação do método changeSearchVal é a seguinte;
changeSearchVal(val){
//查询搜索结果,为了简化,写死固定值,模拟查询过程
console.log("输入值:"+val);
let searchListVal=['牛奶','饼干']
//更新state中的searchListVal
this.setState({searchListVal:searchListVal});
}
Nesse método, o parâmetro de entrada é o valor da caixa de entrada.Por uma questão de simplicidade, o resultado da pesquisa é diretamente gravado, atualizado e salvo no searListVal do estado.
Em seguida, o resultado da pesquisa searchListVal é passado para o subcomponente searchList por meio de adereços.
<SearchList searchListVal={this.state.searchListVal}/>
Faça referência ao componente SearchList, defina o atributo SearchListVal e atribua o searchListVal do estado a esse atributo.
O código completo do App.js é o seguinte:
import React from 'react';
import logo from './logo.svg';
import './App.css';
//导入两个组件
import SearchList from './SearchList.js';
import SearchBox from './SearchBox.js';
import SearchHot from './SearchHot.js'
class App extends React.Component {
constructor(props){
super(props);
//初始化state
this.state={searchListVal:[]};
this.changeSearchVal = this.changeSearchVal.bind(this);
}
//1、回调方法,
changeSearchVal(val){
//查询搜索结果,为了简化,写死固定值,模拟查询过程
console.log("输入值:"+val);
let searchListVal=['牛奶','饼干']
//更新state中的searchListVal
this.setState({searchListVal:searchListVal});
}
render(){
return (
<div className="App">
{/* 通过props传递回调方法changeSearchVal */}
<SearchBox changeSearchVal = {this.changeSearchVal}/>
<SearchHot />
{/* 通过props传递属性值searchListVal */}
<SearchList searchListVal={this.state.searchListVal}/>
</div>
);
}
};
export default App;
- Componente SearchList
No componente SearchList, obtenha o valor searchListVal de props e encapsule-o em uma lista. O código SearchList.js é o seguinte:
import React from 'react';
import './SearchList.css';
class SearchList extends React.Component{
constructor(props){
super(props);
}
render(){
//1、从props中获取searchListVal,封装列表
const searchValList = this.props.searchListVal.map((value)=>
(<li key={value.toString()}>
{value}
</li>)
);
return(
<div className="d">
<div className="s">搜索结果:</div>
<ul className="u">
{/* 引用对象表达式*/}
{searchValList}
</ul>
</div>
)
}
};
export default SearchList;
Veja o efeito de renderização final:
Neste ponto, o uso básico de adereços está concluído, mas comparado ao Vue, descobrimos que há duas perguntas que não foram respondidas:
1. A transferência de dados entre os componentes pai e filho é unidirecional e o componente filho pode alterar o valor dos acessórios?
2. Como implementar o slot vue no Reactjs?
Primeiro, observe o primeiro problema, adicionamos esse código no SearchList.js, alteramos o valor de props no subcomponente.
render(){
//修改props的值
this.props.searchListVal=['牛奶','饼干'];
//1、从props中获取searchListVal,封装列表
const searchValList = this.props.searchListVal.map((value)=>
(<li key={value.toString()}>
{value}
</li>)
);
...
}
O resultado está errado
Os acessórios são somente leitura e não podem ser modificados, o que é consistente com o Vue. A transferência de dados entre os componentes pai e filho é unidirecional e descendente.
Continue examinando a segunda pergunta: de fato, não há "slot" no Reactjs, e a função "slot" é realizada através do disfarce de this.props.children .
Adicionada uma seção do código JSX no App.js,
<SearchList searchListVal={this.state.searchListVal}>
<div>为您搜索到2条记录</div>
</SearchList>
Insira esse código no subcomponente SearchList e exiba-o.
return(
<div className="d">
<div className="s">搜索结果:</div>
{/* 引入插槽代码 */}
{this.props.children}
<ul className="u">
{/* 引用对象表达式*/}
{searchValList}
</ul>
</div>
)
V. Resumo
Este capítulo apresenta o conhecimento básico dos componentes Reactjs.
1. Existem dois modos para criar componentes, modo de função e modo de classe, sendo recomendado o modo de classe.
2. A máquina de estado dentro do componente tem seu escopo apenas dentro do componente.
(1) This.state pode ser usado para atribuição apenas no método construtor, e o método setState é usado para atualizar outros locais.
(2) setState é uma operação assíncrona; se você precisar usar o valor atualizado, chame-o em seu método de retorno de chamada.
3. A transmissão de dados entre os componentes pai e filho é realizada por meio de adereços, e a direção do fluxo de dados é unidirecional e descendente; o disfarce das crianças realiza a função "slot".