tree组件的经验总结
最近项目中有了树形结构的功能需求,要求能够将分类信息使用树形结构展示、新增节点、删除节点、选择节点等功能,项目中使用了iview框架作为视图层框架,iview本身也提供了树形结构示例,但是其ui风格并不符合设计稿需求,没办法一开始的想法是请求外援,网上找到了jquery的著名插件ztree插件,其功能非常强大完全符合项目的功能性需求,但是由于项目是基于vue技术构建,考虑除非非常必要否则都不用jquery插件的原则,又找到了开源框架vue-ztree,它是基于ztree使用vue实现的树形结构,同样非常强大,但是ui风格依旧不符合设计稿,也没有看到可以自定义ui的地方,本着不能谈论别人的精彩,让自己永远是一个看客的技术原则,所以尝试开发了这个tree组件,由于技术浅薄所以该组件仅仅为了满足个人项目需要和自己的技术积累习惯以及给像我一样想实现自己tree组件的人一个参考写下了这篇文章。
该组件的开发环境为:vue-cli2.x脚手架工具创建的项目,iview3.x作为组件视图层框架,vue全家桶技术,stylus作为css解析器。其实该组件也就使用了iview3.x的icon图标而已,完全可以使用自己的icon来代替。先来谈下实现思路,一开始看到项目设计稿需求决定自己写时,就想到了它的html骨架结构,它应该是一个ul>li无序列表嵌套组合,并且是一个递归循环的结构,而vue本身就支持递归组件,戳我https://cn.vuejs.org/v2/guide/components-edge-cases.html,里面有递归组件的定义要求,至此html结构构思完成,下一步是侦听tree组件事件,如何展开收起,如何侦听选择节点的点击事件,如何新增、删除等等,在这个过程里一开始想到的vue里面的父子组件的事件传递机制,但是踩了一个坑,好像对于递归组件,外层父组件不能够像平常的方式去侦听,如下的方式:
#父组件
<div class="parent-tree">
<BasicTree @add="addNode"></BasicTree>
</div>
...addNode(target) {
console.log('监听tree组件',target);
}
#tree组件
<BasicTree>
<template>
.....this.$emit('add',event.target);
</template>
通过上述方式完全监听不到tree组件往外抛出的事件,我能想到的是因为是递归组件,本身就是自身引用,既是子组件又是自己的父组件,如果像这种方式去监听往外抛出的事件需要一层层往外抛出,非常麻烦,所以路过的大神对于这种情况还望能够详细描述这个事件的传递过程。
这种方式在我这里行不通,只能另想别的办法,还好vue提供了vuex作为全局状态管理机制,所以决定所有的事件和传值都通过vuex来进行全局注入,废话不多说直接贴源码
#父组件KnowledgeQuery组件
<template>
<div class="knowledge-query">
<!--左侧布局-->
<div class="left-wrapper">
<!--搜索框-->
<div class="search-wrapper">
<div class="input-wrapper">
<input type="text" v-model="keywordSearch"
@keyup.enter="searchKnowledge"
placeholder="请输入关键词搜索">
<span class="icon" @click="delKeywordSearch"><Icon type="ios-close"/></span>
<span class="search-btn" @click="searchKnowledge(1)">搜索</span>
</div>
<div class="result-wrapper" v-if="IsResultListShow">
<ul>
<li v-for="(item,index) in searchListData" class="item-list"
@click="choiceValue(item.result)" :key="index">
{
{item.result}}
</li>
</ul>
</div>
</div>
<!--内容区-->
<div class="content-wrapper" @click="hideResultList">
<h1 class="title-hide" v-show="!keywordSearch.length">暂无搜索条件以下为默认搜索结果</h1>
<h1 class="title" v-show="keywordSearch.length">大约有<span
class="num">236</span>项与 “<span class="key">{
{keywordSearch}}</span>” 相关的搜索结果</h1>
<ul>
<li v-for="(result,index) in resultListData" class="result-list"
@click="navictionUrl(1)"
:key="index">
<h1 class="title" v-html="result.title"></h1>
<div class="content">
<div class="img-wrapper" v-show="result.img.length">
<img :src="result.img" width="124" height="84">
</div>
<div class="text-wrapper">
<h1 class="top-wrapper">{
{result.desc}}</h1>
<div class="bottom-wrapper">
<span class="time">{
{result.time}}</span>
<span class="classify">{
{result.classify}}</span>
<span class="user">{
{result.reportUser}}</span>
</div>
</div>
</div>
</li>
</ul>
<div class="page">
<Page @on-change="searchKnowledge" :total="100" show-total/>
</div>
</div>
</div>
<!--右侧布局-->
<div class="right-wrapper" @click="hideResultList">
<!--添加知识库-->
<div class="add-wrapper">
<div class="btn-wrapper" @click="addKnowledge">
<span class="icon-knowledge"><Icon type="ios-cloud-upload-outline"/></span>
<span class="btn">添加知识库</span>
</div>
<div class="text">已有<span class="total">3166</span>份知识库资料</div>
<h1 class="nums">363</h1>
<p class="new-text">今日新增知识库</p>
</div>
<!--树形结构-->
<div class="tree-wrapper">
<div class="title-wrapper">
<span class="border"></span>
<span class="tree-title">知识库分类</span>
</div>
<div class="tree" ref="treeWrapper">
<BasicTree :treeList="treeList" :funcFlag="funcFlag"></BasicTree>
</div>
</div>
</div>
</div>
</template>
<script type="text/ecmascript-6">
import axios from 'axios';
import { mapState, mapMutations } from 'vuex';
import BasicTree from 'base/tree/BasicTree.vue';
export default {
name: 'KnowledgeQuery',
data () {
return {
IsResultListShow: false, // 搜索列表显示隐藏的开关
searchListData: [
{result: '打印机卡纸在什么位置'},
{result: '打印机卡纸的解决办法'},
{result: '打印机卡纸了怎么把它拿出来'},
{result: '电脑没法联网'},
{result: '怎么清理电脑c盘'},
{result: '笔记本电脑屏保损坏'}
], // 存放搜索列表的数组
resultListData: [
{
title: '<font color="#f14f4f">打印机卡纸</font>',
img: 'https://gd4.alicdn.com/imgextra/i4/3275704363/TB2E2okfOFTMKJjSZFAXXckJpXa_!!3275704363.jpg',
desc: '打印机不能打印大都是因为进出纸部件损坏,就是滚纸那个轴;纸路传感器故障,驱动部件失灵,还有可能是同时进了多张纸甚至纸张的质量差也会导致卡纸等等',
time: '2018年12月16号',
classify: '打印机卡纸',
reportUser: '张云飞'
},
{
title: '针式<font color="#f14f4f">打印机卡纸</font>',
img: 'https://gd3.alicdn.com/imgextra/i3/246349854/TB2jqJVcXmWBuNjSspdXXbugXXa_!!246349854.jpg',
desc: '打印机不能打印大都是因为进出纸部件损坏,就是滚纸那个轴;纸路传感器故障,驱动部件失灵,还有可能是同时进了多张纸甚至纸张的质量差也会导致卡纸等等',
time: '2018年12月16号',
classify: '打印机卡纸',
reportUser: '张云飞'
},
{
title: '<font color="#f14f4f">打印机卡纸</font>进纸器损坏',
img: 'https://gd3.alicdn.com/imgextra/i3/246349854/TB2H9D4dkfb_uJkSmLyXXcxoXXa_!!246349854.jpg',
desc: '打印机不能打印大都是因为进出纸部件损坏,就是滚纸那个轴;纸路传感器故障,驱动部件失灵,还有可能是同时进了多张纸甚至纸张的质量差也会导致卡纸等等',
time: '2018年12月16号',
classify: '打印机卡纸',
reportUser: '张云飞'
},
{
title: '喷墨<font color="#f14f4f">打印机卡纸</font>',
img: 'https://gd1.alicdn.com/imgextra/i1/246349854/TB2xl4ZlDnI8KJjy0FfXXcdoVXa_!!246349854.png',
desc: '打印机不能打印大都是因为进出纸部件损坏,就是滚纸那个轴;纸路传感器故障,驱动部件失灵,还有可能是同时进了多张纸甚至纸张的质量差也会导致卡纸等等',
time: '2018年12月1