美文网首页
vuetify tree diy

vuetify tree diy

作者: 吴宪峰 | 来源:发表于2019-04-13 19:40 被阅读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>
    

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

    相关文章

      网友评论

          本文标题:vuetify tree diy

          本文链接:https://www.haomeiwen.com/subject/dpmrwqtx.html