Vuetify UI组件笔记
v-btn按钮和v-text-field文本
1. v-btn浮动按钮
v-btn浮动按钮
v-btn按钮和v-text-field文本
flat:移除按钮的背景色,布尔值类型,默认为false;
icon:将按钮指定为图标——原型和平面,布尔值类型,默认为false;
disabled: 移除组件的单击或 target(触发事件)功能;
depressed:移除按钮的阴影效果
2. v-text-field文本框
v-text-field官网
v-btn按钮和v-text-field文本
(1)append-icon:在文本框后面追加一个图标,默认为String类型;
(2)counter:为输入长度创建一个计数器,如果未指定数字,则默认为25,不会应用任何验证;类型为boolean|number|string;
(3)disabled:布尔类型boolean不可见;
(4)multi-line:是否转为文本域,默认是false。文本框和文本域可以自由切换;
(5)name:字段名,表单中会用到;
(6)label:提示文字,输入框的标签;
(7)value:值。可以用v-model代替,实现双向绑定。
(8)hide-details:表示隐藏文本框底部错误信息。
(9)required:是否为必填项,如果是,会在label后加*,不具备校验功能。默认是false;
(10)rows:文本域的行数,multi-line为true时才有效;
(11)single-line:是否单行文本显示,默认是false;
(12)hint:提示文本;
(13)persistent-hint:强制提示总是可见的
3. v-textarea多行文本框 v-textarea
(1)auto-grow:根据文本数量自动增长文本;
(2)rows:默认行数;
(3)hint:提示文本;
(4)persistent-hint:强制提示总是可见的;
(5)disabled:禁用输入;
(6)id:设置组件上的 DOM id;
(7)hide-details:表示隐藏文本框底部提示和验证错误信息;
(8)flat:当使用solo或者solo-inverted属性时,移除添加到元素的标高(阴影)
项目实例:
<v-col cols="12">
<vee
:rules="{required:true, max: 128}"
v-slot="{ errors }"
>
<v-textarea
:error-messages="errors"
:label="$t('schema.license.customerUuid')"
:rows="1"
auto-grow
v-model="currentModel.customerUuid"
></v-textarea>
</vee>
</v-col>
4. v-toolbar工具栏组件
Vuetify官网链接:v-toolbar工具栏
v-toolbar 组件对于任何 gui 都是至关重要的,因为它通常是站点导航的主要来源。工具栏组件与 v-navigation-drawer 和 v-card 配合使用效果非常好。
dense: 将工具栏内容的高度降低到 48px(使用 prominent 属性时为 96px)。 --(type: boolean)
flat: 删除工具栏的框阴影。–(type: boolean)
5. v-dialog对话框
Vuetify官网链接:v-dialog对话框
v-dialog 组件常用属性:
(1)max-width:限制宽度;
(2)v-model:value值双向绑定到show变量,用来控制窗口显示;
(3)persistent: 在元素外部单击不会将其停用。----(type: boolean)-(delault: false);
(4)scrollable:当包含card, card-title, card-text 以及 card-actions这几个的对话框可滚动设为 true 的时候;card-text 应该指定高度并且设置 overflow-y;布尔类型,默认值为false.
6. v-card卡片
Vuetify官网链接:v-card卡片
v-card组件是一个多功能组件,可用于从面板到静态图像的任何事物。card组件有许多班助组件,使标记尽可能简单。没有列出选项的组件使用Vue的功能组件选项来加快渲染速度,并作为标记糖来使构建更容易。
(1)v-card-media:一般放图片或视频;
(2)v-card-title:卡片的标题,一般位于卡片顶部;
(3)v-card-text:卡片的文本(主体内容),一般位于卡片正中;
(4)v-card-action:卡片的按钮,一般位于卡片底部.
7.v-form表单
v-form的常用属性:
(1)lazy-validation:如果启用,value将永远是 true ,除非有可见的验证错误。您仍然可以调用validate()来手动触发验证;布尔类型,默认值为false。
(2)value:true,代表表单验证通过;false,代表表单验证失败;布尔类型,默认值为false。
v-form的常用方法:
(1)validate:校验整个表单数据,前提是你写好了校验规则。返回Boolean表示校验成功或失败。
(2)reset:重置表单数据。
8.v-menu下拉菜单
v-menu的常用属性:
(1)left:将组件向左边对齐
(2)right:将组件向右边对齐
(3)bottom:将组件向底部对齐
(4)offset-x(y):在y轴上偏移菜单,与左/右(上/下)方向一起工作
(6)transition:设置组件转换方式
9.v-overlay遮罩层 v-overlay
v-overlay的常用属性:
(1)absolute:给组件应用 position: absolute,绝对定位,并且包含在其父元素内
(2)color:将指定的颜色应用于控件;
(3)value:控制组件可见还是隐藏;
(4)opacity:设置遮罩层的透明度;
(6)z-index:用于组件的 z-index
项目实例:
<template>
<div class="fill-height">
<v-overlay
:absolute="absolute"
:opacity="opacity"
:value="showing"
>
<v-progress-circular
indeterminate
size="64"
></v-progress-circular>
</v-overlay>
<inner-frame
:src="baseUrl+'#/strategy/dpi?assetIp='+ip+'&'+param+'&token='+token"
id="sasManageIframe"
name="sasFrame"
ref="frame"
style="border: none;"
></inner-frame>
</div>
</template>
<script>
import innerFrame from '@c/inner-frame.vue'
// import { services } from '@/settings'
import userMixins from '@/mixins/store/user'
export default {
mixins: [userMixins],
props: {
show: {
type: Boolean,
default: false
}
},
components: { innerFrame },
data() {
return {
baseUrl: '',
ip: '',
param:
'header=false&footer=false&toolbar=false&license=false&permanent=true&id=strategy&value=0',
token: '',
showing: false,
absolute: true,
opacity: 0.1
}
},
watch: {
show: {
handler(val) {
this.showing = val
},
immediate: true
}
},
mounted() {
//添加审计加载loading
const iframe = document.querySelector('#sasManageIframe')
if (iframe) {
const ithis = this // 将this赋给一个变量,在function(){}中使用
iframe.addEventListener(
'load',
function () {
ithis.showing = false
},
false
)
}
},
created() {
this.ip = this.$attrs.ip
// this.baseUrl = services.sas
this.baseUrl = `https://${this.ip}/`
this.token = this.$token
}
}
</script>
<style>
</style>
10. v-file-input文件上传 v-file-input
v-file-input属性:
(1)truncate-length:在用省略号截断之前的文件名的长度
(2)prepend-icon:在组件前添加一个图标,使用与 v-icon 相同的语法
(3)show-size:设置所选文件的显示大小。当使用 true 默认值为 1000 显示(kB,MB,GB) 时,1024 将显示(KiB,MiB,GiB)。
(4)accept:接收格式(accept=".doc,.docx,.png,.txt")
11. v-navigation-drawer v-navigation-drawer
v-navigation-drawer的常用属性:
(1)permanent:不管屏幕尺寸如何,抽屉都可以看到
(2)value:控制组件可见还是隐藏
(3)fixed:给组件应用 position: fixed
12.v-data-table_表格组件 vuetify—v-data-table
v-data-table 用于显示表格数据,功能包括排序、搜索、分页、行内编辑、头部提示以及行选择。而我们在实际应用中使用最多的就是服务端分页和排序,如果你从后台加载数据,并希望显示结果之前进行分页和排序,你可以使用 total-items 属性。定义这个属性将会禁用内置的分页和排序,并且你需要使用 pagination 属性来监听变化。使用 loading 属性来显示获取数据时的进度条。
相关资料:
(1)data-tables组件
(2)v-data-table_表格组件
(3)data-table每页数目下拉框设置
项目实例:
(1) 安管(smp)操作日志&事件记录页面
<!--
FilePath: \src\views\reports\analysis\analysis1.vue
Project: xxx
CreatedAt: 2020-10-28 10:02:47
CreatedBy:666
Copyright: (c) 2020
Task: #1
操作日志页面
-->
<template>
<div class="d-flex flex-column fill-height">
<v-toolbar
class="mb-1"
slot="header"
>
<v-toolbar-items class="d-flex align-center">
<span class="pr-4">{{$t('schema.logs.time')}}</span>
<v-select
:items="items"
class="pr-5 mt-6"
dense
solo
style="flex: 1; width: 200px"
v-model="time"
></v-select>
<date-time-picker
:enablings="enabling"
v-model="date"
></date-time-picker>
<div class="my-2 ml-5">
<v-btn
@click="search"
color="primary"
>{{$t('common.actions.searchBtn')}}</v-btn>
</div>
</v-toolbar-items>
</v-toolbar>
<div
class="fill-height my-1 white"
style="overflow: auto;"
>
<data-table
:headers="headers"
:list="list"
:total="totalItems"
@pagi="pagi"
></data-table>
</div>
</div>
</template>
<script>
// import dateTimePicker from '@c/data-time-picker'
import dataTable from './data-table'
import dateTimePicker from './date-time-picker'
import { format, subMinutes, subHours, subDays } from 'date-fns'
export default {
components: {
dateTimePicker,
dataTable
},
// filters: {
// time(value) {
// return format(Date.parse(value), 'yyyy-MM-dd HH:mm:ss')
// }
// },
data() {
return {
date: {
from: format(subMinutes(new Date(), 10), 'yyyy-MM-dd HH:mm'),
to: format(new Date(), 'yyyy-MM-dd HH:mm')
},
items: [
{ text: this.$t('schema.dates.5-minutes'), value: 1 },
{ text: this.$t('schema.dates.1-hour'), value: 2 },
{ text: this.$t('schema.dates.1-day'), value: 3 },
{ text: this.$t('schema.dates.selfDefine'), value: 4 }
],
enabling: true,
time: '',
totalItems: 0,
model: {
timerange: {
type: 'absolute'
},
per_page: 15,
page: 1, // 当前页
// itemsPerPage: 10,
filter: { alerts: 'exclude' }
},
headers: [
// {
// type: 'index'
// },
// {
// text: '',
// value: 'data-table-expand',
// width: 20,
// align: 'right',
// sortable: false
// },
{
text: this.$t('schema.logs.operator'),
value: 'event.message',
align: 'left',
sortable: true
},
{
text: this.$t('schema.logs.time'),
value: 'event.priority',
align: 'left',
sortable: true
},
{
text: this.$t('schema.logs.content'),
value: 'event.description',
align: 'left',
sortable: true
}
],
list: []
}
},
watch: {
'model.page'() {
this.getRecords()
},
time: {
handler(val) {
if (val === 1 || val === 2 || val === 3) {
this.enabling = true
this.date.from =
val === 1
? format(subMinutes(new Date(), 5), 'yyyy-MM-dd HH:mm')
: val === 2
? format(subHours(new Date(), 1), 'yyyy-MM-dd HH:mm')
: format(subDays(new Date(), 1), 'yyyy-MM-dd HH:mm')
this.date.to = format(new Date(), 'yyyy-MM-dd HH:mm')
} else if (val === 4) {
this.enabling = false
}
}
}
},
methods: {
search() {
if (this.model.page === 1) {
this.getRecords()
} else {
this.model.page = 1
}
},
pagi(val) {
this.model.per_page = val.itemsPerPage
this.model.page = val.page
this.getRecords()
},
async getRecords() {
const date = JSON.parse(JSON.stringify(this.date))
const { from, to } = date
const data = JSON.parse(JSON.stringify(this.model))
Object.assign(data.timerange, {
from: new Date(from).toISOString(),
to: new Date(to).toISOString()
})
// const res = await search(data)
// if (res.status === 200) {
// this.list = res.data.events
// this.totalItems = res.data.total_events
// }
}
},
created() {
this.time = this.items[0].value
},
async mounted() {
this.getRecords()
}
}
</script>
<style lang="scss" scoped>
</style>
<!--
FilePath: \src\views\happening\record\data-table.vue
Project: xxx
CreatedAt: 2020-10-28 10:23:19
CreatedBy: 666
Copyright: (c) 2020
Task: #1
事件记录页面-data-table
-->
<template>
<v-data-table
:footer-props="perPageOptions"
:headers="headers"
:hide-default-footer="false"
:items="list"
:options.sync="options"
:server-items-length="total"
:single-expand="true"
@update:options="optionsChanged"
class="elevation-1 flex-table"
item-key="event.id"
>
<template
v-slot:item.event.timestamp="{ item }"
>{{format(Date.parse(item.event.timestamp), 'yyyy-MM-dd HH:mm:ss.SSS')}}</template>
</v-data-table>
</template>
<script>
import { format } from 'date-fns'
// import i18n from '@/i18n'
export default {
props: {
headers: {
type: Array,
default: () => {
return []
}
},
list: {
type: Array,
default: () => {
return []
}
},
total: {
type: Number,
default: 0
}
},
data() {
return {
format,
options: {
page: 1,
itemsPerPage: 15,
pageStart: 1,
pageStop: 1,
sortDesc: [false, false]
},
perPageOptions: {
'items-per-page-options': [5, 10, 15, 20, -1]
}
}
},
filters: {},
methods: {
optionsChanged() {
this.$emit('pagi', this.options)
}
}
}
</script>
(2) 安全审计(sas)数据外发页面
<!--
FilePath: \src\views\devices\outdata\outdata.vue
Project: xxx
CreatedAt: 2021-05-07 09:56:46
CreatedBy: 666
Copyright: (c) 2021
Task: #1
数据外发页面
-->
<template>
<one-table>
<div class="flex-grow-1">
<v-row class="mt-n4 mb-n4">
<v-col cols="6">
<syslog-server></syslog-server>
</v-col>
</v-row>
<v-row class="mt-n2">
<v-col cols="6">
<safe-platform></safe-platform>
</v-col>
</v-row>
</div>
</one-table>
</template>
<script>
import oneTable from '@c/layout/one-table'
import syslogServer from './syslog-server'
import safePlatform from './safe-platform'
export default {
components: { oneTable, syslogServer, safePlatform },
data() {
return {}
}
}
</script>
<style>
</style>
-------------------------------------------------------------------------------------
<!--
FilePath: \src\views\devices\outdata\syslog-server.vue
Project: xxx
CreatedAt: 2021-05-07 11:16:51
CreatedBy: 666
Copyright: (c) 2021
Task: #1
数据外发--syslog服务器模块
-->
<template>
<div class="d-flex flex-column white">
<v-toolbar
color="#e6f0fb"
dense
flat
>
<v-toolbar-title
class="primary--text"
>{{$t('schema.system.syslogServer')}}</v-toolbar-title>
</v-toolbar>
<div
class="d-flex flex-column"
style="height: 221px"
>
<div class="text-left pt-3 pl-3 mb-2">
<v-btn
:disabled="syslogServers.length >=2 ? true : false"
@click="addSyslogServer"
class="primary"
>{{$t('schema.system.addSyslogServer')}}</v-btn>
</div>
<div
class="mx-3"
style="border:1px solid #e0e0e0"
>
<v-data-table
:headers="headers"
:items="syslogServers"
:items-per-page="per_page"
class="fill-height overflow-y-auto"
hide-default-footer
>
<template v-slot:top>
<syslogServer-dialog
:icon="icon"
:model="model"
:title="title"
:uploadDatas="uploadDatas"
@changed="refresh"
v-if="serverDialog"
v-model="serverDialog"
></syslogServer-dialog>
</template>
<template v-slot:item.option="{ item }">
<v-icon
@click="editServer(item)"
class="mr-2"
color="primary"
dense
>edit</v-icon>
<v-icon
@click="deleteServer(item)"
color="primary"
dense
>remove_circle</v-icon>
</template>
</v-data-table>
</div>
</div>
</div>
</template>
<script>
import { enums } from '@utils'
import syslogServerDialog from './syslogServer-dialog'
import { findSyslogServer, remove } from '@api/system/outData'
import { success, error, confirm } from '@utils/message'
export default {
components: { syslogServerDialog },
data() {
return {
icon: '',
uploadDatas: [],
title: '',
serverDialog: false,
syslogServers: [],
per_page: 10000,
model: this.getDef(),
headers: [
{
text: this.$t('schema.system.ip'),
value: 'ip',
sortable: false
},
{
text: this.$t('schema.system.port'),
value: 'port',
sortable: false,
width: 60
},
{
text: this.$t('schema.system.uploadDatas'),
value: 'items',
sortable: false
},
{
text: this.$t('schema.dpi.actions'),
value: 'option',
sortable: false,
width: 80
}
]
}
},
methods: {
addSyslogServer() {
// if (this.syslogServers.length >= 2) {
// error(this.$t('schema.system.syslogServerlen'))
// return
// }
this.icon = 'add_circle'
this.title = this.$t('schema.system.addSyslogServer')
this.model = this.getDef()
this.serverDialog = true
},
editServer(item) {
this.icon = 'edit'
this.title = this.$t('schema.system.editSyslogServer')
let itemsys = JSON.parse(JSON.stringify(item))
itemsys.items = itemsys.items.map(o => {
for (let i = 0; i < this.uploadDatas.length; i++) {
if (this.uploadDatas[i].text === o) {
return this.uploadDatas[i].value
}
}
})
this.model = itemsys
this.serverDialog = true
},
refresh() {
this.findSyslogServer()
},
async deleteServer(item) {
const yes = await confirm(this.$t('common.messages.deleteConfirm'))
if (!yes) {
return
}
try {
await remove(item.id)
this.refresh()
success()
} catch (err) {
error()
throw new Error(err)
}
},
async findSyslogServer() {
const res = await findSyslogServer()
this.syslogServers = res.map(item => {
item.items = item.items.map(o => {
for (let i = 0; i < this.uploadDatas.length; i++) {
if (this.uploadDatas[i].value === o) {
return this.uploadDatas[i].text
}
}
})
return item
})
},
getDef() {
return {
ip: '',
port: '',
items: []
}
}
},
created() {
this.uploadDatas = enums.list('UploadDatas')
this.findSyslogServer()
}
}
</script>
-----------------------------------------------------------------------------------
<!--
FilePath: \src\views\devices\outdata\syslogServer-dialog.vue
Project: xxx
CreatedAt: 2021-05-09 11:33:46
CreatedBy: 666
Copyright: (c) 2021
Task: #1
新增/修改syslog服务器弹框
-->
<template>
<single-dialog
:actions="actions"
:icon="icon"
:title="title"
@cancel="cancel"
@ok="ok"
max-width="500"
v-model="value"
>
<vee-ob ref="ob">
<form-flex class="pb-0">
<v-row class="mx-0">
<v-col
class="pb-0"
cols="6"
>
<vee
:customMessages="{remote:$t('common.messages.alreadyExist')}"
:debounce="500"
:rules="{required: true, ip: true, remote: { callback: uniqueValue, args:{id: currentModel.id }}}"
v-slot="{ errors }"
>
<v-text-field
:error-messages="errors"
:label="$t('schema.system.ip')"
placeholder="192.168.1.1"
v-model="currentModel.ip"
></v-text-field>
</vee>
</v-col>
<v-col
class="pb-0"
cols="2"
>
<vee
rules="required|port"
v-slot="{ errors }"
>
<v-text-field
:error-messages="errors"
:label="$t('schema.system.port')"
placeholder="514"
v-model="currentModel.port"
></v-text-field>
</vee>
</v-col>
<v-col
class="mt-n8"
cols="12"
>
<div>
<h4 class="pt-4 pb-1">{{$t('schema.system.uploadData')}}</h4>
<v-row class="mb-n3">
<v-col
:key="index"
class="mt-n6"
cols="4"
v-for="(item, index) in this.uploadDatas"
>
<v-checkbox
:label="item.text"
:value="item.value"
class="pt-0"
dense
hide-details
v-model="currentModel.items"
></v-checkbox>
</v-col>
</v-row>
</div>
</v-col>
</v-row>
</form-flex>
</vee-ob>
</single-dialog>
</template>
<script>
import { singleDialog } from '@c/dialogs'
import { formFlex } from '@c/forms'
import { update, create, validateSyslogServerIp } from '@api/system/outData'
import { success, error } from '@utils/message'
export default {
components: { singleDialog, formFlex },
props: {
value: {
type: Boolean,
default: false
},
title: {
type: String,
default: ''
},
icon: {
type: String,
default: ''
},
uploadDatas: {
type: Array,
default: () => []
},
model: {
type: Object,
default: () => {}
}
},
data() {
return {
actions: true,
currentModel: {}
}
},
watch: {
model: {
handler(val) {
this.currentModel = JSON.parse(JSON.stringify(val))
},
immediate: true
}
},
methods: {
async uniqueValue(value, args) {
const res = await validateSyslogServerIp(value, args.id)
return res.length <= 0
},
cancel() {
this.$emit('input', false)
},
async ok() {
const valid = await this.$refs.ob.validate()
if (!valid) {
return
}
const { ip, port, items } = this.currentModel
let data = {
ip,
port: Number(port),
items
}
try {
if (this.currentModel.id) {
data = {
ip: { set: ip },
port: { set: Number(port) },
items
}
await update(this.currentModel.id, data)
} else {
await create(data)
}
this.$emit('changed')
this.$emit('input', false)
success()
} catch (err) {
error()
throw new Error(err)
}
}
}
}
</script>
更多推荐
所有评论(0)