質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.51%
Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

Q&A

解決済

1回答

1015閲覧

TypeScript配列の特殊なソート

退会済みユーザー

退会済みユーザー

総合スコア0

Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

0グッド

0クリップ

投稿2018/08/13 03:17

編集2018/08/14 10:31

少し説明が難しいのですが、なるべくコードなども簡略化してみますので、読んでくだされば幸いです(T_T)

https://github.com/holiber/sl-vue-tree

↑こちらの、リストのソートをするライブラリを使用しました。

typescript

1//拡張子は.vueです。vueクラスコンポーネントを使ってます。 2 3<template> 4 <div class="objectList"> 5 <div class="objectArea"> 6 <SlVueTree ref="SlVueTree" v-model="objectList"> 7 8 </SlVueTree> 9 </div> 10 </div> 11</template> 12 13<script lang="ts"> 14import { Component, Prop, Vue } from "vue-property-decorator"; 15 16import SlVueTree from 'sl-vue-tree' 17 18 19@Component({ 20 components: { 21 SlVueTree 22 } 23}) 24 25export default class ObjectList extends Vue { 26 27 28 get objectList() { 29 return this.$store.getters.objectList; 30 } 31 32 set objectList(updatedObjectList) { 33 this.$store.dispatch('edit/sortObjectList' , updatedObjectList) 34 } 35} 36</script> 37 38<style lang="scss"> 39 40</style> 41 42

vuexとこちらのライブラリを組み合わせる場合、上のように、getとsetを使います。
setはドラッグ&ドロップした時に呼ばれます。

set objectList(updatedObjectList) {
this.$store.dispatch('edit/sortObjectList' , updatedObjectList)
}

↑ここでは、ソートされた結果(updatedObjectList)を元々のobjectListに格納しています。
(objectList = updatedObjectListみたいなことをする)
そうすることで、

get objectList() {
return this.$store.getters.objectList;
}

ここが変化し、ソートができます。
データはgetとバインドされています。

しかし、こちらのライブラリ、
objectListのモデルに含まれた"関数"に関しては、updatedObjectListに入ってくれないです。
updatedObjectListに入ってくれるのはプロパティのみです。

したがって、

objectList=updatedObjectList

のように上書きするのではなく、

元々のobjectListをupdatedObjectListに従ってソートするということをしたいです。

例えば、

元々のobjectListが

typescript

1 2let objectList = [ 3 4 { 5 objectId : 1, 6 objectName : "オブジェクト1", 7 objectList : [], 8 isLeaf : false, 9 children : [] 10 }, 11 { 12 objectId : 2, 13 objectName : "オブジェクト2", 14 objectList : [], 15 isLeaf : true 16 }, 17 { 18 objectId : 3, 19 objectName : "オブジェクト3", 20 objectList : [], 21 isLeaf : false, 22 children : [] 23 }, 24 { 25 objectId : 4, 26 objectName : "オブジェクト4", 27 objectList : [], 28 isLeaf : true 29 }, 30 { 31 objectId : 5, 32 objectName : "オブジェクト5", 33 objectList : [], 34 isLeaf : false, 35 children : [] 36 }, 37 38] 39 40

で、updatedObjectListが

typescript

1 2let updatedObjectList = [ 3 { 4 objectId : 5, 5 objectName : "オブジェクト5", 6 objectList : [], 7 isLeaf : false, 8 children : [] 9 }, 10 { 11 objectId : 3, 12 objectName : "オブジェクト3", 13   objectList : [], 14 isLeaf : false, 15 children : [ 16 { 17 objectId : 2, 18 objectName : "オブジェクト2", 19 objectList : [], 20 isLeaf : true 21 }, 22 { 23 objectId : 1, 24 objectName : "オブジェクト1", 25 objectList : [], 26 isLeaf : false, 27 children : [ 28 { 29 objectId : 4, 30 objectName : "オブジェクト4", 31 objectList : [], 32 isLeaf : true 33 }, 34 ] 35 }, 36 ] 37 } 38] 39

だった場合、

objectList = updatedObjectListとするのではなく

"objectListをソートして、"updatedObjectListと同じ構造にするためにはどのようにすればよろしいでしょうか。

親になることができるobjectは

isLeaf : false

というパラメーターを持ちます。
そして、子はchildrenという名前のパラメーターに入ります。
しかし、childrenに格納することに加えて、同じものを、objectListというパラメーターに格納したいです。
linq-es2015という,typescript用のlinqモジュールも使えますので、linqを使うこともできます。
ただc#のlinqと全く同じメソッドが定義されている訳ではありません。

-追記-

dataにプロパティで任意のプロパティを持っても、関数が渡されなかった
以下はvuexのルートモデルの一部

typescript

