Vue中的输入框使用场景总结

本文介绍了在Vue中实现输入框自动聚焦的两种方法,包括使用$nextTick和自定义v-focus指令。同时,针对输入框聚焦显示保存按钮、失焦隐藏并保存内容的交互场景,提供了解决方案,特别处理了点击保存按钮时的焦点问题。在有滚动条的情况下,通过修改判断条件确保事件正确触发。
摘要由CSDN通过智能技术生成

1. 自动聚焦

第1种方法:使用 $nextTick

<input ref="myInput" v-model="text"/>
mounted() {
  this.$nextTick(function () {
    this.$refs.myInput.focus();
  });
},

第2种方法:自定义 v-focus 指令

为了方便,这里用到了 jquery

Vue.directive('focus', {
  inserted(el) {
    // 兼容 Element 基于原生 input 封装的输入框组件
    let innerInput = el.querySelector('input');
    if (innerInput) {
      innerInput.focus();
    // 兼容原生 input
    } else {
      el.focus();
    }
  },
});

如果你有一个按钮可以控制输入框的显示和隐藏,需要每次显示的时候都自动聚焦,那要 v-if 而不能使用 v-show,因为只有 v-if 才能触发自定义指令的 inserted 生命周期函数。

<input v-if="visible" v-focus v-model="text"/>

2. 如何优雅的实现下面效果

效果描述:我们在开发表格的时候经常会遇到一个输入框,输入框聚焦的时候会显示输入框后面的“保存”按钮,失焦的时候后面的“保存”按钮隐藏。点击保存,保存输入框里面的内容。输入框失焦的时候(点击保存按钮保存成功除外),输入框里面的内容要显示原先的内容。  

这里实现的时候会遇到一些比较恶心的地方,比如说,点击保存按钮,输入框失焦了,保存按钮先隐藏了,就不会触发按钮上绑定的点击事件,等等。话不多说,直接上代码,看怎么优雅的去实现它。

代码实现: 

<template>
  <div>
    <el-table
      :data="tableData"
      border
    >
      <el-table-column
        label="商家编码"
        width="200"
      >
        <template slot-scope="{row, $index}">
          <input
            style="width: 100px;"
            v-model="row.skuOuterId"
            @focus="toggleFocus($event, $index, row, true)"
            @blur="toggleFocus($event, $index, row, false)"
          />
          <el-button
            :class="`J_saveBtn_${$index}`"
            :ref="'saveBtn_' + $index"
            v-show="row.showSaveBtn"
            type="primary"
          >保存
          </el-button>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>

<script>
export default {
  data() {
    return {
      tableData: [
        {
          skuOuterId: '123',
          oldSkuOuterId: '123',
          showSaveBtn: false,
        }
      ]
    };
  },
  methods: {
    toggleFocus(e, $index, data = {}, isFocus = false) {
      // 聚焦
      if (isFocus) { 
        data.showSaveBtn = true;
      // 失焦
      } else { 
        // 点击“保存”失焦(判断失焦时关联的目标元素是不是输入框后面的保存按钮)
        if (e.relatedTarget === this.$refs[`saveBtn_${$index}`].$el) {
          axios.post('/updateSkuOuterId', {skuOuterId: data.skuOuterId}).then(res => {
            // 保存成功
            data.oldSkuOuterId = data.skuOuterId;
          }).catch(() => {
            data.skuOuterId = data.oldSkuOuterId;
          });
        // 点击其他地址失焦
        } else {
          data.skuOuterId = data.oldSkuOuterId;
        }
        data.showSaveBtn = false;
      }
    },
  },
};
</script>

上面的代码在有横向滚动条的时候,如果出现了 e.relatedTarget === this.$refs[`saveBtn_${$index}`].$el 为 false,但我们感觉失焦的目标元素就是保存按钮的情况,我们可以把判断条件这么改一下:

e.relatedTarget === this.$refs[`saveBtn_${$index}`].$el
// 改成(下面使用了jQuery) 
$(e.relatedTarget).hasClass(`J_saveBtn_${$index}`)

这样就 OK 了!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue,`ref`是一个特殊的属性,用于给元素或组件注册引用信息。`ref`可以用在以下场景: 1. 获取DOM元素:通过给DOM元素添加`ref`属性,可以在Vue实例通过`$refs`属性访问到这个DOM元素。例如: ```vue <template> <div> <input type="text" ref="input" /> <button @click="focusInput">Focus Input</button> </div> </template> <script> export default { methods: { focusInput() { this.$refs.input.focus(); }, }, }; </script> ``` 在上述代码,我们给`input`元素添加了`ref="input"`属性,然后在`focusInput`方法通过`this.$refs.input`访问到这个DOM元素,并调用了它的`focus`方法,使得输入框获取。 2. 访问子组件:通过给子组件添加`ref`属性,可以在父组件访问到这个子组件实例。例如: ```vue <template> <div> <child-component ref="child"></child-component> <button @click="changeChildText">Change Child Text</button> </div> </template> <script> import ChildComponent from "@/components/ChildComponent.vue"; export default { components: { ChildComponent, }, methods: { changeChildText() { this.$refs.child.changeText("New Text"); }, }, }; </script> ``` 在上述代码,我们给`child-component`组件添加了`ref="child"`属性,然后在父组件通过`this.$refs.child`访问到这个子组件实例,并调用了它的`changeText`方法,修改了子组件的文本内容。 3. 访问动态组件:通过给动态组件添加`ref`属性,可以在父组件访问到这个动态组件实例。例如: ```vue <template> <div> <component :is="currentComponent" ref="component"></component> <button @click="changeComponent">Change Component</button> </div> </template> <script> import ComponentA from "@/components/ComponentA.vue"; import ComponentB from "@/components/ComponentB.vue"; export default { components: { ComponentA, ComponentB, }, data() { return { currentComponent: "ComponentA", }; }, methods: { changeComponent() { this.currentComponent = this.currentComponent === "ComponentA" ? "ComponentB" : "ComponentA"; this.$refs.component.doSomething(); }, }, }; </script> ``` 在上述代码,我们通过`<component>`标签动态渲染了两个组件`ComponentA`和`ComponentB`,并给它们添加了`ref="component"`属性。然后在父组件通过`this.$refs.component`访问到当前动态组件实例,并调用了它的`doSomething`方法,执行一些操作。 总之,`ref`可以用于访问DOM元素、子组件和动态组件等情况,但是过多使用`ref`可能会导致代码难以维护,应该谨慎使用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值