>  기사  >  웹 프론트엔드  >  Pastate.js 반응형 프레임워크의 배열 렌더링 및 작동

Pastate.js 반응형 프레임워크의 배열 렌더링 및 작동

不言
不言원래의
2018-04-10 16:24:551573검색

이 글에서 공유한 내용은 Pastate.js 반응형 프레임워크의 배열 렌더링 및 작동에 관한 것입니다. 이는 특정 참조 가치가 있습니다. 필요한 친구가 참조할 수 있습니다.

이것은 Pastate.js 반응형 반응 상태 관리 프레임워크입니다. 시리즈 3장의 튜토리얼에 주목하고 계속 업데이트해 주세요.

이 장에서는 붙여넣기 상태의 배열을 렌더링하고 처리하는 방법을 살펴보겠습니다.

배열 렌더링

먼저 상태 구조를 업데이트합니다.

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

객체 요소로 구성된 initState.pets 배열을 정의하고 배열에는 초기 요소가 있습니다.

다음으로 애완동물의 값을 표시하는 관련 구성 요소를 정의합니다.

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

여기에는 두 개의 구성 요소가 정의되어 있습니다. 첫 번째는 애완 동물 배열을 표시하는 데 사용되는 PetsView이고, 두 번째는 애완 동물 요소를 표시하는 데 사용되는 PetView입니다.
다음으로 PetsView 구성 요소를 AppView 구성 요소에 넣어 다음을 표시합니다.

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

완료! 네이티브 리액트를 사용한 배열 렌더링 패턴과 동일한 배열 객체 렌더링에 성공했습니다. 페이지 결과는 다음과 같습니다.

Pastate.js 반응형 프레임워크의 배열 렌더링 및 작동

배열 수정

먼저 배열 요소를 추가하거나 빼겠습니다. 이는 pasate Simple을 사용하여 구현하기가 매우 쉽습니다. vue.js에서 영감을 받아 Pastate는 store.state 배열 노드의 다음 7가지 배열 변형 방법을 향상했습니다. 이러한 배열 함수를 직접 호출할 수 있으며 Pastate는 자동으로 뷰 업데이트를 트리거합니다. 이 7가지 배열 변이 방법은 다음과 같습니다

  • push()push()

  • pop()

  • shift()

  • unshift()

  • splice()

  • sort()

  • reverse()

我们来尝试使用 push 和 pop 来更新数组:

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

非常容易!我们还添加了两个按钮并指定了点击处理函数,运行体验一下:

Pastate.js 반응형 프레임워크의 배열 렌더링 및 작동

打开 react dev tools 的 Highlight Updates 选项,并点击 push 或 pop 按钮,可以观察到视图更新情况如我们所愿:

Pastate.js 반응형 프레임워크의 배열 렌더링 및 작동

空初始数组与编辑器 intelliSence

通常情况下,数组节点的初始值是空的。为了实现编辑器 intelliSence, 我们可以在外面定义一个元素类型,并注释这个数组节点的元素为该类型:

const initState = {
    ...
    /** @type {[pet]} */
    pets: []
}
const pet = {
    id: &#39;id01&#39;,
    name: &#39;Kitty&#39;,
    age: 2
}

你也可以使用泛型的格式来定义数组类型:  /** @type {Array4c3a5eece312dd836da9fe9d51745a77} */

多实例组件的内部动作处理

上一章我们提到了单实例组件,是指组件只被使用一次;而我们可以到  PetView 被用于显示数组元素,会被多次使用。我们把这类在多处被使用的组件称为多实例组件。多实例组件内部动作的处理逻辑由组件实例的具体位置而定,与单实例组件的处理模式有差别,我们来看看。

我们试着制作一个每个宠物视图中添加两个按钮来调整宠物的年龄,我们用两种传统方案和pastate方案分别实现:

react 传统方案

传统方案1:父组件处理

父组件向子组件传递绑定index的处理函数:这种模式是把子组件的动作处理逻辑实现在父组件中,然后父组件把动作绑定对应的 index 后传递给子组件

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>
        )
    }
}
class PetView extends PureComponent {
    render() {
        /** @type {initState[&#39;pets&#39;][0]} */
        let state = this.props.state;
        return (
            <p >
                <li> {state.name}: 
                    <button onClick={this.props.reduceAge}> - </button> {/* 使用已绑定 index 值得动作处理函数 */}
                    {state.age} 
                    <button onClick={this.props.addAge}> + </button> {/* 使用已绑定 index 值得动作处理函数 */}
                    years old.
                </li>
            </p>
        )
    }
}

这种模式可以把动作的处理统一在一个组件层级,如果多实例组件的视图含义不明确、具有通用性,如自己封装的 Button 组件等,使用这种动作处理模式是最好的。但是如果多实例组件的含义明显、不具有通用性,特别是用于显示数组元素的情况下,使用这种模式会引发多余的渲染过程。

打开 react dev tools 的 Highlight Updates 选项,点击几次 push pet 增加一些元素后,再点击 +-