1import { ImageObject } from './image/imageObject' 2 3import { ObjectData } from './objectData' 4 5export class Object{ 6 7 public title : string = "" 8 9 public isLeaf : boolean = true 10 11 public data : ObjectData = new ObjectData("") 12 13 constructor(object : {objectType : string , objectId : number}){ 14 15 if(object.objectType == "imageObject"){ 16 this.data = new ImageObject(object) 17 //imageObjectはobjectDataをextendしている 18 } 19 } 20 21}

typescript

1 2import { OuterRect } from './rect/outerRect' 3 4/** 挿入データ(文字とか画像とか)の状態のうち、全てのデータで共有する要素 */ 5export class ObjectData{ 6 7 public objectId : number = 0 8 9 public objectType : string = "" 10 11 public name : string = "" 12 13 public selected : boolean = false 14 15 public outerRect : OuterRect = new OuterRect("string") 16 17 constructor(objectType : string){ 18 this.objectType = objectType 19 if(objectType!=""){ 20 this.outerRect = new OuterRect(objectType) 21 } 22 } 23 24 public changeState(state : { value : string , stateType : string }){ 25 26 27 } 28 29} 30

このようにobjectDataにも関数はありますし、outerRectにも関数があるのですが、それらが順番を変えたりすると(objectList = updatedObjectListをすると)、消えてしまいます。

data.outerRect.function is not a function とエラーが出てしまいます。

-追記-

そしてやはり並び替えだとうまくいきます

typescript

1 2let objectList = this.objectList 3 4this.objectList = [] 5 6for(var i = 0; i < updatedObjectList.length; i++){ 7 this.objectList.unshift(Enumerable.asEnumerable(objectList).Where(x=>x.objectId==updatedObjectList[i].objectId).ToArray()[0]) 8} 9

ただし、これはグループ化をしておらず、一階層目だけでオブジェクトを入れ替えているだけです。
階層構造も含めて
updatedObjectと同じ構造にしたいです...

-追記-
https://ja.stackoverflow.com/questions/47499/typescript-%E9%85%8D%E5%88%97%E3%81%AE%E7%89%B9%E6%AE%8A%E3%81%AA%E3%82%BD%E3%83%BC%E3%83%88

こちら、スタックオーバーフローにほとんど同じ質問をしたところ、マルチポストであるというご指摘を頂きました。
配列をソートする方法自体に関しては、スタックオーバーフローの方で回答をいただけました。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

ノードの型が下記のインターフェイスで定義されているので、data プロパティに任意のデータを持たせれば良いのではないでしょうか。たぶん関数でも問題なく保持されます。インターフェイスに定義されていない objectId なども data プロパティに移したほうが良いかなと思います。

typescript

1interface ISlTreeNodeModel<TDataType> { 2 title: string; 3 isLeaf?: boolean; 4 children?: ISlTreeNodeModel<TDataType>[]; 5 isExpanded?: boolean; 6 isSelected?: boolean; 7 isDraggable?: boolean; 8 isSelectable?: boolean; 9 data?: TDataType; 10} 11interface ISlTreeNode<TDataType> extends ISlTreeNodeModel<TDataType> { 12 isVisible?: boolean; 13 isFirstChild: boolean; 14 isLastChild: boolean; 15 ind: number; 16 level: number; 17 path: number[]; 18 pathStr: string; 19 children: ISlTreeNode<TDataType>[]; 20}

投稿2018/08/13 05:51

yhg

総合スコア2161

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/08/13 05:59

yhgさん!!!!! ありがとうございます なるほどです、任意のプロパティや関数はdataに持たせるのですね、やってみます!!!
退会済みユーザー

退会済みユーザー

2018/08/13 07:24

すみません、dataで持ってみたのですが、やはり関数は渡されませんでした...。
退会済みユーザー

退会済みユーザー

2018/08/13 09:17 編集

今、setのfunctionを消してgetだけにしてみたのですが、その場合、vuexのstateと直接バインドすることになってしまうため、 Computed property "objectList" was assigned to but it has no setter. とエラーが出てしまうのですが、ちゃんと動きました。 入れ替えを行ってもちゃんと関数ごと入れ替えされました...
退会済みユーザー

退会済みユーザー

2018/08/13 09:30

すみません、関数ごと入れ替えれたと思ったのですが、表示上入れ替えれただけで、objectListのデータ自体は何も変わってませんでした... やはりsetの中で明示的に処理をしたいです...
yhg

2018/08/13 14:13

原因わかりました。こちらのメソッドのせいでメソッド全削除されてますね。この部分を書き換えてきちんとクラスインスタンスとしてディープコピーできるようにすれば上手くいくかと思います。あと Issue 出しておくのも良いかもしれません。 https://github.com/holiber/sl-vue-tree/blob/master/src/sl-vue-tree.js#L715
退会済みユーザー

退会済みユーザー

2018/08/14 09:26 編集

本当にありがとうございます... でもごめんなさい、ちょっと難しいです... JSON.stringifyをしてしまうと、関数も文字列化してしまうということでしょうか.. あと、親に子を含ませた時に、やりたい処理ができてしまった(やりたい処理が生まれてしまった)のですが、そういった場合も考慮すると入れ替えの方が良いのかなとか思ってしまいました 入れ替えの処理のなかに自分がやりたい処理を入れたりできそうなので
yhg

2018/08/14 05:08

JSON.stringify すると関数が全て消えます。 JSON.stringify({ a: function(){} }) → {} のようになります。 やりたいことが出来たのなら良いのですが、一応ライブラリを書き換える方法も記載しておきますね。 1. github.com 上のリポジトリを Fork し、ローカルに git clone します。 2. NPM で適当なディープコピーのライブラリを dependencies としてインストールし、該当箇所を書き換えます。 3. npm run build でビルドします。 4. git で変更をコミットし、リポジトリに push します。 5. アプリケーション側に戻って package.json の dependencies にある sl-vue-tree のバージョンの部分を your-username/sl-vue-tree#master のようにします。 6. npm install しなおします。上手くいかない場合は lock ファイル削除すると良いです。 以上です。プルリク送ったり Issue 建てて公式に変更が取り込まれれば自分でメンテしなくて良くなるので、積極的にプルリク送りましょう。
退会済みユーザー

退会済みユーザー

2018/08/14 09:13

ありがとうございます。 やりたいことできてないです...。 やっぱり objectList をソートして updatedObjectList と同じ構造にするというのをしたいです...。 ありがとうございます。 JSON.stringifyだとDeep Copyできないとか、その他Deep Copyの記事などは見つけたので、試してみたいです...。
退会済みユーザー

退会済みユーザー

2018/08/14 09:43 編集

---------------------------------------------------------------------------------------------------------------------------------------- リポジトリのフォーク GitHub のアカウントを持っていると、自分のアカウント内に既存のリポジトリの複製をつくれたりします。この操作はフォークと呼ばれます。 共有されていないリポジトリに対して書き込むことはできません。一方、フォークしたリポジトリは自分の所有物なので、自由に更新ができます。 つまり、自分のフォークを作れば、共有されていないリポジトリをベースとした作業も (勝手に) 始められることになります。 GitHub には、自分のフォーク内の更新を反映するよう、オリジナルの管理者に依頼する手段があります。この依頼を受け取った管理者が、依頼どおりにオリジナルを更新すれば、リポジトリを共有しない共同開発の実現です。 こちらの方式の場合、調整が必要なのは、オリジナルを更新 (マージ) する際の修正内容だけです。事前に開発者間のコーディネートが不要なため、オープンソースプロジェクト向きと言われています。CreateJS のドキュメント翻訳はこちらの方式をとっています。 ---------------------------------------------------------------------------------------------------------------------------------------- フォークという言葉が分からなかったので調べていたのですが、こんな風に書いてありました。 それでなんですが、フォークして、自分のアカウント内のsl-vue-treeのモジュールのcopyの関数を書き換えてから、自分のフォーク内の更新を反映するよう、オリジナルの管理者に依頼するという手順ではダメなのでしょうか。 ディープコピー用のライブラリをインストールとかbuildする意味ってなんなのでしょうか。 yhgさんが提示してくださった手順では何が起きているのでしょうか。
退会済みユーザー

退会済みユーザー

2018/08/14 09:53

copy(entity) { return this.deepClone(entity) }, deepClone(object) { console.log("deepClone") //ここで関数が呼ばれているか確認できる let node; if (object === null) { node = object; } else if (Array.isArray(object)) { node = object.slice(0) || []; node.forEach(n => { if (typeof n === 'object' && n !== {} || Array.isArray(n)) { n = deepClone(n); } }); } else if (typeof object === 'object') { node = Object.assign({}, object); Object.keys(node).forEach(key => { if (typeof node[key] === 'object' && node[key] !== {}) { node[key] = deepClone(node[key]); } }); } else { node = object; } return node; } 今試しに、ライブラリの中を直接上のようにしてみたのですが、deepClone関数は呼ばれていませんでした...。 yhgさんが提示してくださった手順でないと、ライブラリの変更は反映できないのでしょうか。
yhg

2018/08/14 11:01

たぶん src 以下のファイルをいじってるので実行されないのだと思います。 dist/sl-vue-tree.js を修正すると実行されると思いますが、minify されてるので読みづらいです。ソートのほう解決されたのなら何よりです。
退会済みユーザー

退会済みユーザー

2018/08/14 12:03 編集

なるほどです、実際に呼ばれてるのはminの方なのですね...。 提示してくださった手順のうちの3のビルドというのは、 このminを作り直すということでしょうか。 普通に npm run build コマンドを利用すると、distフォルダが作られて、その中身をサーバーにアップロードすることでwebアプリをそのサーバーで使えるようになると思うのですが、ライブラリやモジュールを書き換えることとどう関連するのでしょうか。
yhg

2018/08/14 13:57

npm run build するのはライブラリのディレクトリ内で、です。src 以下のファイルを編集しても実際に読み込まれるのは minify されたほうなのでライブラリのほうをビルドしなおす必要があるということです。
退会済みユーザー

退会済みユーザー

2018/08/15 00:38

なるほどです!!! 分かってきました。 ライブラリのディレクトリ内でnpm run build のコマンドが使え、そしてそれでminファイルをビルドできるとは知りませんでした。 やっと提示してくださった6っつの手順の意味が分かってきました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.51%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問