Vue 封装grid布局
Grid布局博客地址Vue-iView-ui Grid布局代码有些 冗余,现在封装一套自己的grid布局 以 from表单为例第一种方法创建Grid 文件夹,创建Grid和GridItem 组件Gird.vue<template><Form :label-width="80" class="grid" :style="style"><slot></slot
·
Vue-iView-ui 和 Vue-element-ui 的 Grid 布局代码有些 冗余,现在封装一套自己的 grid布局 以 from表单为例
支持表单校验,国际化,错误信息定位,网格布局
Grid>Grid.vue
<template>
<div>
<Form v-if="type == 'iview'" ref="form" v-bind="$attrs" v-on="$listeners" :label-width="labelWidth" :label-position='labelPosition' class="grid" :style="style" >
<slot></slot>
</Form>
<el-form v-else-if="type == 'element'" ref="form" v-bind="$attrs" v-on="$listeners" :label-width="labelWidth" :label-position='labelPosition' class="grid" :style="style">
<slot></slot>
</el-form>
</div>
</template>
<script>
export default {
props:{
column:{
type:[String,Number],
default:2
},
// 表单域标签的宽度
labelWidth:{
type:[String,Number],
},
// 表单域标签的位置,支持left,top,right
labelPosition:{
type:String,
default:null
},
type:{
type:[String],
default:'iview',
validate:function(value){
// 类型必须是iview或者element
return ['iview','element'].includes(value)
}
},
columnGap:{
type:[String,Number],
default:30
},
rowGap:{
type:[String,Number],
default:10
},
colon:{
type:[Boolean],
default:false
}
},
provide(){
return{
'grid':this
}
},
computed:{
style(){
return{
// 设置的列的状态,可以根据this.column设置当前行有几列,fr是等份,代表可用剩余宽度的分配
'grid-template-columns' : `repeat(${this.column},1fr)`,
//设置行列间距
'grid-column-gap':this.columnGap + 'px',
'grid-row-gap':this.rowGap + 'px'
}
}
},
methods:{
validate(callback){
//如果有 没有校验的表单元素,视图自动显示到这个部分
// 校验表单
this.$refs.form.validate(callback);
let elementError = document.getElementsByClassName('el-form-item__error');
let iviewError = document.getElementsByClassName("ivu-form-item-error-tip")
// this.$nextTick指的是下一个周期执行
this.$nextTick(function () {
if(elementError.length > 0){
elementError[0].scrollIntoView({
block:'center'
})
}
if(iviewError.length > 0){
iviewError[0].scrollIntoView({
block:'center'
})
}
});
}
}
}
</script>
<style scoped>
.grid{
display: grid;
grid-template-rows: 1fr;
}
</style>
Grid>GridItem.vue
<template>
<FormItem :label="label+colon" v-bind="$attrs" v-on="$listeners" :style="style" v-if="grid.type == 'iview'">
<slot></slot>
</FormItem>
<el-form-item :label="label+colon" v-bind="$attrs" v-on="$listeners" :style="style" v-else-if="grid.type == 'element'">
<slot></slot>
</el-form-item>
</template>
<script>
export default {
inject:['grid'],
props:{
column:{
type:[String,Number],
default:1
},
label:{
type:[String]
}
},
computed:{
style(){
return {
// 设置单元格的状态,span代表合状态,第二个参数代表合并几等份
'grid-column-end':`span ${this.column}`
}
},
//配置冒号
colon(){
if(this.grid.colon){
// 判断国际化
return this.$i18n.locale == 'zh' ? ':' : ':'
}else{
return ''
}
}
}
}
</script>
<style scoped>
</style>
Grid>index.js
import Vue from 'vue'
import Grid from './Grid.vue'
import GridItem from './GridItem.vue'
Grid.install = ()=>{
Vue.component('Grid',Grid)
}
GridItem.install = ()=>{
Vue.component('GridItem',GridItem)
}
export {
Grid,
GridItem
}
main.js
import iviewUi from 'view-design'
import 'view-design/dist/styles/iview.css'
import elementUi from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import i18n from './lang/index'
//全局引入Grid
import {Grid,GridItem} from './components/Grid/index'
Vue.use(elementUi)
Vue.use(iviewUi)
Vue.use(Grid)
Vue.use(GridItem)
new Vue({
render: h => h(App),
i18n
}).$mount('#app')
lang>index.js
import Vue from 'vue'
import VueI18n from 'vue-i18n'
Vue.use(VueI18n)
const i18n = new VueI18n({
locale : "zh",
messages:{
'zh':{
},
'en':{
}
}
})
export default i18n
app.vue
<template>
<div >
<Grid column='1' type='iview' :model="ruleForm" :rules="rules" ref="formName" colon :labelPosition="'left'" :labelWidth="'140px'" style="height:1000px">
<GridItem column='1' label="活动名称" prop="name">
<el-input v-model="ruleForm.name"></el-input>
</GridItem>
<GridItem column='1' label="活动区域" prop="region">
<el-select v-model="ruleForm.region" placeholder="请选择活动区域">
<el-option label="区域一" value="shanghai"></el-option>
<el-option label="区域二" value="beijing"></el-option>
</el-select>
</GridItem>
<GridItem column='1' label="活动性质" prop="type">
<el-checkbox-group v-model="ruleForm.type">
<el-checkbox label="美食/餐厅线上活动" name="type"></el-checkbox>
<el-checkbox label="地推活动" name="type"></el-checkbox>
<el-checkbox label="线下主题活动" name="type"></el-checkbox>
<el-checkbox label="单纯品牌曝光" name="type"></el-checkbox>
</el-checkbox-group>
</GridItem>
<GridItem column='1' label="特殊资源" prop="resource">
<el-radio-group v-model="ruleForm.resource">
<el-radio label="线上品牌商赞助"></el-radio>
<el-radio label="线下场地免费"></el-radio>
</el-radio-group>
</GridItem>
<GridItem column='1' label="活动形式" prop="desc">
<el-input type="textarea" v-model="ruleForm.desc"></el-input>
</GridItem>
</Grid>
<el-button type="primary" @click="submit">提交</el-button>
</div>
</template>
<script>
export default {
data() {
return {
ruleForm: {
name: '',
region: '',
date1: '',
date2: '',
delivery: false,
type: [],
resource: '',
desc: ''
},
rules: {
name: [{
required: true,
message: '请输入活动名称',
trigger: 'blur'
},
{
min: 3,
max: 5,
message: '长度在 3 到 5 个字符',
trigger: 'blur'
}
],
region: [{
required: true,
message: '请选择活动区域',
trigger: 'change'
}],
date1: [{
type: 'date',
required: true,
message: '请选择日期',
trigger: 'change'
}],
date2: [{
type: 'date',
required: true,
message: '请选择时间',
trigger: 'change'
}],
type: [{
type: 'array',
required: true,
message: '请至少选择一个活动性质',
trigger: 'change'
}],
resource: [{
required: true,
message: '请选择活动资源',
trigger: 'change'
}],
desc: [{
required: true,
message: '请填写活动形式',
trigger: 'blur'
}]
}
}
},
methods: {
submit() {
this.$refs.formName.validate((valid) => {
if (valid) {
alert('submit!');
} else {
console.log('error submit!!');
return false;
}
});
}
},
created(){
this.$i18n.locale = 'zh'
window.localStorage.setItem('lang',this.$i18n.locale)
// console.log(this.$i18n.locale)
}
}
</script>
<style scoped>
</style>
更多推荐
已为社区贡献1条内容
所有评论(0)