<p id="fz1ps"><listing id="fz1ps"></listing></p><acronym id="fz1ps"><listing id="fz1ps"></listing></acronym>

<p id="fz1ps"></p>
<button id="fz1ps"></button>
<acronym id="fz1ps"></acronym>

<p id="fz1ps"><listing id="fz1ps"></listing></p>

<p id="fz1ps"><listing id="fz1ps"><acronym id="fz1ps"></acronym></listing></p>

低代碼平臺前端的設計與實現(四)組件大綱樹的構建設計

在上篇文章,我們已經設計了一個簡單的設計態的Canvas,能夠顯示經過BuildEngine生成的ReactNode進行渲染。本文,我們將繼續上一篇文章的成果,設計并實現一個能夠顯示組件節點大綱樹的組件。

什么是組件大綱樹?

我們希望用戶能通過一個地方比較明顯的看到當前整個ComponentNode的樹狀結構;當用戶點擊某個ComponentNode的時候,既能夠在DesignCanvas上高亮當前選中的UI元素,同時對于組件大綱樹上也能高亮對應的樹狀節點。

PS:我們所設計的低開前端平臺定位是輕量級。所以,我們在構建整個平臺核心庫的時候,并不會設計的非常復雜,本次我們將不會設計直接將元素進行拖拉拽到畫布的內容,而是會圍繞整個節點大綱樹,來優化我們的低開體驗。

010-effect

如何設計實現大綱樹與設計態UI界面的統一?

在本次設計與開發之前,我們需要回顧一下上篇文章中(低代碼平臺前端的設計與實現(三)設計態畫布DesignCanvas的設計與實現 - 知乎 (zhihu.com))關于DesignCanvas的設計。DesignCanvas的過程設計如下:

020-DesignCanvasOldVersion

正如上圖所示,DesignCanvas的執行過程中,step4 -> data5 -> step6 -> data7 是在一個函數處理過程中的。

為了實現本次的需求,我們可能需要對上述的過程進行一定的優化,達到UI的渲染與元素節點大綱樹組件在同一個DesignCanvas中的渲染的目的。在討論如何修改前,我們先采用一個流程圖來展示這個過程:

030-DesignCanvasWithNodeTreeIdea

從上圖,我們可以很容易的知道,為了讓ComponentNode樹到UI界面的生成與ComponentNode樹到節點大綱樹的生成是一致且同步的。我們需要將ComponentNode object和selectedNodePath再交給組件大綱樹進行渲染。

在這樣一套設計下,無論點擊大綱樹任意樹節點,還是點擊設計態UI界面的任意UI組件。我們都能夠通過相關的事件(對于大綱樹來說是樹節點的點擊事件;對于設計態UI界面上的UI組件來說是前面設計的wrapper的點擊事件)拿到當前點擊的元素的唯一path標識;然后,我們將拿到的path標識設置給selectedtNodePath這個state,最后再由該state來同時控制大綱樹的節點高亮和設計態UI界面上的UI組件的邊框高亮。這個過程由下面的流程圖來簡單描述:

040-selectedNodePathChangeEvent

大綱樹組件實現

首先,我們選擇了antd5的Tree樹形組件。對于該組件我們會以受控的方式來使用,具體來講,Tree樹形組件的節點選中通過屬性selectedKeys控制;樹形組件的節點展開通過屬性expandedKeys來控制。當然,一旦我們選擇該組件以受控方式使用,那么不可避免的需要用對應的onSelect事件onExpand事件來獲取當前狀態值,再交給上述的selectedKeysexpandedKeys。

Tree組件的基本用法

本節內容主要講antd5的Tree樹形組件的基本用法,目的是為了后面我們具體的大綱樹組件做基礎準備,可以完全當作獨立的一節內容來看。

Tree的selectedKeys接收的是一個數組,用以表現被選中的節點。但需要特別注意:

Tree在默認的使用場景下是單個選中。也就是說,用戶點擊任意一個節點時,就選中該節點;點擊其他節點,則選中其他節點。同一時間只會有一個被選中的節點。selectedKeys盡管是一個數組,但在單選場景下,要不是一個空數組來表示沒有節點選中,要不是一個只有一個元素的數組,表示某一個節點選中。下面用一個Demo來演示:

 /**
 * 首先準備一段測試數據:
 * 1
 * ├ 1-1
 * └ 1-2
 *   └ 1-2-1
 * 注意:TREE_DATA是一個數組!
 **/
const TREE_DATA = [
    {
        key: '1',
        title: 'title 1',
        children: [{
            key: '1-1',
            title: 'title 1-1'
        }, {
            key: '1-2',
            title: 'title 1-2',
            children: [{
                key: '1-2-1',
                title: 'title 1-2-1'
            }]
        }]
    }
]

然后,編寫一段代碼,將selectedKeys設置為1-2-1,也就是說,我們選中了上面的1-2-1節點:

export const TreeDemo = () => {
    return <Tree selectedKeys={['1-2-1']} treeData={TREE_DATA}/>
}
// 再次強調,selectedKeys是一個數組,但是在默認情況下,該數組只有一個元素或者空。

這個例子的效果如下:

selectedKeys

