ANt-design-vueのtreeの添削操作方法
18335 ワード
1.使用背景
新規プロジェクトでは
2.現在の痛み
公式ヘルプドキュメントを読むことによって、ツリーコントロールに対してデータをバインディングする必要があります。ツリーロードが成功したら、現在のツリーに同じクラスと下級ノードを追加したいです。どうやって操作すればいいですか? ツリーロードが成功したら、ツリーノードのいずれかを変更したいです。どうやって操作すればいいですか? ツリーロードが成功したら、ツリーノードを削除したいです。どうやって操作すればいいですか?
以上の操作は、ツリーコントロールを再ロードしないで完成することを要求します。テストを経て、三つの実行可能な方案を整理しました。 データ駆動 作用分域スロット ノードイベント
3.データ駆動はツリーノードの添削を実現する。
私たちはヘルプドキュメントにバックエンドが構築されたデータである場合、このツリーデータの中を巡回してこのkey値に対応するオブジェクトを見つける必要があります。トップノードを通して再帰的に検索することが考えられます。しかし、コントロールはすべてレンダリングされました。ノードごとのデータを知っています。なぜ再検索しますか? バックエンドが1つの配列だけに戻ると、これは先ほどこの部分のデータをオブジェクトとして再構築する必要があると述べました。このようにこのオブジェクトを検索するとまた2つのケースに分けられます。
a.リストデータと構築されたツリーオブジェクトがクローニングされている場合、リストのオブジェクトのアドレスとツリーの形の同じkey値オブジェクトのアドレスが異なっています。方法1で再構成されたツリーデータを遍歴する必要があります。
b.リストデータのオブジェクトと構築後のノードが同じオブジェクトアドレスであれば、このリストデータを直接検索して対応するオブジェクトを得ることができる。
だから、気持ちが悪いところは良い木を作ることにあります。私はこの木を見て、あるノードを探します。あるいは方案bという空間を使って時間を変えます。
ここでは、データはすでにツリー型のデータフォーマットに構築されていると仮定します。データ駆動を実現するための最初の任務は二つのコア方法を完成する必要があります。は、現在のノードkey値に基づいて、ノードオブジェクト を検索する。は、現在のノードkey値から親レベルノードchildrenセット を検索する。
二つの方法コードはそれぞれ以下の通りです。
同じレベルのノードを追加するには、現在選択されているノードの親レベルの
上の基礎があれば、下のレベルを追加するのは簡単です。唯一の注意点は、取得したオブジェクトのチルドレン属性が存在しない可能性があります。このとき、私たちは$set方式で属性を追加する必要があります。
バインディングオブジェクトを取得することができ、ノード値を変更することも簡単になり、追加したものと同じように
同じレベルの削除と追加は、親レベルのノード
スロット方式でオブジェクトを取得すると、現在のノードに対応する属性値であり、浅いコピーである。ソース
オブジェクトを入手しましたが、コピーだけですので、
修正も同じですが、上に
明らかに削除してもいけません。
上の方はスロット方式を通して、修正機能を実現しました。がっかりしましたか?でも、設計の角度から考えてみます。相手にカスタマイズをしてあげるだけでいいです。公式アプリを読み続けて、事件の中の
次に、これを説明します。文書には現れていない
ファイル
この二つの知识を明らかにしたら、私たちがやるべき操作は简単になります。イベントドライバページのコードは以下の通りです。
5.1同級を追加
vue仮想domを利用して、親レベルを見つけます。
直接オブジェクト
直接修正
vue仮想domによって親レベル
この知識点は、デモから最終的に完成するまでに、前と後の一ヶ月がかかります。ソースを調べたり、テストをしたりして、時間がかかります。でも、この点をはっきり言ってください。価値があると思います。Demoのソースコードが必要なら、下の二次元コードをスキャンしてください。公衆番号に注目してください。
ここで、ant-design-vueのtree添削の操作方法についての文章を紹介します。これに関連して、ant-design-vueのtree添削の内容は以前の文章を検索してください。または、下記の関連記事を引き続きご覧ください。これからもよろしくお願いします。
新規プロジェクトでは
ant-design-vue
コンポーネントライブラリを使用しています。このコンポーネントライブラリは完全に基礎データと双方向結合されたモードで実現されています。フォームコンポーネントだけが少量の方法を提供しています。したがって、ant-design-vue
を使用するときは、データを変更する角度からUI表示効果を切り替える必要があります。しかし、ツリーコントロールa-tree
の使用においては、データ駆動だけを考慮すると、体感効果は本当によくないです。2.現在の痛み
公式ヘルプドキュメントを読むことによって、ツリーコントロールに対してデータをバインディングする必要があります。
children,title,key
属性を含む大きなオブジェクトを構成する必要があります。このようなオブジェクトは後端を通して、このようなJsonオブジェクトを作成するか、後端を先頭のjson配列にするか、先端ルートは上下関係によって構築されます。データはバインディングされています。成功したら、私たちが欲しいUI効果になります。どこが痛いですか?以上の操作は、ツリーコントロールを再ロードしないで完成することを要求します。テストを経て、三つの実行可能な方案を整理しました。
3.データ駆動はツリーノードの添削を実現する。
私たちはヘルプドキュメントに
selectedKeys(.sync)
という属性を見つけることができます。sync
はこの属性が双方向操作をサポートしていることを示しています。しかし、ここで取得したのはkey
の値だけで、必要なバインディングオブジェクトではありません。したがって、このkey値によってこのオブジェクトを見つける必要があります。このオブジェクトを探すのはかなり気持ちが悪いです。b.リストデータのオブジェクトと構築後のノードが同じオブジェクトアドレスであれば、このリストデータを直接検索して対応するオブジェクトを得ることができる。
だから、気持ちが悪いところは良い木を作ることにあります。私はこの木を見て、あるノードを探します。あるいは方案bという空間を使って時間を変えます。
ここでは、データはすでにツリー型のデータフォーマットに構築されていると仮定します。データ駆動を実現するための最初の任務は二つのコア方法を完成する必要があります。
getTreeDataByKey
getTreeParentChilds
二つの方法コードはそれぞれ以下の通りです。
// author:herbert date:20201024 qq:464884492
// key
getTreeDataByKey(childs = [], findKey) {
let finditem = null;
for (let i = 0, len = childs.length; i < len; i++) {
let item = childs[i]
if (item.key !== findKey && item.children && item.children.length > 0) {
finditem = this.getTreeDataByKey(item.children, findKey)
}
if (item.key == findKey) {
finditem = item
}
if (finditem != null) {
break
}
}
return finditem
},
// author:herbert date:20201024 qq:464884492
// key children
getTreeParentChilds(childs = [], findKey) {
let parentChilds = []
for (let i = 0, len = childs.length; i < len; i++) {
let item = childs[i]
if (item.key !== findKey && item.children && item.children.length > 0) {
parentChilds = this.getTreeParentChilds(item.children, findKey)
}
if (item.key == findKey) {
parentChilds = childs
}
if (parentChilds.length > 0) {
break
}
}
return parentChilds
},
3.1同級ノードを追加同じレベルのノードを追加するには、現在選択されているノードの親レベルの
children
配列に追加する必要があります。したがって、追加ノードの難点は、現在選択されているノードのバインディングオブジェクトの親レベルのオブジェクトをどのように見つけるかにあります。ページコードは以下の通りです。
<!-- author:herbert date:20201030 qq:464884492-->
<a-card style="width: 450px;height:550px;float: left;">
<div slot="title">
<h2> ( )<span style="color:blue">@herbert</span></h2>
<div>
<a-button @click="dataDriveAddSame"> </a-button>
<a-divider type="vertical" />
<a-button @click="dataDriveAddSub"> </a-button>
<a-divider type="vertical" />
<a-button @click="dataDriveModify"> </a-button>
<a-divider type="vertical" />
<a-button @click="dataDriveDelete"> </a-button>
</div>
</div>
<a-tree :tree-data="treeData" :defaultExpandAll="true"
:selectedKeys.sync="selectKeys" showLine />
<img src="./assets/gamelogo.png" width="100%" style="margin-top:20px" />
</a-card>
ページコードから分かるように、2つの属性tree-data
、selectedKeys
が再ツリーに結合されています。ここではselectedKeys
バインディング値を通じて、ツリー形の現在選択されているkey
値を取得できます。その後、方法getTreeParentChilds
を使用すれば、同級の追加が可能です。したがって、dataDriveAddSame
コードの使用については以下のように実現されます。
// author:herbert date:20201030 qq:464884492
dataDriveAddSame() {
let parentChilds = this.getTreeParentChilds(this.treeData, this.selectKeys[0])
parentChilds.forEach(item => console.log(item.title));
parentChilds.push({
title: ' , ',
key: new Date().getTime()
})
},
3.2下級を追加する上の基礎があれば、下のレベルを追加するのは簡単です。唯一の注意点は、取得したオブジェクトのチルドレン属性が存在しない可能性があります。このとき、私たちは$set方式で属性を追加する必要があります。
dataDriveAddSub
コードは次のように実現します。
// author:herbert date:20201030 qq:464884492
dataDriveAddSub() {
let selectItem = this.getTreeDataByKey(this.treeData, this.selectKeys[0])
if (!selectItem.children) {
this.$set(selectItem, "children", [])
}
selectItem.children.push({
title: , ,
key: new Date().getTime()
})
this.$forceUpdate()
},
3.3ノードを変更するバインディングオブジェクトを取得することができ、ノード値を変更することも簡単になり、追加したものと同じように
getTreeDataByKey
を使用して現在のオブジェクトを取得し、値を直接修正することができます。dataDriveModify
コードは次のように実現されます。
// author:herbert date:20201030 qq:464884492
dataDriveModify() {
let selectItem = this.getTreeDataByKey(this.treeData, this.selectKeys[0])
selectItem.title = ' , '
},
3.4ノードの削除同じレベルの削除と追加は、親レベルのノード
children
配列を見つける必要があります。現在のオブジェクトは親レベルの配列に対応するインデックスを持っています。dataDriveDelete
コードは次のように実現されます。
// author:herbert date:20201030 qq:464884492
dataDriveDelete() {
let parentChilds = this.getTreeParentChilds(this.treeData, this.selectKeys[0])
let delIndex = parentChilds.findIndex(item => item.key == this.selectKeys[0])
parentChilds.splice(delIndex, 1)
},
4.スロット方式によるツリーノードの添削ant-tree
のappiにおいて、ツリーノード属性title
タイプは文字列でも良いし、スロットでもいいです。ここでは操作対象を取得したいです。ここでは、スコープスロットを使って、対応するページコードは以下の通りです。
<!-- author:herbert date:20201030 qq:464884492-->
<a-card style="width: 450px;height:550px;float: left;">
<div slot="title">
<h2> ( )</h2>
<div>
, <span style="color:blue">@ </span>
</div>
</div>
<a-tree ref="tree1" :tree-data="treeData1" :defaultExpandAll="true" :selectedKeys.sync="selectKeys1" showLine blockNode>
<template v-slot:title="nodeData">
<span>{{nodeData.title}}</span>
<a-button-group style="float:right">
<a-button size="small" @click="slotAddSame(nodeData)" icon="plus-circle" title=" "></a-button>
<a-button size="small" @click="slotAddSub(nodeData)" icon="share-alt" title=" "></a-button>
<a-button size="small" @click="slotModify(nodeData)" icon="form" title=" "></a-button>
<a-button size="small" @click="slotDelete(nodeData)" icon="close-circle" title=" "></a-button>
</a-button-group>
</template>
</a-tree>
<img src="./assets/gamelogo.png" width="100%" style="margin-top:20px" />
</a-card>
4.1同級を追加するスロット方式でオブジェクトを取得すると、現在のノードに対応する属性値であり、浅いコピーである。ソース
string|slot|slot-scope
のvc-tree\src\TreeNode.jsx
は次のようなコードを見つけることができる。
const currentTitle = title;
let $title = currentTitle ? (
<span class={`${prefixCls}-title`}>
{typeof currentTitle === 'function'
? currentTitle({ ...this.$props, ...this.$props.dataRef }, h)
: currentTitle}
</span>
) : (
<span class={`${prefixCls}-title`}>{defaultTitle}</span>
);
このコードからは、datarefが見られます。しかし、公式のヘルプ文書にはこの属性の紹介は全くありません。ソースを見たい学生には福祉としてカウントされていません。コードの面から見ても、デバッグの結果から見ても、スコープを通じて得られたオブジェクトは、親レベルの属性がないので、同級の追加はできません。renderSelector
コードは以下の通りです。
// author:herbert date:20201030 qq:464884492
slotAddSame(nodeItem) {
console.log(nodeItem)
this.$warn({ content: " , , ! , " })
},
4.2下級を追加するオブジェクトを入手しましたが、コピーだけですので、
slotAddSame
をセットしても無駄です。
// author:herbert date:20201030 qq:464884492
slotAddSub(nodeItem) {
if (!nodeItem.children) {
console.log(' , ')
this.$set(nodeItem, "children", [])
}
nodeItem.children.push({
title: this.addSubTitle,
key: new Date().getTime(),
scopedSlots: { title: 'title' },
children: []
})
},
4.3ノードの変更修正も同じですが、上に
children
と書いてあります。ここで簡単に使って、修正titleの値を実現できます。
// author:herbert date:20201030 qq:464884492
slotModify(nodeItem) {
console.log(nodeItem)
console.log('nodeItem Treenode , Title ')
nodeItem.title = ' , '
// dataRef
nodeItem.dataRef.title = nodeItem.title
},
4.4ノードを削除する明らかに削除してもいけません。
// author:herbert date:20201030 qq:464884492
slodDelete(nodeItem) {
console.log(nodeItem)
this.$warn({ content: " , , ! , " })
delete nodeItem.dataRef
},
5.ツリー型イベントをdataRefと組み合わせて実現する上の方はスロット方式を通して、修正機能を実現しました。がっかりしましたか?でも、設計の角度から考えてみます。相手にカスタマイズをしてあげるだけでいいです。公式アプリを読み続けて、事件の中の
dataRef
事件の提供値を見つけて、また私達に大きな空間を与えました。どれぐらいの大きさがありますか?私達はソースコードを見に行きます。まず、私達はselect
のトリガを見つけました。select
ファイルの中で、具体的なコードは以下の通りです。
onSelect(e) {
if (this.isDisabled()) return;
const {
vcTree: { onNodeSelect },
} = this;
e.preventDefault();
onNodeSelect(e, this);
},
コードからはcomponents\vc-tree\src\TreeNode.jsx
onselectが表示されます。実はTreeNode
の中のonNodeSelectedメソッドを呼び出しています。私たちはTree
に対応するコードを見つけました。
onNodeSelect(e, treeNode) {
let { _selectedKeys: selectedKeys } = this.$data;
const { _keyEntities: keyEntities } = this.$data;
const { multiple } = this.$props;
const { selected, eventKey } = getOptionProps(treeNode);
const targetSelected = !selected;
// Update selected keys
if (!targetSelected) {
selectedKeys = arrDel(selectedKeys, eventKey);
} else if (!multiple) {
selectedKeys = [eventKey];
} else {
selectedKeys = arrAdd(selectedKeys, eventKey);
}
// [Legacy] Not found related usage in doc or upper libs
const selectedNodes = selectedKeys
.map(key => {
const entity = keyEntities.get(key);
if (!entity) return null;
return entity.node;
})
.filter(node => node);
this.setUncontrolledState({ _selectedKeys: selectedKeys });
const eventObj = {
event: 'select',
selected: targetSelected,
node: treeNode,
selectedNodes,
nativeEvent: e,
};
this.__emit('update:selectedKeys', selectedKeys);
this.__emit('select', selectedKeys, eventObj);
},
2つの方法に関連して、TreeノードeventObjオブジェクトからコンポーネントcomponents\vc-tree\src\Tree.jsx
がTreeノードをTree Nodeキャッシュデータselect
だけでなく、実際に対応するTreeNodeノードselectedNodes
をレンダリングすることができます。このnode属性があれば、対応するノードの上下関係を得ることができます。次に、これを説明します。文書には現れていない
node
はどんな鬼ですか?ファイル
dataRef
が見つかったのは、対応するcomponents\tree\Tree.jsx
関数の中で、Treeがvc-treeコンポーネントにrender
属性を伝達する必要があることを知ることができます。最終的に使用した転送ノードデータもこの属性名です。二つのキーコードは以下の通りです。
render(){
...
let treeData = props.treeData || treeNodes;
if (treeData) {
treeData = this.updateTreeData(treeData);
}
...
if (treeData) {
vcTreeProps.props.treeData = treeData;
}
return <VcTree {...vcTreeProps} />;
}
上のコードから見れば、コンポーネントの下の呼び出し方法treeData
は、私たちが入ってきたデータを処理しました。この方法のキーコードは以下の通りです。
updateTreeData(treeData) {
const { $slots, $scopedSlots } = this;
const defaultFields = { children: 'children', title: 'title', key: 'key' };
const replaceFields = { ...defaultFields, ...this.$props.replaceFields };
return treeData.map(item => {
const key = item[replaceFields.key];
const children = item[replaceFields.children];
const { on = {}, slots = {}, scopedSlots = {}, class: cls, style, ...restProps } = item;
const treeNodeProps = {
...restProps,
icon: $scopedSlots[scopedSlots.icon] || $slots[slots.icon] || restProps.icon,
switcherIcon:
$scopedSlots[scopedSlots.switcherIcon] ||
$slots[slots.switcherIcon] ||
restProps.switcherIcon,
title:
$scopedSlots[scopedSlots.title] ||
$slots[slots.title] ||
restProps[replaceFields.title],
dataRef: item,
on,
key,
class: cls,
style,
};
if (children) {
// herbert 20200928
if (this.onlyLeafEnable === true) {
treeNodeProps.disabled = true;
}
return { ...treeNodeProps, children: this.updateTreeData(children) };
}
return treeNodeProps;
});
},
}
この方法から私達はupdateTreeData
属性でtreeNodeProps
属性を見つけました。その値はdataRef
に入力されたデータ項目です。この属性は双方向バインディングをサポートしています。このtreeData
は最終的にtreeNodeProps
にレンダリングされます。この二つの知识を明らかにしたら、私たちがやるべき操作は简単になります。イベントドライバページのコードは以下の通りです。
<!-- author:herbert date:20201101 qq:464884492 -->
<a-card style="width: 450px;height:550px;float: left;">
<div slot="title">
<h2> ( dataRef)<span style="color:blue">@464884492</span></h2>
<div>
<a-button @click="eventAddSame"> </a-button>
<a-divider type="vertical" />
<a-button @click="eventAddSub"> </a-button>
<a-divider type="vertical" />
<a-button @click="eventModify"> </a-button>
<a-divider type="vertical" />
<a-button @click="eventDelete"> </a-button>
</div>
</div>
<a-tree :tree-data="treeData2" @select="onEventTreeNodeSelected" :defaultExpandAll="true" :selectedKeys.sync="selectKeys2" showLine />
<img src="./assets/gamelogo.png" width="100%" style="margin-top:20px" />
</a-card>
イベントを通じて駆動されるなら、まず該当イベントを登録しなければなりません。コードは以下の通りです。
// author:herbert date:20201101 qq:464884492
onEventTreeNodeSelected(seleteKeys, e) {
if (e.selected) {
this.eventSelectedNode = e.node
return
}
this.eventSelectedNode = null
},
イベントでは、現在の選択TreeNodeを保存しています。その後の追加修正を削除しやすいです。5.1同級を追加
vue仮想domを利用して、親レベルを見つけます。
// author:herbert date:20201101 qq:464884492
eventAddSame() {
//
let dataRef = this.eventSelectedNode.$parent.dataRef
if (!dataRef.children) {
this.$set(dataRef, 'children', [])
}
dataRef.children.push({
title: ' , ',
key: new Date().getTime()
})
},
5.2下級を追加する直接オブジェクト
components\vc-tree\src\TreeNode.jsx
を使用して、dataRef
はchildren
方法を使用することに注意してください。
// author:herbert date:20201101 qq:464884492
eventAddSub() {
let dataRef = this.eventSelectedNode.dataRef
if (!dataRef.children) {
this.$set(dataRef, 'children', [])
}
dataRef.children.push({
title: ' , bug ',
key: new Date().getTime(),
scopedSlots: { title: 'title' },
children: []
})
},
5.3ノードの変更直接修正
$set
の対応する値を修正する。
// author:herbert date:20201101 qq:464884492
eventModify() {
let dataRef = this.eventSelectedNode.dataRef
dataRef.title = ' , bug'
},
5.4ノードを削除するvue仮想domによって親レベル
dataRef
を見つけ、dataRef
から選択項目を削除すればいいです。
// author:herbert date:20201101 qq:464884492
eventDelete() {
let parentDataRef = this.eventSelectedNode.$parent.dataRef
//
const children = parentDataRef.children
const currentDataRef = this.eventSelectedNode.dataRef
const index = children.indexOf(currentDataRef)
children.splice(index, 1)
}
6.まとめこの知識点は、デモから最終的に完成するまでに、前と後の一ヶ月がかかります。ソースを調べたり、テストをしたりして、時間がかかります。でも、この点をはっきり言ってください。価値があると思います。Demoのソースコードが必要なら、下の二次元コードをスキャンしてください。公衆番号に注目してください。
children
を取得します。ant-tree
のこのセットのコンポーネントライブラリについては、以前使ったant-desgin-vue
のコンポーネントライブラリに比べて、ウェブサイトの展示に適したような感じがします。いくつかのバックグラウンドシステムを作って、大量の操作を提供する必要があります。まだ力がない感じがします。ここで、ant-design-vueのtree添削の操作方法についての文章を紹介します。これに関連して、ant-design-vueのtree添削の内容は以前の文章を検索してください。または、下記の関連記事を引き続きご覧ください。これからもよろしくお願いします。