需求产生
在使用表单时,表单的输入框、选择器会设置 placeholder
属性来进行提示
不设置感觉空荡荡的,但如果自己一条条的写又感觉非常麻烦
那我们为何不封装个指令,让它自己加呢
思路
因为我用的是 element-plus
,组件都有固定的样式、模板
比如
1 2 3
| <el-form-item label="姓名"> <el-input></el-input> </el-form-item>
|
最后的代码就是
1 2 3 4 5 6 7 8
| <div class="el-form-item"> <label for="title" class="el-form-item__label">姓名</label> <div class="el-form-item__content"> <div class="el-input"> <input type="text" class="el-input__inner"> </div> </div> </div>
|
那我们只需要获取到具体的输入框,然后给它设置属性就可以
Vue
指令可以在组件挂载后拿到添加指令的 DOM
元素,再用 DOM
的 querySelector
获取到所有 el-form-item
子元素,遍历后再根据 label
的内容给 input
设置 placeholder
代码参考
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| import _ from 'lodash'
export default { beforeMount(el) { if (!(_.isFunction(_.get(el.classList, 'contains')) && el.classList.contains('el-form'))) { console.warn('v-auto-placeholder 指令需要放在 el-form 上使用') return }
const formItems = el.querySelectorAll('.el-form-item')
_.forEach(formItems, item => { const labelEl = _.get(item.children, '0', '')
const label = _.get(labelEl.children, 'length', 0) > 0 ? _.get(labelEl.children, '0.children.0.innerText', '') : _.get(labelEl, 'innerText', '')
const contentEl = _.get(item.children, '1')
const input = contentEl && contentEl.querySelector ? contentEl.querySelector('input,textarea') : null
const placeholder = _.get(input, 'placeholder')
if (placeholder && placeholder !== '' && placeholder !== '请选择') { return }
const classList = _.get(contentEl, 'children.0.classList')
if (_.some(classList, (className) => ~[ 'el-select', 'el-cascader' ].indexOf(className))) { if (input) input.setAttribute('placeholder', `请选择${label}`) } else { if (input) input.setAttribute('placeholder', `请输入${label}`) } }) } }
|
最终效果
在 el-form
加上 v-auto-placeholder
1 2 3 4 5 6 7
| <el-form v-auto-placeholder> <el-form-item label="姓名"> <el-input></el-input> </el-form-item>
<!-- ... --> </el-form>
|
就可以自动生成 placeholder