vue.js 将重点放在输入上

Posted

技术标签:

【中文标题】vue.js 将重点放在输入上【英文标题】:vue.js put focus on input 【发布时间】:2019-02-04 21:45:32 【问题描述】:

html

<span :style=" display : displayTitle " @dblclick="showInput()">
   node.title 
</span>
<input :style=" display : displayTitleInput " type="text" 
       @blur="hideInput1" @keydown="hideInput2" 
       @input="changeTitle(node.id , $event.target.value)" 
       :value="node.title">

JS

data() 
  return 
      displayTitle: "inline-block",
      displayTitleInput: "none"
    ;
,
showInput() 
    this.displayTitle = "none"
    this.displayTitleInput = "inline-block"
,
hideInput1() 
   this.displayTitle = "inline-block"
   this.displayTitleInput = "none"
,
hideInput2(event) 
    if (event.keyCode === 13) 
        this.hideInput1()
    
,

我是一名初级日本网络开发人员。我英语不好,对不起。

HTML 位于“v-for”(v-for="node in list") 中。

双击文本时变为&lt;input&gt;

我希望在输入出现时能够专注于它。

我试过了,但是没用。

HTML

<span :style=" display : displayTitle " @dblclick="showInput(node.id)">
   node.title 
</span>
<input :ref='"input_" + node.id' :style="display:displayTitleInput" type="text" 
       @blur="hideInput1" @keydown="hideInput2" 
       @input="changeTitle(node.id , $event.target.value)" 
       :value="node.title">

JS

showInput(id) 
    this.displayTitle = "none"
    this.displayTitleInput = "inline-block"

    this.$nextTick(this.$refs["input_" + id][0].focus())
,

控制台没有错误,但没有工作。

【问题讨论】:

非常感谢您的评论。你的意思是这样吗? this.$nextTick(this.$refs["input_" + id].focus()) Uncaught TypeError: this.$refs[("input_" + t)].focus 不是 dblclick ( sl-vue-tree.js?c536:8) 在调用者 (vue.runtime.esm.js?2b0e:2023) 在 HTMLSpanElement.fn._withTask.fn._withTask (vue.runtime.esm.js?2b0e:1822) 我收到了这个错误(T_T) 抱歉,我删除[0] 的方法不正确。出于某种原因,$refs 属性是一个数组 【参考方案1】:

如果您想在单击某物后设置焦点并显示输入文本框并使用 vue js 设置焦点

directives: 
  focus: 
    // directive definition
    inserted: function (el) 
      el.focus()
    
  

并为此使用自定义指令。如果您需要它应该在点击时工作,然后点击设置

directives: 
  click: 
    // directive definition
    inserted: function (el) 
      el.focus()
    
  

并使用它

<input v-focus> or <input v-click>

enter code here

【讨论】:

【参考方案2】:

当我们验证表单并希望动态设置每个字段的焦点时,这对我有用

           this.$validator.validateAll("FORM_NAME").then(valid => 

                var errors = this.$validator.errors;

                if (valid) 
                    console.log('All Fields are valid')
                 else 
                    const errorFieldName = this.$validator.errors.items[0].field;
                    console.log(errorFieldName);
                    this.$refs[errorFieldName].focus();
                

            );

【讨论】:

【参考方案3】:

autofocus 属性是你的朋友:

<input type="text" autofocus />

【讨论】:

(注意:自动对焦不适用于移动版 Safari)来自 Vue 文档。 唉,SPA路由在玩的时候比较脆弱,只在第一次触发。 (如果你 vue-route 到另一个页面并最终回到这里,它无法设置焦点。) ref=... 和 .focus() 正在通过测试,虽然我还没有在 ios 上测试过。【参考方案4】:

您使用this.$nextTick(); 的方式不正确。你应该给它一个回调函数。

this.$nextTick(function () 
    this.$refs["input_" + id].focus()
)

https://jsfiddle.net/un65e9oc/7/


但我不确定该数组访问对您的工作方式,因为正如我所注意到的,$refs 是一个对象,其键引用引用名称。

[编辑:感谢@Phil 的评论,上面很清楚。]


以上是您问题的正确解决方案。既然你已经得到了答案,那我再补充一点。

您看到此行为的原因是,当您在 showInput() 方法中更改文本框的可见性时,您在 $refs 中保存的引用不会更新。所以当你调用this.$refs["input_" + id].focus();时,它实际上是在尝试在隐藏元素上设置focus(因为当前引用没有更新)。

这就是为什么您需要致电$nextTick() 来更新它。但是,如果您想快速解决问题,而无需调用 $nextTick(),您可以像这样手动更新它:

this.displayTitleInput = "inline-block"
this.$refs["input_" + id].style.display = this.displayTitleInput

this.$refs["input_" + id].focus();

这也可以 :) 希望它有所帮助!

【讨论】:

见注释here ~ "当使用v-for的元素/组件时,注册的引用将是一个包含DOM节点或组件实例的Array 。” 是的,那个也让我有点吃惊:) 哦!!!!太感谢了!!!显示后放置焦点!我知道了。你很聪明!!! @Phil 是的,我现在注意到了这个数组。似乎如果您不使用v-for,它会将引用保存在一个对象中。但是,恐怕您对this 的评论似乎无效。它在这里完美运行。 jsfiddle.net/un65e9oc/7 啊,当然。 Vue 默认 $nextTick context param 为当前的 Vue 实例。【参考方案5】:

您的主要问题是 $nextTick 采用回调函数但您正在执行

this.$refs["input_" + id][0].focus()

马上。你可以让你的代码正常工作

this.$nextTick(() => 
  this.$refs["input_" + id][0].focus()
)

但是,我认为您会遇到更多问题,并且您的代码可以变得更加简单。

您会发现一个问题是,由于您的样式规则,当双击其中任何一个节点时,您的所有节点输入都将变得可见。

您可以改为将 "editing" 标志存储在 node 或单独的对象中。

下面是一个通过...简化代码的示例

    v-for 循环中使用ref 的类数组性质,并且 在@keydown 事件绑定上使用enter 修饰符

new Vue(
  el: '#app',
  data: 
    list: [
      id: 1, title: 'Node #1',
      id: 2, title: 'Node #2'
    ],
    editing: 
  ,
  methods: 
    showInput(id, index) 
      this.$set(this.editing, id, true)
      
      this.$nextTick(() => 
        this.$refs.input[index].focus()
      )
    ,
    hideInput(id) 
      this.editing[id] = false
    
  
)
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<ul id="app">
  <li v-for="(node, index) in list">
    <span v-show="!editing[node.id]" @dblclick="showInput(node.id, index)">
       node.title 
    </span>
    <input v-show="editing[node.id]" type="text"
           ref="input" :value="node.title"
           @blur="hideInput(node.id)" @keydown.enter="hideInput(node.id)">
  </li>
</ul>

【讨论】:

天哪!!!太感谢了!!!你是个天才。我没用过这个。$set 之前。很有技术含量! @nichika 不客气。 this.$setVue.set 相同。您最初需要将其用于响应性,editing 没有属性,因此 Vue 不会自然地检测到新属性。见vuejs.org/v2/guide/reactivity.html

以上是关于vue.js 将重点放在输入上的主要内容,如果未能解决你的问题,请参考以下文章

Vue.js 2.0 学习重点记录

Vue.js 2.0 学习重点记录

Vue 通过 refs 将焦点放在输入上

React 如何转 Vue.js

《vue.js从入门到项目实战》的项目实战笔记

Vue JS - 将 Json 放在数据上