uni-search-bar.vue 6.9 KB

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