Maison  >  Article  >  interface Web  >  Rendu de tableau et fonctionnement du framework réactif Pastate.js

Rendu de tableau et fonctionnement du framework réactif Pastate.js

不言
不言original
2018-04-10 16:24:551573parcourir

Le contenu de cet article concerne le rendu des tableaux et le fonctionnement du framework responsive Pastate.js. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer

C'est la réponse de Pastate. js Le troisième chapitre de la série de didacticiels sur le cadre de gestion de l'état de réaction Bienvenue pour prêter attention et continuer à mettre à jour.

Dans ce chapitre, nous verrons comment restituer et traiter des tableaux en état en pâte.

Rendering Array

Nous mettons d'abord à jour la structure de l'état :

const initState = {
    basicInfo: ...,
    address: ...,
    pets: [{
        id:'id01',
        name: 'Kitty',
        age: 2
    }]
}

Nous définissons un tableau initState.pets composé d'éléments d'objet, et le tableau a un élément initial .

Ensuite, nous définissons les composants pertinents pour afficher la valeur des animaux de compagnie :

class PetsView extends PureComponent {
    render() {
        /** @type {initState['pets']} */
        let state = this.props.state;
        return (
            <p style={{ padding: 10, margin: 10 }}>
                <p><strong>My pets:</strong></p>
                {state.map(pet => <PetView state={pet} key={pet.id}/>)}
            </p>
        )
    }
}
class PetView extends PureComponent {
    render() {
        /** @type {initState[&#39;pets&#39;][0]} */
        let state = this.props.state;
        return (
            <p>
                <li> {state.name}: {state.age} years old.</li>
            </p>
        )
    }
}

Deux composants sont définis ici, le premier est PetsView, utilisé pour afficher le tableau des animaux de compagnie ; le deuxième est PetView, utilisé pour afficher les éléments familiers.
Ensuite, placez le composant PetsView dans le composant AppView pour afficher :

...
class AppView extends PureComponent {
    render() {
        /** @type {initState} */
        let state = this.props.state;
        return (
            <p style={{ padding: 10, margin: 10, display: "inline-block" }}>
                <BasicInfoView state={state.basicInfo} />
                <AddressView state={state.address} />
                <PetsView state={state.pets} />
            </p>
        )
    }
}
...

Terminé ! Nous avons réussi à rendre un objet tableau, ce qui est le même que le mode de rendu des tableaux avec réaction native. Les résultats de la page sont les suivants :

Rendu de tableau et fonctionnement du framework réactif Pastate.js

Modifier. array

Tout d'abord, nous voulons ajouter ou soustraire des éléments de tableau, ce qui est très simple à réaliser en utilisant pasate. Inspiré de vue.js, Paste a amélioré les sept méthodes de mutation de tableau suivantes du nœud de tableau de store.state. Vous pouvez appeler ces fonctions de tableau directement et Paste déclenchera automatiquement la mise à jour de la vue. Ces 7 méthodes de mutation de tableau sont les suivantes 🎜>

  • push()

  • pop()

  • shift()

  • unshift()

  • Essayons d'utiliser push et pop pour mettre à jour un tableau : splice()

  • Très facile ! Nous avons également ajouté deux boutons et spécifié la fonction de traitement des clics. Exécutons-la et expérimentons-la :
  • sort()

  • Ouvrez l'option Mettre en évidence les mises à jour des outils de développement de réaction et cliquez sur. bouton poussoir ou pop, on peut observer que la vue se met à jour comme on le souhaite : reverse()

class PetsView extends PureComponent {

    pushPet(){
        state.pets.push({
            id: Date.now() + &#39;&#39;,
            name: &#39;Puppy&#39;,
            age: 1
        })
    }

    popPet(){
        state.pets.pop()
    }

    render() {
        /** @type {initState[&#39;pets&#39;]} */
        let state = this.props.state;
        return (
            <p style={{ padding: 10, margin: 10 }}>
                <p><strong>My pets:</strong></p>
                {state.map(pet => <PetView state={pet} key={pet.id}/>)}
                <p>
                    <button onClick={this.pushPet}>push pet</button>
                    <button onClick={this.popPet}>pop pet</button>
                </p>
            </p>
        )
    }
}
Tableau initial vide et éditeur intelliSence

Normalement , la valeur initiale d'un nœud du tableau est vide. Afin d'implémenter l'éditeur intelliSence, nous pouvons définir un

type d'élément à l'extérieur, et annoter les éléments de ce nœud de tableau comme ce type : Rendu de tableau et fonctionnement du framework réactif Pastate.js

Vous pouvez également utiliser un format générique. Définissez le type de tableau :

.

