Heim  >  Artikel  >  Web-Frontend  >  Array-Rendering und Betrieb des responsiven Frameworks von Pastate.j

Array-Rendering und Betrieb des responsiven Frameworks von Pastate.j

不言
不言Original
2018-04-10 16:24:551572Durchsuche

Der Inhalt dieses Artikels befasst sich mit der Array-Wiedergabe und dem Betrieb des responsiven Frameworks von Pastate.js. Er hat einen gewissen Referenzwert.

Dies ist die Antwort von Pastate.js Das dritte Kapitel der Tutorialreihe zum React State Management Framework. Bitte achten Sie darauf und aktualisieren Sie es weiter.

In diesem Kapitel werfen wir einen Blick darauf, wie man Arrays im Status „Einfügen“ rendert und verarbeitet.

Rendering-Array

Zuerst aktualisieren wir die Struktur des Zustands:

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

Wir definieren ein Array initState.pets, das aus Objektelementen besteht, und das Array hat ein Anfangselement .

Als nächstes definieren wir relevante Komponenten, um den Wert von Haustieren anzuzeigen:

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>
        )
    }
}

Hier werden zwei Komponenten definiert, die erste ist PetsView, die zur Anzeige des Haustiere-Arrays verwendet wird Das zweite ist PetView, das zur Anzeige von Haustierelementen verwendet wird.
Fügen Sie als Nächstes die PetsView-Komponente in die AppView-Komponente ein, um Folgendes anzuzeigen:

...
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>
        )
    }
}
...

Fertig! Wir haben ein Array-Objekt erfolgreich gerendert, was dem Modus zum Rendern von Arrays mit nativer Reaktion entspricht. Die Seitenergebnisse lauten wie folgt:

Array-Rendering und Betrieb des responsiven Frameworks von Pastate.j

Ändern Array

Zuerst möchten wir Array-Elemente hinzufügen oder subtrahieren, was mit Pasate sehr einfach zu erreichen ist. Inspiriert von vue.js hat Pastete die folgenden 7 Array-Mutationsmethoden des Array-Knotens von store.state erweitert. Sie können diese Array-Funktionen direkt aufrufen, und Pastete löst automatisch die Aktualisierung der Ansicht aus. Diese 7 Array-Mutationsmethoden lauten wie folgt: 🎜>

  • push()

  • pop()

  • shift()

  • unshift()

  • Versuchen wir, Push und Pop zu verwenden, um ein Array zu aktualisieren: splice()

  • Sehr einfach! Wir haben auch zwei Schaltflächen hinzugefügt und die Klickverarbeitungsfunktion spezifiziert. Lassen Sie es uns ausführen und erleben:
  • sort()

  • Öffnen Sie die Option „Updates hervorheben“ der React Dev Tools und klicken Sie Wenn wir die Taste drücken oder öffnen, können wir beobachten, dass die Ansicht nach Wunsch aktualisiert wird: 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>
        )
    }
}
Anfängliches Array und Editor intelliSence leeren

Normalerweise , der Anfangswert eines Array-Knotens ist leer. Um Editor-IntelliSence zu implementieren, können wir außerhalb einen

-Elementtyp definieren und die Elemente dieses Array-Knotens als diesen Typ annotieren: Array-Rendering und Betrieb des responsiven Frameworks von Pastate.j

Sie können auch ein generisches Format verwenden, um Definieren Sie den Array-Typ:

.

Interne Aktionsverarbeitung von Komponenten mit mehreren InstanzenArray-Rendering und Betrieb des responsiven Frameworks von Pastate.jIm vorherigen Kapitel haben wir Einzelinstanzkomponente

erwähnt, was bedeutet, dass die Komponente nur einmal verwendet wird und wir sie verwenden können es in PetView Zur Anzeige von Array-Elementen wird es mehrfach verwendet. Wir bezeichnen solche Komponenten, die

an mehreren Stellen

verwendet werden, als

Multiinstanzkomponenten. Die Verarbeitungslogik der internen Aktionen einer Komponente mit mehreren Instanzen wird durch den spezifischen Speicherort der Komponenteninstanz bestimmt, der sich vom Verarbeitungsmodus einer Komponente mit einer einzelnen Instanz unterscheidet.

Wir versuchen, jeder Haustieransicht zwei Schaltflächen hinzuzufügen, um das Alter des Haustiers anzupassen. Wir verwenden zwei traditionelle Lösungen und Pastenlösungen, um sie umzusetzen:
const initState = {
    ...
    /** @type {[pet]} */
    pets: []
}
const pet = {
    id: &#39;id01&#39;,
    name: &#39;Kitty&#39;,
    age: 2
}

Reagieren Sie auf die traditionelle Lösung/** @type {Array4c3a5eece312dd836da9fe9d51745a77} */

Traditionelle Lösung 1: Verarbeitung der übergeordneten Komponente

Die übergeordnete Komponente übergibt die an den Index gebundene Verarbeitungsfunktion an die untergeordnete Komponente: Dieser Modus implementiert die Aktionsverarbeitungslogik der untergeordneten Komponente im übergeordneten Element Komponente, und dann bindet die übergeordnete Komponente die Aktion an den entsprechenden Index und übergibt sie an die untergeordnete Komponente. Dieser Modus kann die Verarbeitung von Aktionen auf Komponentenebene vereinheitlichen einer Komponente mit mehreren Instanzen Es ist am besten, diesen Aktionsverarbeitungsmodus zu verwenden, wenn er unklar und universell ist, z. B. wenn die Button-Komponente in sich selbst gekapselt ist usw. Wenn jedoch die Bedeutung einer Komponente mit mehreren Instanzen offensichtlich und nicht universell ist, insbesondere wenn sie zur Anzeige von Array-Elementen verwendet wird, führt die Verwendung dieses Modus zu redundanten Rendering-Prozessen.

Öffnen Sie die Option „Updates hervorheben“ der React Dev Tools und klicken Sie ein paar Mal.

Nachdem Sie einige Elemente hinzugefügt haben, klicken Sie auf die Schaltfläche

oder

, um zu sehen, wie die Komponente neu gerendert wird:

Sie können feststellen, dass, wenn wir nur den Wert innerhalb eines bestimmten Array-Elements (pet[x].age) ändern, auch andere Array-Elemente geändert werden -gerendert. Dies liegt daran, dass Pet.props.addAge und Pet.props.reduceAge anonyme Objekte sind, die jedes Mal neu generiert werden, wenn die übergeordnete Komponente PetsView gerendert wird. PureComponent verwendet dies, um zu glauben, dass die Daten, von denen die Komponente abhängt, aktualisiert wurden, und löst daher erneut aus -Rendering. Obwohl dieses Problem manuell gelöst werden kann, indem React.Component mit einer benutzerdefinierten Lebenszyklusfunktion ShouldComponentUpdate verwendet wird, wird der anonyme Eigenschaftswert der Unterkomponente jedes Mal neu generiert, wenn die übergeordnete Komponente PetsView gerendert wird, was ebenfalls Rechenressourcen verbraucht.
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 改变时,组件的重新渲染情况:

Array-Rendering und Betrieb des responsiven Frameworks von Pastate.j

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

但是,由于元素组件内部操作函数绑定了唯一位置的 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 的什么节点上! 这种模式使得复用组件可以在多个不同挂载位置的数组中使用,而且可以保证很好的渲染性能:

Array-Rendering und Betrieb des responsiven Frameworks von Pastate.j

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 响应式框架之多组件应用

Das obige ist der detaillierte Inhalt vonArray-Rendering und Betrieb des responsiven Frameworks von Pastate.j. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn