省市区联动组件
一. V - Distpicker 是一个简单易用的地区选择器
官网: https://distpicker.unie.fun/
安装
npm install v-distpicker --save
全局引入
import VDistpicker from 'v-distpicker'
Vue.component('v-distpicker', VDistpicker)
局部引入(建议)
import VDistpicker from 'v-distpicker'
export default {
components: { VDistpicker }
}
开始使用
<template>
<div>
<v-distpicker :province="select.province" :city="select.city" :area="select.area" @selected="onSelected"></v-distpicker>
</div>
</template>
<script>
import VDistpicker from 'v-distpicker'
export default {
name: "Distpicker",
components: {VDistpicker},
data() {
return {
select: { province: '', city: '', area: '' },
}
},
methods: {
onSelected(data){
console.log(data)
this.select.province = data.province.value
this.select.city = data.city.value
this.select.area = data.area.value
}
},
}
</script>
<style scoped>
</style>
效果:
二. ElementUI的Cascader 级联选择器
官网: https://element.eleme.cn/#/zh-CN/component/cascader
安装
npm i element-ui -S
全局引入(main.js)
import Vue from 'vue';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
开始使用
- click触发子菜单
- 只需为 Cascader 的
options
属性指定选项数组即可渲染出一个级联选择器。 options
属性可以准备一份json数据,(属性的值可以自定义)格式如下:
[{
"value": "110000",
"label": "北京市",
"children": [{
"value": "110100",
"label": "北京城区",
"children": [{
"value": "110101",
"label": "东城区"
}, {
"value": "110102",
"label": "西城区"
}
...
}]
- 完整代码
<template>
<div class="block">
<el-cascader
v-model="value"
:options="options"
@change="handleChange"></el-cascader>
</div>
</template>
<script>
export default {
name: "ClickCas", //这里换成自己组件的名称
data() {
return {
value: [],
options: require('../../assets/json/province-city-area.json')
};
},
methods: {
//当选中节点变化时触发
handleChange(value) { // value: 选中节点的值
console.log(value);
}
}
};
</script>
- hover触发子菜单
- 通过
props.expandTrigger
可以定义展开子级菜单的触发方式。 - 准备的json数据和上方一样
- 完整代码
<template>
<div class="block">
<el-cascader
v-model="value"
:options="options"
:props="{ expandTrigger: 'hover' }"
@change="handleChange"></el-cascader>
</div>
</template>
<script>
export default {
name: "HoverCas", //这里换成自己组件的名称
data() {
return {
value: [],
options: require('../../assets/json/province-city-area.json')
};
},
methods: {
handleChange(value) {
console.log(value);
}
}
};
</script>
树形组件
一. iView
官网: https://www.iviewui.com/components/tree
安装
npm install view-design --save
全局引入(main.js)
import ViewUI from 'view-design';
import 'view-design/dist/styles/iview.css';
Vue.use(ViewUI);
开始使用
基本用法
<template>
<Tree :data="data1" @on-select-change="selectChange"></Tree>
</template>
<script>
export default {
name: 'BaseTree',//这里换成自己组件的名称
data () {
return {
data1: [
{
title: 'parent 1',
expand: true,
children: [
{
title: 'parent 1-1',
expand: true,
children: [
{
title: 'leaf 1-1-1'
},
{
title: 'leaf 1-1-2'
}
]
},
{
title: 'parent 1-2',
expand: true,
children: [
{
title: 'leaf 1-2-1'
},
{
title: 'leaf 1-2-2'
}
]
}
]
}
]
}
},
methods:{
//点击数节点时触发
selectChange(data,node){ // data:当前已选中的节点数组 node:当前项
this.$message.info("当前选中了"+node.title)
}
}
}
</script>
可勾选
设置属性 show-checkbox
可以对节点进行勾选。
<template>
<Tree :data="data2" show-checkbox @on-check-change="checkChange"></Tree>
</template>
<script>
export default {
name: 'CheckBoxTree', //这里换成自己组件的名称
data () {
return {
data2: [
{
title: 'parent 1',
expand: true,
children: [
{
title: 'parent 1-1',
expand: true,
children: [
{
title: 'leaf 1-1-1'
},
{
title: 'leaf 1-1-2'
}
]
},
{
title: 'parent 1-2',
expand: true,
children: [
{
title: 'leaf 1-2-1'
},
{
title: 'leaf 1-2-2'
}
]
}
]
}
]
}
},
methods: {
//点击复选框时触发
checkChange(nodes, node){ //nodes: 当前已勾选节点的数组 node: 当前节点
for( var i of nodes){
console.log(i.title) //控制台打印选择的
}
this.$message.info("当前节点为:"+node.title + "选中状态: "+ node.checked)
}
}
}
</script>
点击标题展开/收起节点
设置属性 expand-node
即可
<Tree :data="data1" expand-node></Tree>
默认展开、选中、勾选和禁用
给节点设置 expand
、selected
、checked
和 disabled
可以将节点设置为展开、选中、勾选和禁用。
设置属性 multiple
可进行多选。
<template>
<Tree :data="data4" show-checkbox multiple></Tree>
</template>
<script>
export default {
name:'StatusTree',//这里换成自己组件的名称
data () {
return {
data4: [
{
title: 'parent 1',
expand: true,
selected: true,
children: [
{
title: 'parent 1-1',
expand: true,
children: [
{
title: 'leaf 1-1-1',
disabled: true
},
{
title: 'leaf 1-1-2'
}
]
},
{
title: 'parent 1-2',
expand: true,
children: [
{
title: 'leaf 1-2-1',
checked: true
},
{
title: 'leaf 1-2-1'
}
]
}
]
}
]
}
}
}
</script>
自定义节点内容
使用强大的 Render 函数可以自定义节点显示内容和交互,比如添加图标,按钮, 标题颜色等。
Render 函数的第二个参数,包含三个字段:
- root :树的根节点
- node :当前节点
- data :当前节点的数据
Render 函数分两种,一种是给当前树的每个节点都设置同样的渲染内容,此 render 通过 Tree 组件的属性 render
传递;另一种是单独给某个节点设置,在该节点的 render
字段内设置;同时设置时,会优先使用当前节点的 Render 函数。
<template>
<div>
<Tree :data="data5" :render="renderContent" class="demo-tree-render"></Tree>
<Modal
v-model="model"
title="添加节点"
width="400px"
@on-ok="ok"
@on-cancel="cancel">
<Input v-model="nodeTitle" icon="ios-leaf" placeholder="输入节点名称" style="width: 180px"/>
标题颜色: <ColorPicker v-model="color"/>
</Modal>
</div>
</template>
<script>
export default {
name: 'CustomizeTree', //这里换成自己组件的名称
data() {
return {
color: 'black',
data: null,
model: false,
nodeTitle: '',
data5: [
{
title: 'parent 1',
icon: 'ios-folder',
expand: true,
render: (h, {root, node, data}) => {
return h('span', {
style: {
display: 'inline-block',
width: '100%'
}
}, [
h('span', [
h('Icon', {
props: {
type: data.icon
},
style: {
marginRight: '8px'
}
}),
h('span', data.title)
]),
h('span', {
style: {
display: 'inline-block',
float: 'right',
marginRight: '32px'
}
}, [
h('Button', {
props: Object.assign({}, this.buttonProps, {
icon: 'ios-add',
type: 'primary'
}),
style: {
width: '64px'
},
on: {
click: () => {
this.append(data)
}
}
})
])
]);
},
children: [
{
title: 'child 1-1',
expand: true,
icon: 'ios-ionitron',
children: [
{
title: 'leaf 1-1-1',
expand: true,
icon: 'ios-jet',
},
{
title: 'leaf 1-1-2',
expand: true,
icon: 'ios-leaf', //扩展图标
color: 'yellow' //扩展标题颜色
}
]
},
{
title: 'child 1-2',
expand: true,
children: [
{
title: 'leaf 1-2-1',
expand: true,
icon: 'ios-mail',
color: 'green'
},
{
title: 'leaf 1-2-1',
expand: true,
icon: 'ios-lock',
color: 'red'
}
]
}
]
}
],
buttonProps: {
type: 'default',
size: 'small',
}
}
},
methods: {
renderContent(h, {root, node, data}) {
return h('span', {
style: {
display: 'inline-block',
width: '100%'
}
}, [
h('span', [
h('Icon', {
props: {
type: data.icon //设置图标
},
style: {
marginRight: '8px',
}
}),
h('span', {
style: {
color: data.color //设置标题颜色
}
}, data.title)
]),
h('span', {
style: {
display: 'inline-block',
float: 'right',
marginRight: '32px'
}
}, [
h('Button', {
props: Object.assign({}, this.buttonProps, {
icon: 'ios-add'
}),
style: {
marginRight: '8px'
},
on: {
click: () => {
this.append(data)
}
}
}),
h('Button', {
props: Object.assign({}, this.buttonProps, {
icon: 'ios-remove'
}),
on: {
click: () => {
this.remove(root, node, data)
}
}
})
])
]);
},
append(data) {
this.model = true //打开对话框
this.nodeTitle = ''//清空输入
this.color = 'black' //恢复默认颜色
this.data = data //获得节点数据
},
remove(root, node, data) {
const parentKey = root.find(el => el === node).parent;
const parent = root.find(el => el.nodeKey === parentKey).node;
const index = parent.children.indexOf(data);
parent.children.splice(index, 1);
},
ok() { //对话框点击确定触发事件
var data = this.data
if (this.nodeTitle == '') {
this.$Message.info("输入不能为空")
} else {
const children = data.children || [];
children.push({
title: this.nodeTitle,
expand: true,
icon: 'ios-leaf',
color: this.color
});
this.$set(data, 'children', children);
}
},
cancel() { //对话框点击取消触发事件
this.model = false //关闭对话框
}
}
}
</script>
<style>
.demo-tree-render .ivu-tree-title {
width: 100%;
}
</style>
右键菜单
节点数据开启字段 contextmenu
,可以配合 slot contextMenu
实现点击右键弹出菜单。
on-contextmenu
当前节点点击右键时触发
<template>
<Tree :data="data6" @on-contextmenu="handleContextMenu">
<template slot="contextMenu">
<DropdownItem @click.native="handleContextMenuEdit">编辑</DropdownItem>
<DropdownItem @click.native="handleContextMenuDelete" style="color: #ed4014">删除</DropdownItem>
</template>
</Tree>
</template>
<script>
export default {
name: 'MenuTree', //这里换成自己组件的名称
data () {
return {
data6: [
{
title: 'parent 1',
expand: true,
contextmenu: true,
children: [
{
title: 'parent 1-1',
expand: true,
contextmenu: true,
children: [
{
title: 'leaf 1-1-1',
contextmenu: true
},
{
title: 'leaf 1-1-2',
contextmenu: true
}
]
},
{
title: 'parent 1-2',
expand: true,
contextmenu: true,
children: [
{
title: 'leaf 1-2-1',
contextmenu: true
},
{
title: 'leaf 1-2-2',
contextmenu: true
}
]
}
]
}
],
contextData: null
}
},
methods: {
handleContextMenu (data) {
this.contextData = data;
console.log(data)
},
handleContextMenuEdit () {
this.$Message.info('Click edit of' + this.contextData.title);
},
handleContextMenuDelete () {
this.$Message.info('Click delete of' + this.contextData.title);
}
}
}
</script>
rue
}
]
}
]
}
],
contextData: null
}
},
methods: {
handleContextMenu (data) {
this.contextData = data;
console.log(data)
},
handleContextMenuEdit () {
this.$Message.info('Click edit of' + this.contextData.title);
},
handleContextMenuDelete () {
this.$Message.info('Click delete of' + this.contextData.title);
}
}
}
</script>