Pastate.js 响应式框架之数组渲染与操作

本篇文章给大家分享的内容是关于pastate.js 响应式框架之数组渲染与操作  ,有着一定的参考价值,有需要的朋友可以参考一下

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

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

渲染数组

首先我们更新一下 state 的结构:

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

登录后复制

我们定义了一个有对象元素构成的数组 initState.pets, 且该数组有一个初始元素。

接着,我们定义相关组件来显示 pets 的值:

class PetsView extends PureComponent {    render() {        /** @type {initState['pets']} */        let state = this.props.state;        return (            

                

My pets:

                {state.map(pet => )}                    )    }}

登录后复制

class PetView extends PureComponent {    render() {        /** @type {initState['pets'][0]} */        let state = this.props.state;        return (            

                

登录后复制登录后复制 {state.name}: {state.age} years old.                    )    }}

这里定义了两个组件,第一个是 PetsView,用来显示 pets 数组; 第二个是 PetView,用来显示 pet 元素。  
接下来把 PetsView 组件放入 AppView 组件中显示:

...class AppView extends PureComponent {    render() {        /** @type {initState} */        let state = this.props.state;        return (            

                                                            

        )    }}...

登录后复制

完成!我们成功渲染了一个数组对象,这与用原生 react 渲染数组的模式一样,页面结果如下:

Pastate.js 响应式框架之数组渲染与操作

修改数组

首先,我们想添加或减少数组元素,这用 pasate 实现起来非常简单。受 vue.js 启发,pastate 对 store.state 的数组节点的以下7个 数组变异方法 都进行了加强,你可以直接调用这些数组函数,pastate 会自动触发视图的更新。这 7 个数组变异方法如下

push()

pop()

shift()

unshift()

splice()

sort()

reverse()

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

class PetsView extends PureComponent {    pushPet(){        state.pets.push({            id: Date.now() + '',            name: 'Puppy',            age: 1        })    }    popPet(){        state.pets.pop()    }    render() {        /** @type {initState['pets']} */        let state = this.props.state;        return (            

                

My pets:

                {state.map(pet => )}                

                                                        

                    )    }}

登录后复制

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

Pastate.js 响应式框架之数组渲染与操作

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

Pastate.js 响应式框架之数组渲染与操作

空初始数组与编辑器 intelliSence

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

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

登录后复制

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

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

上一章我们提到了单实例组件,是指组件只被使用一次;而我们可以到  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['pets']} */        let state = this.props.state;        return (            

                ...                {                    state.map((pet, index) =>                          this.addAge(index)} // 绑定 index 值,传递给子组件                            reduceAge={() => this.reduceAge(index)} //  绑定 index 值,传递给子组件                        />)                }                ...            

        )    }}

登录后复制

class PetView extends PureComponent {    render() {        /** @type {initState['pets'][0]} */        let state = this.props.state;        return (            

                

登录后复制登录后复制 {state.name}:                      {/* 使用已绑定 index 值得动作处理函数 */}                    {state.age}                      {/* 使用已绑定 index 值得动作处理函数 */}                    years old.                                    )    }}

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

打开 react dev tools 的 Highlight Updates 选项,点击几次 push pet 增加一些元素后,再点击 + 或 – 按钮看看组件重新渲染的情况:

Pastate.js 响应式框架之数组渲染与操作

可以发现当我们只修改某一个数组元素内部的值(pet[x].age)时,其他数组元素也会被重新渲染。这是因为 Pet.props.addAge 和 Pet.props.reduceAge 是每次父组件 PetsView 渲染时都会重新生成的匿名对象,PureComponent 以此认为组件依赖的数据更新了,所以触发重新渲染。虽然使用 React.Component 配合 自定义的 shouldComponentUpdate 生命周期函数可以手动解决这个问题,但是每次渲染父组件 PetsView 时都重新生成一次匿名子组件属性值,也在消耗运算资源。

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

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

class PetsView extends PureComponent {    ...    render() {        ...        return (            

                ...                {                    state.map((pet, index) =>                         )                }                ...            

        )    }}

登录后复制登录后复制

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['pets'][0]} */        let state = this.props.state;        let index = this.props.index;        return (            

                

登录后复制 {state.name}:                      {/* 使用闭包传递 index 值 */}                    {state.age}                      {/* 或让函数实现自己去获取index值 */}                    years old.                                    )    }}

这种模式可以使子组件获取 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 (            

                ...                {                    state.map((pet, index) =>                         )                }                ...            

        )    }}

登录后复制登录后复制

