由于最近计设做完了,想优化一下项目,来提高vue的核心观念——组件化,避免重复造轮子,在项目中有些地方重复使用了form表单,而导致这样的原因是因为不同的表单,需要的按钮也不同,因此我的做法是将所有的按钮放到了父组件当中,这样导致了一个问题,就是我无法去触发最后对表单的一个校验提交,因此今天复习了一下插槽,提高了组件化。
基本部分
定义: 插槽是为组件的封装者提供的能力,把不确定的内容,希望由用户指定的部分定义为插槽 v-slot指令的使用:
- 作用:将内容指定放入某个插槽中,必须使用在template和components身上
- 简写形式:#
- 注:对于每一个slot,都有name属性,如果省略了name属性,则有一个默认名称叫做default,而对于使用组件时,默认情况下将会把提供的内容填充到名字为default的插槽当中
- 实例:
<Left>
<template #default>
<p>这是</p>
</template>
</Left>
<slot></slot>
后备内容: 封装组件时,可以为预留的插槽提供后备内容(默认内容),如果插槽使用者没有往当中写入任何数据时,后备内容将会生效 具名插槽: 拥有名字的插槽,通常配合上面的v-slot的指令进行使用 作用域插槽:
- 作用:将插槽身上的数据传给使用插槽的组件使用,相当于是子向父传值
- 使用:
<template #content="obj">
<p>{{ obj.msg }}</p>
</template>
<slot name="content" msg="hello"></slot>
案例:
实现表单组件的重复使用,根据需求在表单里显示不同的按钮,同时要在提交的时候进行表单验证,如果表单校验没有通过的话则不像后台发起请求。
由于按钮是在父组件里的,而表单进行校验是在子组件里的,因此这里涉及到了一个如何调用子组件的问题,下面将讲解如何调用: 通过ref来获取子组件的DOM元素,由于export default是默认导出,因此可以获取到所有的methods,因此对子组件进行ref绑定,在父组件用this.$refs.xxx.xxx,第一个是名字,第二个是方法名
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png" />
<div class="form-box">
<CommonForm ref="form" :formLabel="formLabel" :form="form">
<template #submit>
<el-button type="primary" @click="submit">上传</el-button>
</template>
</CommonForm>
</div>
</div>
</template>
<script>
import CommonForm from './components/CommonForm.vue'
export default {
name: 'App',
components: {
CommonForm
},
data () {
return {
formLabel: [
{
model: 'password',
label: '密码',
type: 'input'
},
{
model: 'checkpass',
label: '确认密码',
type: 'input'
}
],
form: {
password: '',
checkpass: ''
}
}
},
methods: {
submit () {
this.$refs.form.submitForm()
}
}
}
</script>
<style scoped>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
.form-box {
display: flex;
justify-content: center;
align-items: center;
}
</style>
<template>
<el-form :model="form" status-icon :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm" @click="submitForm">
<el-form-item :prop="item.model" v-for="item in formLabel" :key="item.model" :label="item.label">
<!-- eslint-disable-next-line vue/no-mutating-props -->
<el-input v-if="item.type==='input'" :placeholder="'请输入'+item.label" v-model="form[item.model]"></el-input>
</el-form-item>
<el-form-item>
<!-- 存放按钮的插槽 -->
<slot name="submit"></slot>
</el-form-item>
</el-form>
</template>
<script>
export default {
props: {
formLabel: Array,
form: Object
},
data () {
const validatePass = (rule, value, callback) => {
if (value === '') {
callback(new Error('请输入密码'))
} else {
callback()
}
}
const validatePass2 = (rule, value, callback) => {
if (value === '') {
callback(new Error('请再次输入密码'))
} else if (value !== this.form.password) {
callback(new Error('两次输入密码不一致!'))
} else {
callback()
}
}
return {
rules: {
password: [{ validator: validatePass, trigger: 'blur' }],
checkpass: [{ validator: validatePass2, trigger: 'blur' }]
}
}
},
methods: {
submitForm () {
this.$refs.ruleForm.validate((valid) => {
if (valid) {
setTimeout(() => {
console.log(this.form)
}, 1000)
} else {
return false
}
})
}
}
}
</script>
<style></style>
element ui 组件库使用具体看 看懂element ui表单组件使用
|