pop()Pastate.js 반응형 프레임워크의 배열 렌더링 및 작동shift ( )

unshift()🎜🎜🎜splice()🎜🎜🎜 sort ()🎜🎜🎜reverse()🎜🎜push와 pop을 사용하여 배열을 업데이트해 보겠습니다. 🎜
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>
        )
    }
}
🎜매우 쉽습니다. ! 또한 두 개의 버튼을 추가하고 클릭 처리 기능을 지정했습니다. 🎜🎜🎜Pastate.js 반응형 프레임워크의 배열 렌더링 및 작동🎜🎜🎜반응 개발 도구의 하이라이트 업데이트 옵션을 열고 푸시 또는 팝 버튼을 클릭하세요. 원하는 대로 뷰가 업데이트되는 것을 확인할 수 있습니다: 🎜🎜🎜Pastate.js 반응형 프레임워크의 배열 렌더링 및 작동🎜🎜🎜비어 있는 초기 배열 및 편집기 intelliSence🎜🎜일반적으로 배열 노드의 초기 값은 비어 있습니다. IntelliSence 편집기를 구현하기 위해 외부에서 🎜요소 유형🎜을 정의하고 이 배열 노드의 요소에 다음 유형으로 주석을 달 수 있습니다. 🎜
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>
        )
    }
}
🎜 일반 형식을 사용하여 배열 유형을 정의할 수도 있습니다: /** @type {배열<pet>}*/</pet> . 🎜🎜다중 인스턴스 구성 요소의 내부 작업 처리🎜🎜이전 장 🎜단일 인스턴스 구성 요소🎜에서 언급했는데, 이는 구성 요소가 한 번만 사용되며 PetView가 배열 요소를 표시하는 데 사용된다는 것을 알 수 있습니다. 여러 번 사용되었습니다. 우리는 이러한 유형의 구성 요소를 여러 위치에서 🎜사용되는🎜 🎜다중 인스턴스 구성 요소🎜라고 부릅니다. 다중 인스턴스 구성 요소의 내부 작업 처리 논리는 구성 요소 인스턴스의 특정 위치에 따라 결정되는데, 이는 단일 인스턴스 구성 요소의 처리 모드와 다릅니다. 🎜🎜우리는 애완동물의 나이를 조정하기 위해 각 애완동물 보기에 두 개의 버튼을 추가하는 방법을 만들려고 합니다. 우리는 두 가지 전통적인 솔루션과 파스타 솔루션을 각각 사용하여 구현합니다: 🎜

react Traditional 솔루션

기존 솔루션 1: 상위 컴포넌트 처리

🎜🎜상위 컴포넌트는 바인딩 인덱스 처리 기능을 하위 컴포넌트에 전달합니다🎜: 이 모드는 상위 컴포넌트에서 하위 컴포넌트의 액션 처리 로직을 구현한 다음, 그러면 상위 구성 요소가 그에 따라 작업을 바인딩합니다. 그러면 인덱스가 하위 구성 요소로 전달됩니다.🎜
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>
        )
    }
}
🎜이 모드는 다중 인스턴스 구성 요소의 보기 의미가 불분명하고 보편적인 경우 구성 요소 수준에서 작업 처리를 통합할 수 있습니다. 자체 캡슐화된 버튼 구성요소인 경우 이 작업을 사용하세요. 처리 모드가 가장 좋습니다. 그러나 다중 인스턴스 구성 요소의 의미가 명확하고 보편적이지 않은 경우, 특히 배열 요소를 표시하는 데 사용되는 경우 이 모드를 사용하면 렌더링 프로세스가 중복됩니다. 🎜🎜반응 개발 도구의 하이라이트 업데이트 옵션을 열고 push pet을 여러 번 클릭한 후 + 또는 - 버튼을 클릭하세요. 컴포넌트 재렌더링 상황을 보려면: 🎜🎜🎜🎜🎜🎜🎜 특정 배열 요소(pet[x].age) 내의 값만 수정하면 다른 배열 요소도 다시 렌더링된다는 것을 알 수 있습니다. 이는 Pet.props.addAge 및 Pet.props.reduceAge가 상위 구성 요소 PetsView가 렌더링될 때마다 재생성되는 익명 개체이기 때문입니다. PureComponent는 이를 사용하여 구성 요소가 의존하는 데이터가 업데이트되었다고 생각하므로 다시 트리거됩니다. -표현. 이 문제는 사용자 정의 shouldComponentUpdate 수명 주기 함수와 함께 React.Component를 사용하여 수동으로 해결할 수 있지만 익명의 하위 구성 요소 속성 값은 상위 구성 요소 PetsView가 렌더링될 때마다 재생성되며 컴퓨팅 리소스도 소비합니다. 🎜

传统方案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 改变时,组件的重新渲染情况:

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 的什么节点上! 这种模式使得复用组件可以在多个不同挂载位置的数组中使用,而且可以保证很好的渲染性能:

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

위 내용은 Pastate.js 반응형 프레임워크의 배열 렌더링 및 작동의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.