uni-search-bar.vue 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. s<template>
  2. <view class="uni-searchbar">
  3. <view :style="{borderRadius:radius+'px',backgroundColor: bgColor}" class="uni-searchbar__box" @click="searchClick">
  4. <view class="uni-searchbar__box-icon-search">
  5. <slot name="searchIcon">
  6. <uni-icons color="#c0c4cc" size="18" type="search" />
  7. </slot>
  8. </view>
  9. <input v-if="show || searchVal" :focus="showSync" :placeholder="placeholderText" :maxlength="maxlength" class="uni-searchbar__box-search-input"
  10. confirm-type="search" type="text" v-model="searchVal" @confirm="confirm" @blur="blur" @focus="emitFocus" />
  11. <text v-else class="uni-searchbar__text-placeholder">{{ placeholder }}</text>
  12. <view v-if="show && (clearButton==='always'||clearButton==='auto'&&searchVal!=='')" class="uni-searchbar__box-icon-clear"
  13. @click="clear">
  14. <slot name="clearIcon">
  15. <uni-icons color="#c0c4cc" size="20" type="clear" />
  16. </slot>
  17. </view>
  18. </view>
  19. <text @click="cancel" class="uni-searchbar__cancel" v-if="cancelButton ==='always' || show && cancelButton ==='auto'">{{cancelTextI18n}}</text>
  20. </view>
  21. </template>
  22. <script>
  23. import {
  24. initVueI18n
  25. } from '@dcloudio/uni-i18n'
  26. import messages from './i18n/index.js'
  27. const { t } = initVueI18n(messages)
  28. /**
  29. * SearchBar 搜索栏
  30. * @description 搜索栏组件,通常用于搜索商品、文章等
  31. * @tutorial https://ext.dcloud.net.cn/plugin?id=866
  32. * @property {Number} radius 搜索栏圆角
  33. * @property {Number} maxlength 输入最大长度
  34. * @property {String} placeholder 搜索栏Placeholder
  35. * @property {String} clearButton = [always|auto|none] 是否显示清除按钮
  36. * @value always 一直显示
  37. * @value auto 输入框不为空时显示
  38. * @value none 一直不显示
  39. * @property {String} cancelButton = [always|auto|none] 是否显示取消按钮
  40. * @value always 一直显示
  41. * @value auto 输入框不为空时显示
  42. * @value none 一直不显示
  43. * @property {String} cancelText 取消按钮的文字
  44. * @property {String} bgColor 输入框背景颜色
  45. * @property {Boolean} focus 是否自动聚焦
  46. * @event {Function} confirm uniSearchBar 的输入框 confirm 事件,返回参数为uniSearchBar的value,e={value:Number}
  47. * @event {Function} input uniSearchBar 的 value 改变时触发事件,返回参数为uniSearchBar的value,e=value
  48. * @event {Function} cancel 点击取消按钮时触发事件,返回参数为uniSearchBar的value,e={value:Number}
  49. * @event {Function} clear 点击清除按钮时触发事件,返回参数为uniSearchBar的value,e={value:Number}
  50. * @event {Function} blur input失去焦点时触发事件,返回参数为uniSearchBar的value,e={value:Number}
  51. */
  52. export default {
  53. name: "UniSearchBar",
  54. emits:['input','update:modelValue','clear','cancel','confirm','blur','focus'],
  55. props: {
  56. placeholder: {
  57. type: String,
  58. default: ""
  59. },
  60. radius: {
  61. type: [Number, String],
  62. default: 5
  63. },
  64. clearButton: {
  65. type: String,
  66. default: "auto"
  67. },
  68. cancelButton: {
  69. type: String,
  70. default: "auto"
  71. },
  72. cancelText: {
  73. type: String,
  74. default: '取消'
  75. },
  76. bgColor: {
  77. type: String,
  78. default: "#F8F8F8"
  79. },
  80. maxlength: {
  81. type: [Number, String],
  82. default: 100
  83. },
  84. value: {
  85. type: [Number, String],
  86. default: ""
  87. },
  88. modelValue: {
  89. type: [Number, String],
  90. default: ""
  91. },
  92. focus: {
  93. type: Boolean,
  94. default: false
  95. }
  96. },
  97. data() {
  98. return {
  99. show: false,
  100. showSync: false,
  101. searchVal: ''
  102. }
  103. },
  104. computed:{
  105. cancelTextI18n() {
  106. return this.cancelText || t("uni-search-bar.cancel")
  107. },
  108. placeholderText() {
  109. return this.placeholder || t("uni-search-bar.placeholder")
  110. }
  111. },
  112. watch: {
  113. // #ifndef VUE3
  114. value: {
  115. immediate: true,
  116. handler(newVal) {
  117. this.searchVal = newVal
  118. if (newVal) {
  119. this.show = true
  120. }
  121. }
  122. },
  123. // #endif
  124. // #ifdef VUE3
  125. modelValue: {
  126. immediate: true,
  127. handler(newVal) {
  128. this.searchVal = newVal
  129. if (newVal) {
  130. this.show = true
  131. }
  132. }
  133. },
  134. // #endif
  135. focus: {
  136. immediate: true,
  137. handler(newVal) {
  138. if (newVal) {
  139. this.show = true;
  140. this.$nextTick(() => {
  141. this.showSync = true
  142. })
  143. }
  144. }
  145. },
  146. searchVal(newVal, oldVal) {
  147. // #ifndef VUE3
  148. this.$emit("input", newVal)
  149. // #endif
  150. // #ifdef VUE3
  151. this.$emit("update:modelValue", newVal)
  152. // #endif
  153. }
  154. },
  155. methods: {
  156. searchClick() {
  157. if (this.show) {
  158. return
  159. }
  160. this.show = true;
  161. this.$nextTick(() => {
  162. this.showSync = true
  163. })
  164. },
  165. clear() {
  166. this.$emit("clear", {
  167. value: this.searchVal
  168. })
  169. this.searchVal = ""
  170. },
  171. cancel() {
  172. this.$emit("cancel", {
  173. value: this.searchVal
  174. });
  175. this.searchVal = ""
  176. this.show = false
  177. this.showSync = false
  178. // #ifndef APP-PLUS
  179. uni.hideKeyboard()
  180. // #endif
  181. // #ifdef APP-PLUS
  182. plus.key.hideSoftKeybord()
  183. // #endif
  184. },
  185. confirm() {
  186. // #ifndef APP-PLUS
  187. uni.hideKeyboard();
  188. // #endif
  189. // #ifdef APP-PLUS
  190. plus.key.hideSoftKeybord()
  191. // #endif
  192. this.$emit("confirm", {
  193. value: this.searchVal
  194. })
  195. },
  196. blur() {
  197. // #ifndef APP-PLUS
  198. uni.hideKeyboard();
  199. // #endif
  200. // #ifdef APP-PLUS
  201. plus.key.hideSoftKeybord()
  202. // #endif
  203. this.$emit("blur", {
  204. value: this.searchVal
  205. })
  206. },
  207. emitFocus(e) {
  208. this.$emit("focus", e.detail)
  209. }
  210. }
  211. };
  212. </script>
  213. <style lang="scss" >
  214. $uni-searchbar-height: 36px;
  215. .uni-searchbar {
  216. /* #ifndef APP-NVUE */
  217. display: flex;
  218. /* #endif */
  219. flex-direction: row;
  220. position: relative;
  221. padding: 10px;
  222. // background-color: #fff;
  223. }
  224. .uni-searchbar__box {
  225. /* #ifndef APP-NVUE */
  226. display: flex;
  227. box-sizing: border-box;
  228. /* #endif */
  229. overflow: hidden;
  230. position: relative;
  231. flex: 1;
  232. justify-content: center;
  233. flex-direction: row;
  234. align-items: center;
  235. height: $uni-searchbar-height;
  236. padding: 5px 8px 5px 0px;
  237. }
  238. .uni-searchbar__box-icon-search {
  239. /* #ifndef APP-NVUE */
  240. display: flex;
  241. /* #endif */
  242. flex-direction: row;
  243. // width: 32px;
  244. padding: 0 8px;
  245. justify-content: center;
  246. align-items: center;
  247. color: #B3B3B3;
  248. }
  249. .uni-searchbar__box-search-input {
  250. flex: 1;
  251. font-size: 14px;
  252. color: #333;
  253. }
  254. .uni-searchbar__box-icon-clear {
  255. align-items: center;
  256. line-height: 24px;
  257. padding-left: 8px;
  258. /* #ifdef H5 */
  259. cursor: pointer;
  260. /* #endif */
  261. }
  262. .uni-searchbar__text-placeholder {
  263. font-size: 14px;
  264. color: #B3B3B3;
  265. margin-left: 5px;
  266. }
  267. .uni-searchbar__cancel {
  268. padding-left: 10px;
  269. line-height: $uni-searchbar-height;
  270. font-size: 14px;
  271. color: #333333;
  272. /* #ifdef H5 */
  273. cursor: pointer;
  274. /* #endif */
  275. }
  276. </style>