Traitement des actions internes des composants multi-instancesRendu de tableau et fonctionnement du framework réactif Pastate.jsDans le chapitre précédent, nous avons mentionné le Composant à instance unique

, ce qui signifie que le composant n'est utilisé qu'une seule fois et que nous pouvons l'utiliser ; il dans PetView Pour afficher les éléments du tableau, il sera utilisé plusieurs fois. Nous appelons les composants qui

sont utilisés à plusieurs endroits

comme

composants multi-instances. La logique de traitement des actions internes d'un composant multi-instance est déterminée par l'emplacement spécifique de l'instance du composant, qui est différent du mode de traitement d'un composant mono-instance.

Nous essayons de trouver un moyen d'ajouter deux boutons à chaque vue d'animal pour ajuster l'âge de l'animal. Nous utilisons deux solutions traditionnelles et des solutions de pâte pour les mettre en œuvre respectivement :
const initState = {
    ...
    /** @type {[pet]} */
    pets: []
}
const pet = {
    id: &#39;id01&#39;,
    name: &#39;Kitty&#39;,
    age: 2
}

réagir solution traditionnelle. /** @type {Array4c3a5eece312dd836da9fe9d51745a77} */

Solution traditionnelle 1 : Traitement du composant parent

Le composant parent transmet la fonction de traitement liée à l'index au composant enfant : Ce mode implémente la logique de traitement des actions du composant enfant dans le composant parent , puis le composant parent lie l'action à l'index correspondant et la transmet au composant enfant Ce mode peut unifier le traitement des actions au niveau du composant .Si la signification de la vue d'un composant multi-instance Il est préférable d'utiliser ce mode de traitement d'action s'il n'est pas clair et universel, comme le composant Button encapsulé par lui-même, etc. Cependant, si la signification d'un composant multi-instance est évidente et non universelle, notamment s'il est utilisé pour afficher des éléments de tableau, l'utilisation de ce mode entraînera des processus de rendu redondants.

Ouvrez l'option Mettre en évidence les mises à jour des outils de développement de React et cliquez plusieurs fois

Après avoir ajouté quelques éléments, cliquez sur le bouton

ou

pour voir comment le composant est restitué :

Vous pouvez constater que lorsque nous modifions uniquement la valeur à l'intérieur d'un certain élément du tableau (pet[x].age), d'autres éléments du tableau seront également modifiés. -rendu. En effet, Pet.props.addAge et Pet.props.reduceAge sont des objets anonymes qui seront régénérés à chaque fois que le composant parent PetsView est rendu. PureComponent l'utilise pour penser que les données dont dépend le composant ont été mises à jour, il se déclenche donc. -rendu. Bien que ce problème puisse être résolu manuellement en utilisant React.Component avec une fonction de cycle de vie ShouldComponentUpdate personnalisée, la valeur de la propriété du sous-composant anonyme est régénérée chaque fois que le composant parent PetsView est rendu, ce qui consomme également des ressources informatiques.
class PetsView extends PureComponent {
    ...
    addAge(index){
        state.pets[index].age += 1
    }
    reduceAge(index){
        state.pets[index].age -= 1
    }
    render() {
        /** @type {initState[&#39;pets&#39;]} */
        let state = this.props.state;
        return (
            <p style={{ padding: 10, margin: 10 }}>
                ...
                {
                    state.map((pet, index) => 
                        <PetView 
                            state={pet} 
                            key={pet.id} 
                            addAge={() => this.addAge(index)} // 绑定 index 值,传递给子组件
                            reduceAge={() => this.reduceAge(index)} //  绑定 index 值,传递给子组件
                        />)
                }
                ...
            </p>
        )
    }
}

传统方案2:子组件结合 index 实现

父组件向子组件传递 index 值:这种模式是父组件向子组件传递 index 值,并在子组件内部实现自身的事件处理逻辑,如下:

class PetsView extends PureComponent {
    ...
    render() {
        ...
        return (
            <p style={{ padding: 10, margin: 10 }}>
                ...
                {
                    state.map((pet, index) => 
                        <PetView 
                            state={pet} 
                            key={pet.id} 
                            index={index} // 直接把 index 值传递给子组件
                        />)
                }
                ...
            </p>
        )
    }
}
class PetView extends PureComponent {

    // 在子组件实现动作逻辑

    // 调用时传递 index
    addAge(index){
        state.pets[index].age += 1
    }

    // 或函数自行从 props 获取 index
    reduceAge = () => { // 函数内部使用到 this 对象,使用 xxx = () => {...} 来定义组件属性更方便
        state.pets[this.props.index].age -= 1
    }

