Vue2.0 中,代码复用和抽象的主要形式是组件。然而,有的情况下,你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令。举个聚焦输入框的例子,如下:
在网上查找了很多方法,
但是在实际使用中发现了一个问题
无论是使用$ref获取input元素然后使用focus方法:
if (column.property == "remark") { this.$nextTick(() => { this.$refs.remarkRef.focus(); // 视图出现后使input获取焦点 }); } else { this.$nextTick(() => { this.$refs.hitchRef.focus(); // 视图出现后使input获取焦点 }); }
还是使用饿了么组件自带的autoFocus
都只有在第一次点击按钮的时候可以让Input获得焦点,在不刷新页面的情况下,第二次以后的按钮点击都不会让Input获得焦点。猜测了一下是存才一个全局变量,当我们第一次使Input获得焦点以后改变了这个预设变量的值,在Input失去焦点的时候并没有将这个值重置,所以导致了后面的问题。
事实上,只要你在打开这个页面后还没点击过任何内容,这个输入框就应当还是处于聚焦状态。现在让我们用指令来实现这个功能:
在main.js中
// 注册一个全局自定义指令 `v-focus` Vue.directive('focus', { // 当被绑定的元素插入到 DOM 中时…… inserted: function (el) { // 聚焦元素 el.focus() el.querySelector('input').focus() } })
如果想注册局部指令,组件中也接受一个 directives
的选项:
directives: { // 注册一个局部的自定义指令 v-focus focus: { // 指令的定义 inserted: function (el) { // 聚焦元素 el.querySelector("input").focus(); }, }, },
注意:directives是vue中的自定义指令,个人理解成自定义的钩子函数。
然后你可以在模板中任何元素上使用新的 v-focus
property,如下
<input v-focus>
具体代码
<el-table-column label="调整值" width="300" align="center"> <template slot-scope="scope"> <el-input ref="inputRef" v-if="scope.row.isEditCell" v-model.number="scope.row.amount2" class="el-input" v-focus @blur="cellBlur(scope.row, scope.column)" /> <span v-else>{{ scope.row.amount2 }}</span> <el-button style="margin-left: 5px" v-if="scope.row.isEditCell" type="success" icon="el-icon-check" size="small" circle @click="submitName(scope.row)" ></el-button> <el-button v-show="scope.row.isEditCell" class="cancel-btn" size="mini" icon="el-icon-refresh" type="warning" @click.native.prevent="handleCancel(scope.row)" > cancel </el-button> </template> </el-table-column>
这样使我们在组件中可以自用的调用v-focus方法,给他绑定定义布尔变量来控制元素是否获得焦点
但是这里要注意的是组件<el-input>本身在页面中渲染成了一个div元素
所以我们要在<el-input>被绑定为v-focus的同时
在自定义指令中获取组件下通过querySelector()方法获取input元素