有没有一种方法可以同时添加onkeypress和onclick事件监听器?

3

我有两个问题,有点相关。

1)是否可能将下面的两个函数合并成一个更加流畅的函数,或者我必须只创建一个函数并在这两个事件监听器中调用它。

input.addEventListener("keyup", () => {
   if (event.keyCode === 13) {
     // code here 
}

并且

input.addEventListener("click", () => {
     // code here 
}

但这本质上是代码的复制

2) 是否有一种方法可以基于数组内容创建简单/基本的自动完成菜单(类似于Google,但远远不如它强大),在输入/搜索栏中输入时?为了澄清,w3schools的示例对我无效。

4个回答

4
这是您如何将多个事件附加到单个元素的方法。 可参考 Mozilla 文档

var elem = document.querySelector('input')

elem.addEventListener('keyup', eventhandler, false);
//elem.addEventListener('click', eventhandler, false);// not sure about this event
elem.addEventListener('keydown', eventhandler, false);

function eventhandler(event) {
     if (event.keyCode === 13) { // you press enter you get alert 
     
        alert("hi");
     }
}
<input type="text" id="field">


但是,keyup和keydown不基本上是一样的吗?它们都来自于同一个元素,但是我希望点击的按钮是完全不同的元素,所以我想知道是否可以将它们绑定到输入的公共链接周围?另外,人们是如何做那个代码片段的? - Anan
结尾的 false 代表什么?我猜 true 也是一个可能性,那会做什么? - Anan
@Anan 当您撰写答案时,编辑器中有一个按钮可打开代码片段编辑器。 - some
@Anan,你在addEventListener()中传递了三个参数,第三个参数是选项,用于指定事件侦听器的特性。你可以查看Mozilla文档。 - Shubham Dixit
在使用npm启动网站时,从event.keyCode中获取错误Unexpected use of 'event' no-restricted-globals,文档没有涵盖此问题。 - Anan
显示剩余4条评论

2
使用一个单独的函数,在两个事件监听器中调用它。最初的回答。
function doWhatIWant() {
    // code here
}

input.addEventListener("keyup", () => {
   if (event.keyCode === 13) {
     doWhatIWant();
}

input.addEventListener("click", () => {
     doWhatIWant();
}

这就是我一直在做的事情,希望能有更简化的方法,但似乎这已经是最好的了。你知道任何自动完成或其他类似的解决方案吗?我想避免使用下拉菜单,因为它会变得非常庞大(可能会超出屏幕),而且箭头会破坏我的美感。 - Anan
有许多自动完成小部件,尽管其中一些需要jQuery(包括当然是jQuery UI小部件)。 - Barmar
已经有一个可用的,但需要提交相同数据两次才能工作。 - Anan
你应该发布一个新的问题来解决这个问题。听起来你没有正确地使用异步代码。 - Barmar

1
你可以尝试直接将onclick事件监听器和/或keypress事件监听器添加到按钮中,并在JavaScript中使用其他内容,使代码内容运行在自己的函数中。
<input type="text" id="input1" placeholder="searchbar">
<button id="button1" onclick=foo()>Search</button>

    function foo() {
      searchResult = document.getElementById("input1").value;
      // code here
    }

    const searchBar = document.getElementById("input1");
    searchBar.addEventListener("keyup", () => {
        if (event.keyCode === 13) {
          // executes the button click
          document.getElementById("myBtn").click();
        }
    });

关于自动完成菜单,我不确定,但您可以尝试将其转换为下拉菜单,但这可能会使您对第一个问题的需求无效。

0

对于您问题中的#1,其他答案似乎已经足够了。

作为另一种选择,您可以使用一些现代JS编写代码,为事件名称数组添加侦听器,并在处理程序函数中处理它们,如下所示:

// Handle keyup/click.
const handlerFn = e => e.type === 'keyup' ? e.keyCode === 13 && doSomething( e.type ) : doSomething( e.type );

// Did something.
const doSomething = type => console.log( `did something when ${type} triggered.` );

// Add handle/click listeners.
['keyup', 'click'].forEach( e => window.addEventListener( e, event => handlerFn( event ) ) );
Click in here, or press enter.

就第二点而言,并且实现第一点,使用数据数组进行过滤,是有可能在您输入时触发搜索的。

作为一种非常基本的实现方法,我建议编写一个函数来处理JS中的正则表达式匹配,通过keyup事件触发它,这样用户在输入时就可以进行过滤。

以下是使用输入和搜索与一些虚拟数据进行搜索的示例:

// Some data to filter/search while typing.
const thingsToFilter = [
 {
  title: "One one one title",
  description: "description for this one one one"
 },
 {
  title: "Number 2",
  description: "2 is two."
 },
 {
  title: "Another Thing",
  description: "description for another things"
 }
];

// Function to match searches.
const findMatches = (stringToMatch, thingsToFilter) => {
 return thingsToFilter.filter(function(thingToFilter) {
  var regex;

  // Search for the stringToMatch from thingsToFilter.
  regex = new RegExp(stringToMatch, "gi");

  // Returns matches based on title or description.
  return thingToFilter.title.match(regex) || thingToFilter.description.match(regex);
 });
};

// Setup event listener for typing in input.
const pageSearch = document.getElementById("search");
pageSearch.addEventListener("keyup", () => {
 let val = pageSearch.value;

 if (val) {
  let matched = findMatches(val, thingsToFilter);
  if (matched) {
   let markup = matched.map(result => `<div class="search-result">${result.title}:${result.description}</div>` ).join("");
   document.getElementById("search-results").innerHTML = markup;
  }
 }
});
<input type="text" id="search" placeholder="Search...">
<div id="search-results"></div>


有没有办法使thingsToFilter数组能够更新?我有一个自动完成功能,只要数组是预定义的,它就可以工作。但是,我希望从rest api下载该数组以供使用,但如果我下载该数组,则似乎无法正常工作。 - Anan
是的,thingsToFilter可以是任何你想要的数据源。这个例子只显示了一个带有"title"和"description"的对象数组,但可以根据需要对返回的任何内容进行过滤和排序。如果你在使用的数据源方面遇到问题,你可以尝试打开一个新的问题,包括一些测试API响应和你正在使用的代码。我唯一的猜测是数据源的格式与脚本所期望的格式不同。 - Tim Elsass
是的,现在我明白了,我没有测试足够,问题在于它只有在第二次访问搜索栏时才会应用,我需要解决它产生的巨大列表,拉伸我的搜索栏到无穷尽的问题。 - Anan
我必须通过两次才能得到响应,这很麻烦(目前只有keydown可以解决,问题是,这意味着它在每个按钮按下时都会重新下载数组,对速度不利),不知道你是否知道如何使其在一次实例后应用并仅在值更改时更新? - Anan
听起来好像开始了,但是接下来发生的任何事情都在数据准备好之前执行,第二个触发的事件是在那时读取第一个调用的数据。我建议确保在执行进一步操作之前等待调用完成。另一个有助于资源管理的提示是去抖动,我建议使用 https://www.npmjs.com/package/lodash.debounce。这篇关于 CSS 技巧的文章解释得更详细,并且有一个带有 ajax 的按键示例:https://css-tricks.com/debouncing-throttling-explained-examples/#article-header-id-3 - Tim Elsass
是的,那只是在数据准备好之前匆忙前进,一个 Promise 解决了它。 - Anan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接