vuetify tree diy

2019-04-13  本文已影响0人  吴宪峰
屏幕快照 2019-04-13 下午7.35.07.png

找不到合适的工作,弄完这个就去开出租车糊口了。

对于一个40多半路出家,学了7、8年的伪码农,接触vue一个月了,感觉进度很慢,把代码记下来备忘,有很多不足的地方等有时间再优化下。

基础差,花了大半天google了关于vuetify treevie的例子,在跟服务取数据添充时总是出错,youtube上看了毛子的例子,还是不会用,没办法回到vue,油管上看了一个排在前边的,花了不到20分钟,样式是看懂了,没有添加删除节点的代码,第二天花了一天时间才把这个组件弄完,包括跟后端交互。

treeview.vue

<template>
  <ul>
    <li v-ripple>
      <v-layout align-center justify-start row fill-height>
        <v-icon left>{{ icon }}</v-icon>
        <label @click="toggle">{{ node.name }}</label>
        <v-spacer></v-spacer>
        <v-btn v-show="!hasChildren&&!noRoot" @click="deleteClicked">删除</v-btn>
        <v-btn v-show="!noRoot" @click="editClicked">编辑</v-btn>
        <v-btn @click="appendClicked">添加下级</v-btn>
      </v-layout>
    </li>
    <ul v-if="open">
      <tree-view
        v-for="(child,index) in node.children"
        :key="index"
        :node="child"
        :depth="depth + 1"
        @onDeleteClick="(node)=>$emit('onDeleteClick',node)"
        @onEditClick="(node)=>$emit('onEditClick',node)"
        @onAppendClick="(node)=>$emit('onAppendClick',node)"
      ></tree-view>
    </ul>
  </ul>
</template>
<script>
export default {
  name: "tree-view",
  data() {
    return {
      open: true
    };
  },
  props: {
    node: Object,
    depth: {
      type: Number,
      default: 0
    }
  },
  computed: {
    // 判断是否根结点,不显示 删除 编辑 按钮
    noRoot(){
      return this.node.name==='root'
    },
    // 是否有子结点 显示不同的图标
    hasChildren() {
      return this.node.children && this.node.children.length;
    },
    // 图标
    icon() {
      return this.hasChildren
        ? this.open
          ? "arrow_drop_down"
          : "arrow_right"
        : "note";
    }
  },
  methods: {
    // 三个操作结点的事件
    deleteClicked() {
      if (!this.hasChildren) {
        this.$emit("onDeleteClick", this.node);
      }
    },
    editClicked(){
        this.$emit("onEditClick", this.node);
    },
    appendClicked(){
        this.open = true
        this.$emit("onAppendClick", this.node);
    },
    // 打开关闭节点
    toggle() {
      if (this.hasChildren) {
        this.open = !this.open;
        return;
      }
    },
  }
};
</script>
<style>
ui,
li {
  list-style: none;
}
</style>

调用

<template>
  <div>
    <v-dialog v-model="dialog" max-width="500px">
      <v-card>
        <v-card-title>
          <span class="headline">{{ formTitle }}</span>
        </v-card-title>

        <v-card-text>
          <v-container grid-list-md>
            <v-layout wrap>
              <v-flex xs12 sm12 md12>
                <v-text-field label="上级分类" v-model="editedItem.parent.name" disabled></v-text-field>
              </v-flex>
              <v-flex xs12 sm12 md12>
                <v-text-field v-model="editedItem.name" label="名称"></v-text-field>
              </v-flex>
            </v-layout>
          </v-container>
        </v-card-text>

        <v-card-actions>
          <v-spacer></v-spacer>
          <v-btn color="blue darken-1" flat @click="close">Cancel</v-btn>
          <v-btn color="blue darken-1" flat @click="save">Save</v-btn>
        </v-card-actions>
      </v-card>
    </v-dialog>
    <tree-view
      :node="tree"
      @onDeleteClick="nodeDeleteClick"
      @onAppendClick="nodeAppendClick"
      @onEditClick="nodeEditClick"
    ></tree-view>
  </div>
