How does MaterialUI do this?
P粉916760429
2023-09-04 18:17:31
<p>If you look at their autocomplete component: https://mui.com/material-ui/react-autocomplete/</p>
<p>The input box retains focus after clicking on a suggestion in the dropdown...how do they do that? In every variant in my own vue app (not using material UI) I can't get the click event to prevent the input from losing focus. </p>
<p>I've been trying to google this problem for a long time but haven't seen a clear solution. For example, people suggested mousedown/touchstart, but this breaks scrolling (by dragging the dropdown). MaterialUI apparently doesn't have this problem and doesn't seem to use mousedown. </p>
<p>I tried analyzing the event using Chrome Dev Tools, but I can only see a single click event, but with the stripped down code it's hard to tell what's going on. </p>
<p>Vuetify does this too: https://github.com/vuetifyjs/vuetify/blob/master/packages/vuetify/src/components/VAutocomplete/VAutocomplete.ts</p>
<p>If anyone has this problem, I also found this helpful https://codepen.io/Pineapple/pen/MWBVqGW</p>
<p><strong>Edit</strong>This is what I'm doing: </p>
<pre class="brush:html;toolbar:false;"> <app-input-autocomplete
@autocomplete-select="onSelect"
@autocomplete-close="onClose"
:open="open">
<template #default="{ result }">
<div class="input-autocomplete-address">
{{ result.address }}
</div>
</template>
</app-input-autocomplete>
</pre>
<p>Then in <code>app-input-autocomplete</code>: </p>
<pre class="brush:html;toolbar:false;"><template>
<app-input
@focus="onFocus"
@blur="onBlur"
v-bind="$attrs">
<template #underInput>
<div ref="dropdown" v-show="open" class="input-autocomplete-dropdown">
<div class="input-autocomplete-results">
<div v-for="result in results" :key="result.id" @click="onClick(result)" class="input-autocomplete-result">
<slot :result="result" />
</div>
</div>
</div>
</template>
</app-input>
</template>
<script>
import { ref, toRef } from 'vue';
import AppInput from '@/components/AppInput.vue';
import { onClickOutside } from '@vueuse/core';
export default {
components: {
AppInput,
},
inheritAttrs: false,
props: {
open: {
type: Boolean,
default: false,
},
results: {
type: Array,
default: () => ([]),
},
},
emits: ['autocomplete-close', 'autocomplete-select'],
setup(props, { emit }) {
const dropdown = ref(null);
const open = toRef(props, 'open');
const focused = ref(false);
onClickOutside(dropdown, () => {
if (!focused.value && open.value) {
emit('autocomplete-close');
}
});
return {
dropdown,
focused,
};
},
methods: {
onFocus() {
this.focused = true;
},
onBlur() {
this.focused = false;
},
onClick(result) {
this.$emit('autocomplete-select', result);
},
},
};
</script>
</pre></p>
I solved this problem by doing the following, thanks to @Claies for the idea and this link:
https://codepen.io/Pineapple/pen/MWBVqGW
event.preventDefault
onmousedown
open = true