dom树视图_从dom中删除不可见的视图,同时仍然能够更改其状态

dom树视图

Especially in case your UIs are growing, it can significantly increase the performance → UX in case you keep the DOM minimal. For many use cases you still want to change the state of inactive (no longer rendered) views.

尤其是在UI不断增长的情况下,如果将DOM保持在最小限度,它可以显着提高性能→UX。 对于许多用例,您仍然想要更改非活动(不再呈现)视图的状态。

内容 (Content)

  1. Introduction

    介绍
  2. The Problem

    问题
  3. The Solution

    解决方案
  4. How does it work?

    它是如何工作的?
  5. Can we achieve the same in Angular, React or Vue?

    我们可以在Angular,React或Vue中实现相同的效果吗?
  6. Online Demo

    在线演示
  7. What is neo.mjs?

    什么是neo.mjs?
  8. Expanding Single Page Apps into multiple Browser Windows

    将单页应用程序扩展到多个浏览器窗口

1.简介 (1. Introduction)

While watching the video, please focus on the DOM inside the dev tools. I am switching between different cards (active views), opening the settings side bar and am changing settings of non active views. Inactive views are not inside the DOM. When re-activating the views, the latest state is in place and the scroll state is kept.

观看视频时,请专注于开发工具中的DOM。 我正在不同的卡片之间切换(活动视图),打开设置侧栏并更改非活动视图的设置。 非活动视图不在 DOM内部。 重新激活视图时,最新状态处于适当位置,并且滚动状态保持不变。

2.问题 (2. The Problem)

Especially back in the days, when I was working for Sencha, the UI performance has been a major pain point for client Apps as soon as they grow bigger.

尤其是在我为Sencha工作时,UI性能一直是客户端应用程序变得越来越大的主要痛点。

I am talking about UIs with 100+ views, many of them nested in Tabs or just card layouts.

我说的是具有100多个视图的UI,其中许多嵌套在“选项卡”中,或者仅嵌套在卡片布局中。

It was always a trade off: either you destroy the instances of non visible views, which means destroying the JS instances and no longer being able to access or even change Component states or keeping all views inside the DOM, resulting in a poor performance the bigger your UIs grow.

总是要权衡:要么销毁不可见视图的实例,这意味着销毁JS实例,并且不再能够访问甚至更改Component状态或将所有视图保留在DOM内,从而导致性能变差,您的用户界面不断增长。

Think about tabbed forms, where you want to validate fields vs other fields in different Tabs. For use cases like this, you had to keep all views.

考虑选项卡式表单,您要在其中验证字段与其他选项卡中的其他字段。 对于这样的用例,您必须保留所有视图。

As an example, let us take a look at the Neo Calendar (work in progress):

例如,让我们看一下Neo Calendar(正在进行的工作):

Image for post

If you look close: the div with the class “neo-layout-card” contains 4 items: the day, week, month and year views. Now imagine you would add 100+ events to this Calendar, affecting all views at once.

如果您仔细看:具有“ neo-layout-card”类的div包含4个项目:日,周,月和年视图。 现在想象您将向该日历添加100多个事件,从而一次影响所有视图。

This is still a “small” example, it does get even more problematic for massive UIs.

这仍然是一个“小”示例,对于大量的UI确实会出现更多问题。

3.解决方案 (3. The Solution)

What we want, is a DOM markup like this:

我们想要的是这样的DOM标记:

Image for post

The card layout now only contains one item: the month view. In case you look close, you will also notice that the Settings SideBar is not inside the DOM as well.

卡布局现在仅包含一项:月视图。 如果您看上去很近,您还会注意到Settings SideBar也不在DOM内。

Obviously, you could achieve this with killing the instances of the non active view, but this is not the goal.

显然,您可以通过杀死非活动视图的实例来实现此目的,但这不是目标。

Now we are opening (& mounting) the Settings View and activate the Year View Settings Tab:

现在,我们打开(安装)“设置”视图并激活“年视图”设置选项卡:

Image for post

You will notice, that the Settings View is inside the DOM now and the card layout still only contains the Month View.

您会注意到,“设置视图”现在位于DOM内,并且卡布局仍仅包含“月”视图。

We check the “showSixWeeksPerMonth” CheckBox:

我们选中“ showSixWeeksPerMonth”复选框:

Image for post

Now we navigate to the Years View:

现在,我们导航到Years视图:

Image for post

The View shows 6 rows per month (which is not the default value), the Month View is no longer inside the DOM.

该视图每月显示6行(这不是默认值),“月视图”不再位于DOM中。

