最近、会社は Vue 開発に基づいたプロジェクトに取り組んでいます。そのプロジェクトでは、インターネットで長い間検索しましたが、適切なコンポーネントが見つかりませんでした。 Vue に基づいた組織構造ツリー コンポーネントを共有します。友人である必要がありますので、参照してください
会社のビジネス ニーズにより、組織構造 (会社の) を表示するツリー コンポーネントを開発する必要があります。プロジェクトは Vue に基づいています)。 GitHub で長い間検索した結果、そのようなコンポーネントはあまりなく、ビジネス ニーズを満たすコンポーネントもなかったので、独自のホイールを作成することにしました。
分析
ツリーなので、各ノードは同じコンポーネントである必要があります
ノードはノードの下にネストされているため、ノードコンポーネントは再帰コンポーネントである必要があります
、 質問は 。再帰的なコンポーネントを記述するにはどうすればよいですか?
再帰コンポーネント
Vue の公式ドキュメントには次のように書かれています:
コンポーネントはテンプレート内で自身を再帰的に呼び出すことができます。ただし、これは名前オプションがある場合にのみ実行できます
次に、ツリー ノードの再帰コンポーネントを作成しましょう:
<template> <p class="org-tree-node"> <p class="org-tree-node-label">{{data.label}}</p> <p class="org-tree-node-children" v-if="data.children"> <org-tree-node v-for="node in data.children" :data="node" :key="data.id"></org-tree-node> </p> </p> </template> <script> export default { name: 'OrgTreeNode', props: { data: Object } } </script> <style> /* ... */ </style>
次に、このコンポーネントをレンダリングすると、効果は次のようになります
この時点で、単純な構成構造 ツリーコンポーネントが完成しました。
しかし、事態はまだ終わっていません。 。 。
要件: ノードのラベルはカスタマイズをサポートし、ツリーは水平表示をサポートする必要があります。
そのため、再帰コンポーネントに次の変更を加えました:
<template> <p class="org-tree-node"> <p class="org-tree-node-label"> <slot>{{data.label}}</slot> </p> <p class="org-tree-node-children" v-if="data.children"> <org-tree-node v-for="node in data.children" :data="node" :key="data.id"></org-tree-node> </p> </p> </template> <script> export default { name: 'OrgTreeNode', props: { data: Object } } </script> <style> /* ... */ </style>
ラベルのカスタマイズをサポートするためにスロットスロットを使用しましたが、問題が再び発生しました: カスタマイズできるのは第 1 レベルのノードラベルと、ネストされた子ノードのみであることがわかりました。スロットスロットを効果的に渡すことができません。長い間オンラインで検索しても結果がなかったので、公式ドキュメントを見ました。機能的なコンポーネントが見つかりました。以前に element-ui のツリー コンポーネントを使用したことがあったので、element-ui のツリー コンポーネントと同じように renderContent 関数を渡すことを思いつき、呼び出し元が自分でノード ラベルをレンダリングできるため、ノードのカスタマイズの目的を達成できます。 !
機能コンポーネント
次に、ツリーノードテンプレートコンポーネントを機能コンポーネントに変換します。 Node.js の書き方:
まず render 関数を実装します
export const render = (h, context) => { const {props} = context return renderNode(h, props.data, context) }
renderNode 関数を実装します
export const renderNode = (h, data, context) => { const {props} = context const childNodes = [] childNodes.push(renderLabel(h, data, context)) if (props.data.children && props.data.children.length) { childNodes.push(renderChildren(h, props.data.children, context)) } return h('p', { domProps: { className: 'org-tree-node' } }, childNodes) }
renderLabel 関数を実装します。ノード ラベルのカスタマイズの鍵は次のとおりです:
export const renderLabel = (h, data, context) => { const {props} = context const renderContent = props.renderContent const childNodes = [] // 节点label定制,由调用者传入的renderContent实现 if (typeof renderContent === 'function') { let vnode = renderContent(h, props.data) vnode && childNodes.push(vnode) } else { childNodes.push(props.data.label) } return h('p', { domProps: { className: 'org-tree-node-label' } }, childNodes) }
renderChildren 関数を実装します。ここで、renderNode が再帰的に呼び出され、再帰コンポーネントが実装されます
export const renderChildren = (h, list, context) => { if (Array.isArray(list) && list.length) { const children = list.map(item => { return renderNode(h, item, context) }) return h('p', { domProps: { className: 'org-tree-node-children' } }, children) } return '' }
これで、render 関数が完成しました。 次に、render 関数を使用して機能コンポーネントを定義します。ツリーコンポーネントで宣言します:
<template> <!-- ... --> </template> <script> import render from './node.js' export default { name: 'OrgTree', components: { OrgTreeNode: { render, // 定义函数式组件 functional: true } } } </script>
この時点で、機能コンポーネントの変換は完了です。水平表示については、スタイル コントロールを使用するだけです。
CSS スタイル
スタイルは、less を使用してプリコンパイルされます。ノード間の線は、:before と :after 擬似要素の境界線を使用して描画されます
機能拡張
ノードラベルのスタイルカスタマイズをサポートするために labelClassName 属性を追加しました
以前に使用されていた labelWidth 属性を追加しましたノードラベルの幅を制限します
props 属性を追加しました。複雑なデータ構造をサポートするために、element-ui のツリーコンポーネントの props 属性を参照します
子の展開と拡張をサポートするために、collapseable 属性を追加しましたノードの折りたたみ (展開と折りたたみの操作は呼び出し側で実装する必要があります)
最初はフレックス レイアウトが使用されていましたが、IE9 と互換性がある必要があり、後に表示に変更されました: テーブル レイアウト
最終的な効果:
デフォルト
水平
問題の概要
各ノードのステータスを保存するツリーストアを定義できるため、ツリーノードの展開状態と折りたたみ状態を確認できます。内部的にメンテナンスできます
上記は私が皆さんのためにまとめたものです。将来的に皆さんのお役に立てれば幸いです。
関連記事:
WeChatアプレットに画像アップロードなどの一連の機能を実装する方法
以上がVue を使用して組織構造ツリー コンポーネントを作成する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。