import {..., getResponsiveState } from 'pastate'class PetView extends PureComponent {    addAge = () => {        /** @type {initState['pets'][0]} */        let pet = getResponsiveState(this.props.state); // 使用 getResponsiveState 获取响应式 state 节点        pet.age += 1    }    reduceAge = () => {        /** @type {initState['pets'][0]} */        let pet = getResponsiveState(this.props.state); // 使用 getResponsiveState 获取响应式 state 节点        pet.age -= 1    }    render() {        /** @type {initState['pets'][0]} */        let state = this.props.state;        return (            

                

登录后复制 {state.name}:                                         {state.age}                                         years old.                                    )    }}

我们可以看到,子组件通过 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 'pastate'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 到父节点中,不可以使用  getResponsiveState ,set 或 update。我们在设计 state 结构时,应尽量避免使用绝对空值,我们完全可以用 ”, [] 等代替绝对空值。

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

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

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

相关推荐:

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

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

以上就是Pastate.js 响应式框架之数组渲染与操作 的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2773909.html

(0)
上一篇 2025年3月8日 14:00:16
下一篇 2025年3月5日 01:11:59

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • Pastate.js 响应式 react 框架之表单渲染与操作

    本篇文章给大家分享的内容是关于pastate.js 响应式 react 框架之表单渲染与操作  ,有着一定的参考价值,有需要的朋友可以参考一下 这是 Pastate.js 响应式 react state 管理框架系列教程的第四章,欢迎关注,…

    2025年3月8日 编程技术
    200
  • Pastate.js 响应式 react 框架之 模块化

    本篇文章给大家分享的内容是关于pastate.js 响应式 react 框架之 模块化  ,有着一定的参考价值,有需要的朋友可以参考一下 这是 Pastate.js 响应式 react state 管理框架系列教程,欢迎关注,持续更新。 P…

    2025年3月8日 编程技术
    200
  • JavaScript创建对象

    本篇文章给大家分享的内容是关于javascript创建对象,有着一定的参考价值,有需要的朋友可以参考一下 调用系统的构造函数 创建一个最简单的方式就是创建一个Object的实例,如下:     // 1. 调用系统的构造函数    var …

    编程技术 2025年3月8日
    200
  • 详解js中的遍历 问题

    本篇文章给大家分享的内容是关于详解js中的遍历 问题,有着一定的参考价值,有需要的朋友可以参考一下 实例属性和原型属性 JavaScript中对象的属性分为两种: 数据属性 和 访问器属性 。 根据具体的上下文环境的不同,又可以将属性分为:…

    编程技术 2025年3月8日
    200
  • node结合swig渲染摸板

    本篇文章给大家分享的内容是关于node结合swig渲染摸板 ,有着一定的参考价值,有需要的朋友可以参考一下 在这里就nodejs如何应用swig摸板,总结一下一些基本的用法。首先当然是利用express框架在node后台上面搭建服务 var…

    2025年3月8日
    200
  • 使用node.js构建命令行工具

    本篇文章给大家分享的内容是使用node.js构建命令行工具 ,有着一定的参考价值,有需要的朋友可以参考一下 工具说明 inquirer.js:一个封装了常用命令行交互的node.js模块,通过该模块可以很方便地构建一个新的命令行应用。 sh…

    编程技术 2025年3月8日
    200
  • Vue.js提升必知的几点总结

    这次给大家带来Vue.js提升必知的几点总结,Vue.js提升的注意事项有哪些,下面就是实战案例,一起来看一下。 第一招:化繁为简的Watchers 场景还原: created(){ this.fetchPostList()},watch:…

    编程技术 2025年3月8日
    200
  • 在vuejs中使用v-show不起作用的原因有哪些

    这次给大家带来在vuejs中使用v-show不起作用的原因有哪些,在vuejs中使用v-show的注意事项有哪些,下面就是实战案例,一起来看一下。 1.官网概念描述 v-if 是’真正的’条件渲染,因为它会确保在切换…

    编程技术 2025年3月8日
    200
  • vue对storejs获取数据进行处理的步奏详解

    这次给大家带来vue对storejs获取数据进行处理的步奏详解,vue对storejs获取数据进行处理的注意事项有哪些,下面就是实战案例,一起来看一下。 具体代码如下所示: export default { data(){ return {…

    编程技术 2025年3月8日
    200
  • JS怎样扩展字符串拼接

    这次给大家带来JS怎样扩展字符串拼接,JS扩展字符串拼接的注意事项有哪些,下面就是实战案例,一起来看一下。 1、题外话,有关概念理解:String.prototype 属性表示 String原型对象。所有 String 的实例都继承自 St…

    编程技术 2025年3月8日
    200

发表回复

登录后才能评论