Now you could say: “This is easy, since the Year View was never there yet!”

现在您可以说:“这很容易,因为年度视图还没有出现!”

Fair point. Let us switch to the General Settings:

有道理。 让我们切换到常规设置:

Image for post

We switch the language to German, which will affect the active Year View right away. Now we open the Month View Settings:

我们将语言切换为德语,这将立即影响当前的“年视图”。 现在,我们打开“月视图”设置:

Image for post

We switch the dayNameFormat to long and we switch to the Dark Theme.

我们将dayNameFormat切换为long,然后切换为Dark Theme。

Now we are navigating back to the Month View:

现在,我们回到月视图:

Image for post

At this point you will probably be excited, since our Setting changes are applied right away.

这时您可能会很兴奋,因为我们的设置更改已立即应用。

Let us close the Settings View:

让我们关闭“设置”视图:

Image for post

The Settings SideBar is no longer inside the DOM. In case we open it again, it will look the same.

设置边栏不再位于DOM中。 万一我们再次打开它,它看起来会一样。

You can also scroll inside the Month View (like seen inside the video), navigate to a different View and back, and the scroll state is still as it was before.

您还可以在“月视图”内部滚动(就像在视频内部看到的那样),然后导航到另一个“视图”并返回,并且滚动状态仍然像以前一样。

4.它如何运作? (4. How does it work?)

With the neo.mjs setup, it is actually pretty easy.

使用neo.mjs设置,实际上非常简单。

Let us take a look at:

让我们来看看:

https://github.com/neomjs/neo/blob/dev/src/calendar/MainContainer.mjs

https://github.com/neomjs/neo/blob/dev/src/calendar/MainContainer.mjs

/**
 *
 * @returns {Neo.component.Base[]}
 */
createViews() {
    let me    = this,
        cards = [],
        cmp;


    const defaultConfig = {
        currentDate : me.currentDate,
        eventStore  : me.eventStore,
        locale      : me.locale,
        weekStartDay: me.weekStartDay
    };


    const map = {
        day: {
            module: DayComponent,
            style : {padding: '20px'},
            ...defaultConfig,
            ...me.dayComponentConfig || {}
        },
        month: {
            module: MonthComponent,
            ...defaultConfig,
            ...me.monthComponentConfig || {}
        },
        week: {
            module      : WeekComponent,
            ...defaultConfig,
            ...me.weekComponentConfig || {}
        },
        year: {
            module              : YearComponent,
            scrollNewYearFromTop: me.scrollNewYearFromTop,
            ...defaultConfig,
            ...me.yearComponentConfig || {}
        }
    }


    me.views.forEach(view => {
        me[view + 'Component'] = cmp = Neo.create(map[view]);
        cards.push(cmp);
    });


    return cards;
}

The Calendar MainContainer will create all 4 views right away.

Calendar MainContainer将立即创建所有4个视图。

You can pass configs for each view, which allows you to change their configs any way you want. This also includes the module config, so you can extend a sub-module class, add configs & methods as you like and use your own class.

您可以为每个视图传递配置,这使您可以根据需要更改其配置。 这也包括模块配置,因此您可以扩展子模块类,根据需要添加配置和方法,并使用自己的类。

I will cover this part more in depth inside my next blog post.

我将在下一篇博客文章中更深入地介绍这一部分。

Each View will get stored inside an internal reference:

每个视图都将存储在内部引用中:

> myCalendar.monthComponent, myCalendar.yearComponent etc.

> myCalendar.monthComponent,myCalendar.yearComponent等。

As a next step, I enhanced the card layout a bit:

下一步,我对卡布局进行了一些改进:

https://github.com/neomjs/neo/blob/dev/src/layout/Card.mjs#L83

https://github.com/neomjs/neo/blob/dev/src/layout/Card.mjs#L83

/**
 * Modifies the CSS classes of the container items this layout is bound to.
 * Automatically gets triggered after changing the value of activeIndex.
 * @param value
 * @param oldValue
 * @protected
 */
afterSetActiveIndex(value, oldValue) {
    let me        = this,
        container = Neo.getComponent(me.containerId),
        sCfg      = me.getStaticConfig(),
        isActiveIndex, cls, items, vdom;


    if (container) {
        items = container.items;
        vdom  = container.vdom;


        if (!items[value]) {
            Neo.error('Trying to activate a non existing card', value, items);
        }


        items.forEach((item, index) => {
            cls           = item.cls;
            isActiveIndex = index === value;


            NeoArray.remove(cls, isActiveIndex ? sCfg.inactiveItemCls : sCfg.activeItemCls);
            NeoArray.add(   cls, isActiveIndex ? sCfg.activeItemCls   : sCfg.inactiveItemCls);


            if (me.removeInactiveCards) {
                item._cls = cls; // silent update
                item.vdom.cls = cls;
                item.vdom.removeDom = !isActiveIndex;
            } else {
                item.cls = cls;
            }
        });


        if (me.removeInactiveCards) {
            container.vdom = vdom;
        }
    }
}

