Diversão com o Reactjs Parte 3-Componentes (Padrões, Estado e Acessórios)

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>&nbsp;&nbsp;<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>&nbsp;&nbsp;<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".

Publicado 33 artigos originais · Gostei 95 · Visitantes com mais de 30.000

Acho que você gosta

Origin blog.csdn.net/tcy83/article/details/104269261
Recomendado
Clasificación