從上面的gif可以看到界面渲染后,選中的節點就是1-2-1。同時,其他的節點無論我們如何點擊,都不會有任何的效果(受控)。為了能夠點擊后,讓Tree組件選中對應的節點,我們需要將selectedKeys至少作為一個state來存放,然后通過onSelect來設置該state:

export const TreeDemo = () => {
    // 用一個state來表明當前選擇的Keys
    const [currSelectedKeys, setCurrSelectedKeys] = useState<string[]>([]);
    return <Tree
        treeData={TREE_DATA}
        selectedKeys={currSelectedKeys}
        onSelect={selectedKeys => {
            // 當我們點擊任何一個節點的時候,都會觸發該onSelect,第一個參數則是即將選中的Keys
            // 當然,根據文檔,我們重復點擊同一節點,也會觸發該onSelect事件,但參數 selectedKeys 會是一個空數組
            console.log('onSelect, selectedKeys: ', selectedKeys);
            setCurrSelectedKeys(selectedKeys as string[])
        }}
    />
}

上述的過程,可以用如下的數據流來描述:

060-selectedKeys-workflow

上述過程中,currSelectedKeys表明當前選中的Keys(默認的單選模式下,是一個長度為1或0的數組),傳給Tree的屬性selectedKeys,Tree組件的UI展示的過程中使用根據selectedKeys來高亮對應節點;當然,我們點擊任意節點的時候,會觸發onSelect事件,該事件第一個參數就是點擊選中的節點的Keys,我們可以直接將這個值再次設置給currSelectedKeys這個state。在上述的代碼下,我們可以看到效果如下:

070-selectedKeys-with-control

現在,我們分析了selectedKeys后,再來分析一下Tree樹形組件的expandedKeys。這個屬性是一個數組,控制整個Tree節點展開的Keys。我們首先將該值設置為:['1']

    ... ...
    return <Tree
        treeData={TREE_DATA}
        selectedKeys={currSelectedKeys}
        onSelect={selectedKeys => {
           ... ...
        }}
+       expandedKeys={['1']}
    />

然后查看Demo效果:

080-expandedKeys-without-control

可以看到,無論怎樣點擊節點左側的三角,都無法展開或收起對應的子節點。類似的,我們使用一個state來存儲展開的節點,然后使用onExpand事件來設置,即可達到效果:

090-expandedKeys-with-control.gif

組件大綱樹面板

有了上面關于antd5的Tree樹形組件的受控方式的使用基礎,我們開始設計我們自己的組件大綱樹組件,這里我們為它取名為:ComponentNodeTreeDesignPanel。該組件的props如下:

interface ComponentNodeTreeDesignPanelProps {
    /**
     * 根 ComponentNode
     */
    componentNode: ComponentNode;
    /**
     * 選中的元素節點
     */
    selectedComponentNodePath: string;
    /**
     * 點擊選中Tree中的某個節點的事件回調
     * @param selectedNodePath 選中指定的節點的Path,
     * 譬如:"/page/panel@0/button@0"
     */
    onComponentNodeSelected: (selectedNodePath: string) => void;
}

我們再來討論下這些屬性如何關聯內部的antd Tree樹形組件的渲染與行為的。這里,我直接用一個流程圖來描述:

100-ComponentNodeTreeDesignPanel-workflow

上述過程具體為:

  1. 首先,為了呈現組件節點樹狀UI,很容易知道至少需要將ComponentNode對象傳入,因為該對象本身就是樹形的,只需要進行簡單的數據轉換即可完成Tree的樹形數據格式,并渲染;

  2. 其次,為了達到高亮對應的節點效果,則需要傳入當前選中的節點的唯一標識path,在內部轉換為selectedKeys和expandedKeys;

  3. 最后,當我們點擊Tree的節點時候,需要把對應的節點信息傳到上層,讓外部再次控制傳入當前選中的ComponentNode的path,形成一個閉環的數據流。

當然,這里面還涉及一些轉換,還有path的構成規則。這里不再贅述,感興趣的讀者可以閱讀有關ComponentNodeTreeDesignPanel的組件代碼。

最終效果:

110-final-real-effect

附錄

本次的內容已經提交至Github,并在打上了相應的Git tag標識:

https://github.com/w4ngzhen/lite-lc/tree/chapter_04

commit信息(倒序):

2. 修改DesignCanvas相關邏輯,實現ComponentNodeTreeDesignPanel組件與BuildEngine生成的組件對于選中的節點path,同步分別高亮樹形節點和UI組件。

1. 新增工具方法,支持根據 ComponentNode 的path,得到該節點的整個鏈路path形成的數組;新增 ComponentNodeTreeDesignPanel 組件,內部使用antd5的Tree樹形控件呈現 ComponentNode 的樹狀結構,且通過外部傳入的"選中節點path"屬性,以受控方式控制高亮節點。
posted @ 2023-03-05 21:22  w4ngzhen  閱讀(624)  評論(0編輯  收藏  舉報
真人性做爰视频

<p id="fz1ps"><listing id="fz1ps"></listing></p><acronym id="fz1ps"><listing id="fz1ps"></listing></acronym>

<p id="fz1ps"></p>
<button id="fz1ps"></button>
<acronym id="fz1ps"></acronym>

<p id="fz1ps"><listing id="fz1ps"></listing></p>

<p id="fz1ps"><listing id="fz1ps"><acronym id="fz1ps"></acronym></listing></p>