uni-search-bar.vue 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  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.searchVal = ""
  177. this.$emit("clear", '');
  178. },
  179. cancel() {
  180. if(this.readonly) return
  181. this.$emit("cancel", {
  182. value: this.searchVal
  183. });
  184. this.searchVal = ""
  185. this.show = false
  186. this.showSync = false
  187. // #ifndef APP-PLUS
  188. uni.hideKeyboard()
  189. // #endif
  190. // #ifdef APP-PLUS
  191. plus.key.hideSoftKeybord()
  192. // #endif
  193. },
  194. confirm() {
  195. // #ifndef APP-PLUS
  196. uni.hideKeyboard();
  197. // #endif
  198. // #ifdef APP-PLUS
  199. plus.key.hideSoftKeybord()
  200. // #endif
  201. this.$emit("confirm", {
  202. value: this.searchVal
  203. })
  204. },
  205. blur() {
  206. // #ifndef APP-PLUS
  207. uni.hideKeyboard();
  208. // #endif
  209. // #ifdef APP-PLUS
  210. plus.key.hideSoftKeybord()
  211. // #endif
  212. this.$emit("blur", {
  213. value: this.searchVal
  214. })
  215. },
  216. emitFocus(e) {
  217. this.$emit("focus", e.detail)
  218. }
  219. }
  220. };
  221. </script>
  222. <style lang="scss">
  223. $uni-searchbar-height: 36px;
  224. .uni-searchbar {
  225. /* #ifndef APP-NVUE */
  226. display: flex;
  227. /* #endif */
  228. flex-direction: row;
  229. position: relative;
  230. padding: 10px;
  231. // background-color: #fff;
  232. }
  233. .uni-searchbar__box {
  234. /* #ifndef APP-NVUE */
  235. display: flex;
  236. box-sizing: border-box;
  237. /* #endif */
  238. overflow: hidden;
  239. position: relative;
  240. flex: 1;
  241. justify-content: left;
  242. flex-direction: row;
  243. align-items: center;
  244. height: $uni-searchbar-height;
  245. padding: 5px 8px 5px 0px;
  246. }
  247. .uni-searchbar__box-icon-search {
  248. /* #ifndef APP-NVUE */
  249. display: flex;
  250. /* #endif */
  251. flex-direction: row;
  252. // width: 32px;
  253. padding: 0 8px;
  254. justify-content: center;
  255. align-items: center;
  256. color: #B3B3B3;
  257. }
  258. .uni-searchbar__box-search-input {
  259. flex: 1;
  260. font-size: 14px;
  261. color: #333;
  262. margin-left: 5px;
  263. margin-top: 1px;
  264. background-color: inherit;
  265. }
  266. .uni-searchbar__box-icon-clear {
  267. align-items: center;
  268. line-height: 24px;
  269. padding-left: 8px;
  270. /* #ifdef H5 */
  271. cursor: pointer;
  272. /* #endif */
  273. }
  274. .uni-searchbar__text-placeholder {
  275. font-size: 14px;
  276. color: #B3B3B3;
  277. margin-left: 5px;
  278. text-align: left;
  279. }
  280. .uni-searchbar__cancel {
  281. padding-left: 10px;
  282. line-height: $uni-searchbar-height;
  283. font-size: 14px;
  284. color: #333333;
  285. /* #ifdef H5 */
  286. cursor: pointer;
  287. /* #endif */
  288. }
  289. </style>