index.taro.vue 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. <template>
  2. <view class="nut-searchbar" :style="searchbarStyle">
  3. <view v-if="$slots.leftout" class="nut-searchbar__search-icon nut-searchbar__left-search-icon">
  4. <slot name="leftout"></slot>
  5. </view>
  6. <view class="nut-searchbar__search-input" :style="inputSearchbarStyle">
  7. <view v-if="$slots.leftin" class="nut-searchbar__search-icon nut-searchbar__iptleft-search-icon">
  8. <slot name="leftin"></slot>
  9. </view>
  10. <view class="nut-searchbar__input-inner">
  11. <form action="#" onsubmit="return false" @submit.prevent="handleSubmit">
  12. <input
  13. ref="inputsearch"
  14. class="nut-searchbar__input-bar"
  15. :type="inputType"
  16. :maxlength="maxLength"
  17. :placeholder="placeholder || translate('placeholder')"
  18. :value="modelValue"
  19. :confirm-type="confirmType"
  20. :disabled="disabled"
  21. :readonly="readonly"
  22. @click="clickInput"
  23. @input="valueChange"
  24. @focus="valueFocus"
  25. @blur="valueBlur"
  26. @confirm="handleSubmit"
  27. :style="styleSearchbar"
  28. />
  29. </form>
  30. <view @click="handleClear" class="nut-searchbar__input-clear" v-if="clearable" v-show="modelValue.length > 0">
  31. <nut-icon name="circle-close" size="12" color="#555"></nut-icon>
  32. </view>
  33. </view>
  34. <view v-if="$slots.rightin" class="nut-searchbar__search-icon nut-searchbar__iptright-sarch-icon">
  35. <slot name="rightin"></slot>
  36. </view>
  37. </view>
  38. <view v-if="$slots.rightout" class="nut-searchbar__search-icon nut-searchbar__right-search-icon">
  39. <slot name="rightout"></slot>
  40. </view>
  41. </view>
  42. </template>
  43. <script lang="ts">
  44. import { toRefs, reactive, computed, ref, onMounted, PropType } from 'vue';
  45. import { createComponent } from '@/packages/utils/create';
  46. const { create, translate } = createComponent('searchbar');
  47. interface Events {
  48. eventName: 'change' | 'focus' | 'blur' | 'clear' | 'update:modelValue';
  49. params: (string | number | Event)[];
  50. }
  51. export type confirmTextType = 'send' | 'search' | 'next' | 'go' | 'done';
  52. export default create({
  53. props: {
  54. modelValue: {
  55. type: [String, Number],
  56. default: ''
  57. },
  58. inputType: {
  59. type: String,
  60. default: 'text'
  61. },
  62. maxLength: {
  63. type: [String, Number],
  64. default: '9999'
  65. },
  66. placeholder: {
  67. type: String,
  68. default: ''
  69. },
  70. clearable: {
  71. type: Boolean,
  72. default: true
  73. },
  74. background: {
  75. type: String,
  76. default: ''
  77. },
  78. inputBackground: {
  79. type: String,
  80. default: ''
  81. },
  82. confirmType: {
  83. type: String as PropType<confirmTextType>,
  84. default: 'done'
  85. },
  86. autofocus: {
  87. type: Boolean,
  88. default: false
  89. },
  90. disabled: {
  91. type: Boolean,
  92. default: false
  93. },
  94. readonly: {
  95. type: Boolean,
  96. default: false
  97. },
  98. inputAlign: {
  99. type: String,
  100. default: 'left'
  101. }
  102. },
  103. emits: [
  104. 'change',
  105. 'update:modelValue',
  106. 'blur',
  107. 'focus',
  108. 'clear',
  109. 'search',
  110. 'click-input',
  111. 'click-left-icon',
  112. 'click-right-icon'
  113. ],
  114. setup(props, { emit }) {
  115. const state = reactive({
  116. active: false
  117. });
  118. const searchbarStyle = computed(() => {
  119. return {
  120. background: props.background
  121. };
  122. });
  123. const inputSearchbarStyle = computed(() => {
  124. return {
  125. background: props.inputBackground
  126. };
  127. });
  128. const valueChange = (event: Event) => {
  129. const input = event.target as HTMLInputElement;
  130. let val = input.value;
  131. if (props.maxLength && val.length > Number(props.maxLength)) {
  132. val = val.slice(0, Number(props.maxLength));
  133. }
  134. emit('update:modelValue', val, event);
  135. emit('change', val, event);
  136. };
  137. const valueFocus = (event: Event) => {
  138. const input = event.target as HTMLInputElement;
  139. let value = input.value;
  140. state.active = true;
  141. emit('focus', value, event);
  142. };
  143. const valueBlur = (event: Event) => {
  144. setTimeout(() => {
  145. state.active = false;
  146. }, 0);
  147. const input = event.target as HTMLInputElement;
  148. let value = input.value;
  149. if (props.maxLength && value.length > Number(props.maxLength)) {
  150. value = value.slice(0, Number(props.maxLength));
  151. }
  152. emit('blur', value, event);
  153. };
  154. const handleClear = (event: Event) => {
  155. emit('update:modelValue', '', event);
  156. emit('change', '', event);
  157. emit('clear', '');
  158. };
  159. const handleSubmit = () => {
  160. emit('search', props.modelValue);
  161. };
  162. const clickInput = (event: Event) => {
  163. emit('click-input', event);
  164. };
  165. const leftIconClick = (event: Event) => {
  166. emit('click-left-icon', props.modelValue, event);
  167. };
  168. const rightIconClick = (event: Event) => {
  169. emit('click-right-icon', props.modelValue, event);
  170. };
  171. const styleSearchbar: any = computed(() => {
  172. return {
  173. 'text-align': props.inputAlign
  174. };
  175. });
  176. const inputsearch: any = ref(null);
  177. onMounted(() => {
  178. if (props.autofocus) {
  179. inputsearch.value.focus();
  180. }
  181. });
  182. return {
  183. inputsearch,
  184. ...toRefs(state),
  185. valueChange,
  186. valueFocus,
  187. valueBlur,
  188. handleClear,
  189. handleSubmit,
  190. searchbarStyle,
  191. inputSearchbarStyle,
  192. translate,
  193. clickInput,
  194. leftIconClick,
  195. rightIconClick,
  196. styleSearchbar
  197. };
  198. }
  199. });
  200. </script>