一、使用需求
首先来看一下官网的介绍,简单了解一下:
然后看一下官网的demo的页面效果,如果需要集成这种灵活看板的首页页面,或者需要实现拖拽的网络布局,可以了解一下这个部件;
二、使用环境
它有目前可以支持vue2和vue3,下载的依赖和demo源码都不一样,注意区分;
官网:Vue Smart Widget(智能小部件)的简介及使用教程 - Made with Vuejs
vue2源码:https://github.com/xiaoluoboding/vue-smart-widget
vue3源码:GitHub - xiaoluoboding/vue-smart-widget at next
vue2依赖:npm i vue-smart-widget / yarn add vue-smart-widget
vue3依赖:npm i vue-smart-widget@next / yarn add vue-smart-widget@next
可以根据自己项目需求灵活选择。
三、使用步骤
1,使用方式一:下载依赖使用
(1)下载依赖
yarn add vue-smart-widget / npm i vue-smart-widget
(2)引入组件
-
vue2
//全局引入
import VueSmartWidget from 'vue-smart-widget'
Vue.use(VueSmartWidget)
//小部件引入
import Vue from 'vue'
import {SmartWidget} from 'vue-smart-widget'
Vue.component('SmartWidget',SmartWidget)
- vue3
//全局引入
const app = create(App)
import VueSmartWidget from 'vue-smart-widget'
app.use(VueSmartWidget)
//小部件引入
import {SmartWidget} from 'vue-smart-widget'
app.component('SmartWidget',SmartWidget)
2,使用方式二:下载源码使用
(1)拉下源码项目
目录结构如下,src文件夹内部SmartWidget.vue是源码。
vue2源码:https://github.com/xiaoluoboding/vue-smart-widget
vue3源码:GitHub - xiaoluoboding/vue-smart-widget at next
注意:我记得我当时拉下vue3版本的启动时有报错,可以优先排查ts规范,或者vue3不兼容的vue2写法问题,即可。
两个使用方式都可,如果你的业务需求在官网上所给的props和方法都能满足的话那就下载依赖使用,如果不能满足,需要修改源码开发扩展功能的话,可以下载源码使用。
3,简单试用
(1)smart-widget-only 不带拖拽
简单的部件,不带拖拽功能,另外,可以通过.smartwidget设置添加背景颜色、边框、阴影等增加效果,看的更清楚些;
<smart-widget title="Default Widget">
<p>
It's default widget.
</p>
</smart-widget>
(2)smart-widget-grid 带拖拽
带有拖拽功能,layout就是形成部件布局的关键数据;
- vue2版本:
<smart-widget-grid :layout="layout">
<smart-widget slot="0" simple>
<div class="layout-center">
<h3>Simple Widget Without Header</h3>
</div>
</smart-widget>
<smart-widget slot="1" title="Default Widget">
<div class="layout-center">
<h3>Default Widget With Header</h3>
</div>
</smart-widget>
<smart-widget slot="2" title="Full Screen" fullscreen>
<div class="layout-center">
<h3>Make any widget full screen</h3>
</div>
</smart-widget>
</smart-widget-grid>
layout: [
{ x: 0, y: 0, w: 4, h: 4, i: '0' },
{ x: 4, y: 0, w: 4, h: 4, i: '1' },
{ x: 8, y: 0, w: 4, h: 4, i: '2' }
]
- vue3版本:vue3插槽方式和vue2不一样,要注意!
<smart-widget-grid :layout="layout">
<smart-widget #0 simple>
<div class="layout-center">
<h3>Simple Widget Without Header</h3>
</div>
</smart-widget>
<smart-widget #1 title="Default Widget">
<div class="layout-center">
<h3>Default Widget With Header</h3>
</div>
</smart-widget>
<smart-widget #2 title="Full Screen" fullscreen>
<div class="layout-center">
<h3>Make any widget full screen</h3>
</div>
</smart-widget>
</smart-widget-grid>
- 官网属性说明:
四、真实使用
其实真实情况下,每个插槽的内容不可能一个个去写,如果需求改变,或者ui改变等等,代码复用性就很低。所以我们可以由后端数据去控制其可配置内容渲染,通过v-for循环出不同的部件内容。
1,以 vue3 的案例来举例:
<smart-widget-grid
:layout="layout" //布局数据
:row-height="50" //每行的高度(单位px)
:margin="[15, 15]" //部件间距
:is-static="isStatic" //是否能编辑拖动部件
@layout-updated="onLayoutUpdated"
@moved="onMove"
@resized="onResize"
v-if="layout && isHasLayout">
<template v-for="(item, index) in portlets" :key="item.id" #[item.id]>
<smart-widget
:title="item.title" //部件标题
:sub-title="item.subTitle" //部件副标题
:fullscreen="item.fullscreen" //全屏按钮
:collapse="item.collapse" //折叠按钮
:refresh="item.refresh" //刷新按钮
:simple="item.simple" //是否显示标题
@on-refresh="handleRefresh(item)" //刷新事件
:loading="item.loading" //加载效果
v-if="portlets && isHasPortlets"
>
</smart-widget>
</template>
</smart-widget-grid>
2,以vue2的案例举例:
<smart-widget-grid
:layout="layout" //布局数据
:row-height="50" //每行高度(单位px)
:margin="[15, 15]" //部件间距
:is-static="isStatic"//控制编辑拖动
@layout-updated="onLayoutUpdated"
@moved="onMove"
@resized="onResize"
>
<smart-widget
v-for="item in portlets"
:key="item.i"
:slot="item.id"
:title="item.title" //部件标题
:fullscreen="item.fullscreen" //全屏
:collapse="item.collapse" //折叠
:refresh="item.refresh"//刷新
:sub-title="item.subTitle" //副标题
:simple="item.simple" //是否显示标题
@on-refresh="handleRefresh(item)" //刷新方法
:loading="item.loading"//加载效果
>
</smart-widget>
</smart-widget-grid>
二者的区别主要在于插槽方式不一样,注意辨别。
3,portlet数据结构示例:
以下是示例数据,可以根据自己的业务需求更改数据结构。
portlets: [
{ id: '0', module: 'content', title: '内容', simple: true, content: '没有标题栏', btn: { fullscreen: false, collapse: false, refresh: false, loading: false } },
{ id: '1', module: 'content', title: '全屏展示', simple: false, content: '这是一个有很多内容的部件,这是一个有很多内容的部件,这是一个有很多内容的部件,这是一个有很多内容的部件,这是一个有很多内容的部件,这是一个有很多内容的部件,这是一个有很多内容的部件,这是一个有很多内容的部件,这是一个有很多内容的部件,这是一个有很多内容的部件,这是一个有很多内容的部件,这是一个有很多内容的部件,这是一个有很多内容的部件,这是一个有很多内容的部件,这是一个有很多内容的部件,这是一个有很多内容的部件,这是一个有很多内容的部件,这是一个有很多内容的部件,这是一个有很多内容的部件,这是一个有很多内容的部件,这是一个有很多内容的部件,这是一个有很多内容的部件,这是一个有很多内容的部件,这是一个有很多内容的部件,这是一个有很多内容的部件,这是一个有很多内容的部件', btn: { fullscreen: true, collapse: true, refresh: false, loading: false } },
{ id: '2', module: 'tubiao1', title: '图表测试', simple: false, content: '', btn: { fullscreen: false, collapse: false, refresh: true, loading: false } },
{ id: '3', module: 'html', title: '图表测试1', simple: false, content: '', btn: { fullscreen: true, collapse: true, refresh: true, loading: false } },
{ id: '4', module: 'edit', title: '可操作性列', simple: false, content: '', btn: { fullscreen: true, collapse: false, refresh: true, loading: false } },
{ id: '5', module: 'cms', title: '信息', simple: false, btn: { fullscreen: false, collapse: false, refresh: true, loading: false } },
{ id: '6', module: 'cms', title: '信息', simple: false, btn: { fullscreen: false, collapse: false, refresh: true, loading: false } }
],
除去官网原有props,可以自定义以下字段:
名称 | 类型 | 说明 | 默认值 | 备注 |
---|---|---|---|---|
id | String | 唯一标识 | null | 和layout的 i 值对应 |
module | String | 部件类型 | null | 不同类型标识【方便有转换部件的需求】 |
btn | Object | 部件右侧按钮的数据控制 | Object(必填) | fullscreen, collapse, refresh, loading |
content | Object/Array/String | 部件内容数据 | null | 根据业务需求编写字段渲染页面 |
portlets: [
{
id: '0',
module: 'profile',
title: 'profile',
simple: true,
btn: { fullscreen: false, collapse: false, refresh: false, cancel: true, setting: true, loading: false },
content: {
career: "心内科主任医师",
profilename: "张嘉欣",
org: "上海某某医院",
onlineNum: 234,
unreadEmail: 10,
avatar: '../../assets/images/avatar.png'
},
},
{
id: '1',
module: 'newstrends',
type: 'content',
title: '新闻动态',
simple: false,
btn: { fullscreen: true, collapse: true, refresh: true, cancel: true, setting: true, loading: false },
content: {
data1:
{
title: "中心召开规章制度宣贯第一次会议",
content: "新闻详情新闻新闻详情新闻新闻详情新闻新闻详情新闻详情新闻详情新闻详情新闻详情新闻详情新闻详情新闻闻详情新闻详情新闻闻详情新闻详情新闻闻详情新闻详情新闻新闻详情新闻新闻详情新闻新闻详情新闻新闻详情新闻新闻详情新闻",
time: '2020-12-09'
},
data2: [
{
time: "2020-09-06",
content: "焦点访谈:“十四五”时期,中国将着重办"
},
{
time: "2020-09-06",
content: "同仁医院徐凌博士,荣获上海市大奖!"
},
{
time: "2020-09-06",
content: "同仁医院徐凌博士,荣获上海市大奖!"
}
]
},
},
{
id: '2',
module: 'fileHandle',
type: 'content',
title: '文件办理',
simple: false,
btn: { fullscreen: true, collapse: true, refresh: true, cancel: true, setting: true, loading: false },
content: {
backlogProcess: 10,
unreadProcess: 10,
unreadEmail: 10,
newCall: 10
},
}]
4,扩展使用
(1)属性扩展
也就是说你的业务需求官网提供的props不满足时,可以去修改源码来实现相应的功能需求,把源码当成封装的组件去修改就可以了,要注意vue2和vue3的写法问题;
- 增加图标
src/SmartWidget.vue 源码中添加:
使用时:
以上就是完整的修改思路啦,大功告成。
(2)扩展部件
按照上文设计思路,portlets里的module定义部件类型,这个定义的前提是有相应的ui设计图后去设计对应的类型字段,或者得假设有哪些类型,但是如果要求有一个类型的部件可以支持自定义呢?比如标题内容不止是一个字符串,是tab选项卡,比如右侧按钮要插入一个input搜索框呢?比如内容的部分支持iframe嵌套呢?这也就是开发扩展部件的意义,去满足更多样化的需求。
我们可以给module添加一个类型"customize",当然叫啥取决于你自己。然后去实现每个部分的自定义功能。以下是以vue3源码示例,注意辨别:
- 左侧标题
src/SmartWidget.vue 源码中添加:
使用示例:
<!-- 自定义左侧标题内容 -->
<template #title v-if="item.customTitle">
<div v-html="item.customTitle"></div>
</template>
- 右侧按钮自定义
src/SmartWidget.vue 源码中添加:
使用示例:
<!-- 自定义右侧内容 -->
<template #toolbar v-if="item.toolbar">
<div v-html="item.toolbar"></div>
</template>
- 内容自定义
<!-- 自定义部件 -->
<template v-if="item.module == 'customize'">
<div v-html="item.content" style="height:100%"></div>
</template>
- portlets自定义数据
{
"id": "10",
"module": "customize",
"customTitle": "<div style='margin-left:20px'><i class='iconfont icon-kaoqin' style='color:#3480FB;margin-right:10px'></i>自定义部件</div>", //标题内容
"simple": false,
"toolbar": "<input placeholder='请输入'/>", //右侧插槽内容
"btn": {
"fullscreen": true,
"collapse": false,
"refresh": true,
"cancel": true,
"setting": true,
"loading": false
},
"content": "<iframe src='https://www.huaban.com/' width='100%' height='100%' frameborder='0'></iframe>" //部件内容iframe嵌套
}
- 实现效果
注意:目前v-html解析出来的标签是原生标签,框架内的好像出不来,如果有此需求可以研究一下,修改一下写法也行。或者自定义的内容可以换成子组件注册在此,然后通过插槽也可以实现解析框架内的标签。
五、总结
大体思路如上, 可以根据需求灵活扩展,学废了吗?!