</template>
<script>
import TreeView from "../../components/TreeView";
import instance from "../../axios";
export default {
  data() {
    return {
      tree: {}, 
      dialog: false,
      editfield: false,
      formTitle: "添加分类",
      targetItem: {},
      editedItem: {
        id: 0,
        name: "",
        p_id: 0,
        children: [],
        parent: { name: "" }
      },
      defaultItem: {
        id: 0,
        name: "",
        p_id: 0,
        children: [],
        parent: { name: "" }
      }
    };
  },
  created() {
    this.getmessagetype();
  },
  methods: {
    // 删除操作
    nodeDeleteClick(node) {
      if (confirm("确认要删除此条记录吗?")) {
        instance({
          method: "delete",
          url: "/api/v1/admin/messagetype/" + node.id
        }).then(response => {
          if (response.data.code > 0) {
            this.changetree(node, this.tree, null, "delete");
          } else {
            alert(response.data.msg);
          }
        });
      }
    },
    // 打开编辑对话框
    nodeEditClick(node) {
      this.editfield = true;
      this.targetItem = node;
      this.editedItem = { id: node.id, name: node.name, p_id: node.p_id };
      this.editedItem.parent = this.getparent(node, this.tree);
      this.dialog = true;
    },
    // 打开添加对话框
    nodeAppendClick(node) {
      this.editfield = false;
      this.targetItem = node;
      this.editedItem.parent = node;
      this.dialog = true;
    },
    // 后端取得树结构数据
    getmessagetype() {
      instance({
        method: "get",
        url: "/api/v1/admin/messagetype"
      }).then(response => {
        if (response.data.code > 0) {
          this.tree = response.data.data;
        } else {
          alert(response.data.msg);
        }
      });
    },
    // 关闭对话框
    close() {
      Object.assign(this.editedItem, this.defaultItem);
      this.dialog = false;
    },
    // 保存
    save() {
      if (!this.editfield) {
        // 添加
        let data = {
          name: this.editedItem.name,
          pid: this.editedItem.parent.id
        };
        instance({
          method: "post",
          url: "/api/v1/admin/messagetype",
          data
        }).then(response => {
          if (response.data.code == 200) {
            this.changetree(
              this.targetItem,
              this.tree,
              {
                id: response.data.data.id,
                name: response.data.data.name,
                p_id: response.data.data.p_id
              },
              "append"
            );
          } else {
            alert(response.data.msg);
          }
        });
      } else {
        // 编辑
        let data = {
          id: this.editedItem.id,
          name: this.editedItem.name,
          pid: this.editedItem.parent.id
        };
        instance({
          method: "put",
          url: "/api/v1/admin/messagetype",
          data
        }).then(response => {
          if (response.data.code == 200) {
            this.targetItem.name = response.data.data.name;
          } else {
            alert(response.data.msg);
          }
        });
      }

      this.close();
    },
    // 从树结构中查找结定结点的父结点
    getparent(node, tree) {
      if (tree.children) {
        for (let i = 0; i < tree.children.length; i++) {
          if (tree.children[i].id == node.id) {
            return tree;
          }
        }
        for (let i = 0; i < tree.children.length; i++) {
          let p = this.getparent(node, tree.children[i]);
          if (p != null) {
            return p;
          }
        }
      }
      return null;
    },
    // 添加 或 删除 结点
    changetree(node, tree, newnode, methed) {
      // 判断根结点匹配
      if (node.id == tree.id) {
        if (methed == "append") {
          if (!tree.children) {
            this.$set(tree, "children", []);
          }
          tree.children.push({
            id: newnode.id,
            name: newnode.name,
            p_id: node.id
          });
          return true;
        }
      }
      // 判断子节点匹配
      if (tree.children && tree.children.length) {
        let found = false;
        for (let i = 0; i < tree.children.length; i++) {
          if (node.id !== tree.children[i].id) {
            continue;
          }
          found = true;
          if (methed == "append") {
            if (!tree.children[i].children) {
              this.$set(tree.children[i], "children", []);
            }
            tree.children[i].children.push({
              id: newnode.id,
              name: newnode.name,
              p_id: node.id
            });
            return found;
          } else if (methed == "delete") {
            tree.children.splice(i, 1);
            return found;
          } else {
            return found;
          }
        }
        if (!found) {
          // 递归匹配
          for (let i = 0; i < tree.children.length; i++) {
            if (!tree.children[i].children) {
              continue;
            }
            found = this.changetree(node, tree.children[i], newnode, methed);
            if (found) {
              return found;
            }
          }
        }
        return found;
      }
    }
  },
  components: {
    TreeView
  }
};
</script>

修改组件回传的节点可以直接修改节点。

上一篇下一篇

猜你喜欢

热点阅读