The important part here is line 32:

这里的重要部分是第32行:

We add the vdom flag “removeDom: true” to each inactive card.

我们将vdom标志“ removeDom:true”添加到每个非活动卡中。

This will remove the card(s) from the real DOM.

这将从实际DOM中删除卡。

We still keep the JS instances as well as the vdom for each card.

我们仍然保留每张卡的JS实例以及vdom。

This allows us to continue changing configs, which will then get added to the virtual DOM. Once we put an inactive card back in, we will have the latest state of its vdom out of the box.

这使我们能够继续更改配置,然后将其添加到虚拟DOM中。 重新插入非活动的卡后,我们将立即提供其vdom的最新状态。

Let us take a look at the Settings View for Months:

让我们看一下“几个月的设置视图”:

https://github.com/neomjs/neo/blob/dev/src/calendar/view/MonthComponent.mjs#L152

https://github.com/neomjs/neo/blob/dev/src/calendar/view/MonthComponent.mjs#L152

Image for post

What we are basically doing here is:

我们基本上在这里做的是:

myCalendarInstance.monthComponent.dayNameFormat = “long”;

myCalendarInstance.monthComponent.dayNameFormat =“ long”;

Changing a config is all you need to do inside a config driven framework.

在配置驱动的框架内,您只需要做的就是更改配置。

This will trigger:

这将触发:

Image for post

which will change the current format and update the virtual DOM.

这将更改当前格式并更新虚拟DOM。

5.我们可以在Angular,React或Vue中实现相同的效果吗? (5. Can we achieve the same in Angular, React or Vue?)

Honestly, I have not looked into these libraries & framework for a very long time. I don’t know!

老实说,我已经很长时间没有研究这些库和框架了。 我不知道!

Feel free to add comments on this one and I will update the article.

随时对此发表评论,我将更新本文。

6.在线演示 (6. Online Demo)

This is a Sneak Preview version of the new Calendar Component.

这是新日历组件的Sneak Preview版本。

Please do not expect it to be fully functional yet. The development is in progress and a final version is scheduled for the 1.4 release.

请不要指望它能完全正常工作。 开发正在进行中,最终版本计划为1.4版本。

https://neomjs.github.io/pages/node_modules/neo.mjs/dist/production/examples/calendar/basic/index.html

https://neomjs.github.io/pages/node_modules/neo.mjs/dist/production/examples/calendar/basic/index.html

7.什么是neo.mjs? (7. What is neo.mjs?)

neo.mjs is an Open Source project (the entire code base as well as all examples & demo apps are using the MIT license).

neo.mjs是一个开源项目(整个代码库以及所有示例和演示应用程序均使用MIT许可证)。

Meaning: you can use it for free.

含义:您可以免费使用它。

It will stay like this.

它将保持这样。

However, the project is in need for more contributors as well as sponsors.

但是,该项目需要更多的贡献者赞助者

A lot(!) more items & ideas are on the roadmap.

路线图上还有很多(!)更多项目和想法。

If you want to contribute to a lovely Open Source project, this would be highly appreciated.

如果您想为可爱的开源项目做出贡献,将不胜感激。

In case the project has or will have business value for your company: signing up as a sponsor will allow me to put more time into it, resulting in a faster delivery time for new things.

如果该项目对贵公司具有或将具有商业价值:以赞助商身份注册将使我有更多时间投入其中,从而加快了新产品的交付时间。

8.将单页应用程序扩展到多个浏览器窗口 (8. Expanding Single Page Apps into multiple Browser Windows)

The current highlight of the neo.mjs framework is its ability, to move entire virtual DOM trees into different Browser Windows.

neo.mjs框架的当前亮点是其将整个虚拟DOM树移动到不同的浏览器Windows中的能力。

In case you are thinking about Apps running on multiple screens, you will love this one:

如果您正在考虑在多个屏幕上运行的Apps,那么您会喜欢上这样的一个:

Best regards & happy coding,Tobias

最好的问候和快乐的编码,Tobias

翻译自: https://itnext.io/removing-non-visible-views-from-the-dom-while-still-being-able-to-alter-their-state-dd366ed185ec

dom树视图

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值