    render() {
        /** @type {initState[&#39;pets&#39;][0]} */
        let state = this.props.state;
        let index = this.props.index;
        return (
            <p >
                <li> {state.name}: 
                    <button onClick={() => this.reduceAge(index)}> - </button> {/* 使用闭包传递 index 值 */}
                    {state.age} 
                    <button onClick={this.addAge}> + </button> {/* 或让函数实现自己去获取index值 */}
                    years old.
                </li>
            </p>
        )
    }
}

这种模式可以使子组件获取 index 并处理自身的动作逻辑,而且子组件也可以把自身所在的序号显示出来,具有较强的灵活性。我们再来看看其当元素内部 state 改变时,组件的重新渲染情况:

Rendu de tableau et fonctionnement du framework réactif Pastate.js

我们发现,数组元素组件可以很好地按需渲染,在渲染数组元素的情况下这种方法具有较高的运行效率。

但是,由于元素组件内部操作函数绑定了唯一位置的 state 操作逻辑,如addAge(index){ state.pets[index].age += 1}。假设我们还有 state.children 数组,数组元素的格式与 state.pets 一样, 我们要用相同的元素组件来同时显示和操作这两个数组时,这种数组渲染模式就不适用了。我们可以用第1种方案实现这种情况的需求,但第1种方案在渲染效率上不是很完美。

pastate 数组元素操作方案

Pastate 的 imState 的每个节点本身带有节点位置的信息和 store 归宿信息,我们可以利用这一点来操作数组元素!

pastate 方案1:获取对于的响应式节点

我们使用 getResponsiveState 函数获取 imState 对于的响应式 state,如下:

class PetsView extends PureComponent {
    ...
    render() {
        ...
        return (
            <p style={{ padding: 10, margin: 10 }}>
                ...
                {
                    state.map((pet, index) => 
                        <PetView 
                            state={pet} 
                            key={pet.id}   {/* 注意,这里无需传递 index 值,除非要在子组件中有其他用途*/}
                        />)
                }
                ...
            </p>
        )
    }
}
import {..., getResponsiveState } from &#39;pastate&#39;

class PetView extends PureComponent {
    addAge = () => {
        /** @type {initState[&#39;pets&#39;][0]} */
        let pet = getResponsiveState(this.props.state); // 使用 getResponsiveState 获取响应式 state 节点
        pet.age += 1
    }
    reduceAge = () => {
        /** @type {initState[&#39;pets&#39;][0]} */
        let pet = getResponsiveState(this.props.state); // 使用 getResponsiveState 获取响应式 state 节点
        pet.age -= 1
    }
    render() {
        /** @type {initState[&#39;pets&#39;][0]} */
        let state = this.props.state;
        return (
            <p >
                <li> {state.name}: 
                    <button onClick={this.reduceAge}> - </button>
                    {state.age} 
                    <button onClick={this.addAge}> + </button>
                    years old.
                </li>
            </p>
        )
    }
}

我们可以看到,子组件通过 getResponsiveState 获取到当前的 props.state 对应的响应式 state,从而可以直接对 state 进行复制修改,你无需知道 props.state 究竟在 store.state 的什么节点上! 这种模式使得复用组件可以在多个不同挂载位置的数组中使用,而且可以保证很好的渲染性能:

Rendu de tableau et fonctionnement du framework réactif Pastate.js

pastate 方案2:使用 imState 操作函数

Pastate 提供个三个直接操作 imState 的函数,分别为 set, merge, update。我们来演示用这些操作函数来代替  getResponsiveState 实现上面操作宠物年龄的功能:

import {..., set, merge, update } from &#39;pastate&#39;

class PetView extends PureComponent {
    addAge = () => {
        set(this.props.state.age, this.props.state.age + 1); 
    }
    reduceAge = () => {
        merge(this.props.state, {
            age: this.props.state.age - 1
        });
    }
    reduceAge_1 = () => {
        update(this.props.state.age, a => a - 1);
    }
    ...
}

可见,这种 imState 操作函数的模式也非常简单!

使用 pastate 数组元素操作方案的注意事项:当操作的 state 节点的值为 null 或 undefined 时,  只能使用 merge 函数把新值 merge 到父节点中,不可以使用  getResponsiveStatesetupdate。我们在设计 state 结构时,应尽量避免使用绝对空值,我们完全可以用 '', [] 等代替绝对空值。

下一章,我们来看看如何在 pastate 中渲染和处理表单元素。


这是 Pastate.js 响应式 react state 管理框架系列教程的第三章,欢迎关注,持续更新。

这一章我们来看看在 pastate 中如何渲染和处理 state 中的数组。

相关推荐:

Pastate.js 之响应式 react state 管理框架

Pastate.js 响应式框架之多组件应用

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn