uni-search-bar.vue 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  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" :style="{color:textColor}"
  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 {String} textColor 输入文字颜色
  51. * @property {Boolean} focus 是否自动聚焦
  52. * @property {Boolean} readonly 组件只读,不能有任何操作,只做展示
  53. * @event {Function} confirm uniSearchBar 的输入框 confirm 事件,返回参数为uniSearchBar的value,e={value:Number}
  54. * @event {Function} input uniSearchBar 的 value 改变时触发事件,返回参数为uniSearchBar的value,e=value
  55. * @event {Function} cancel 点击取消按钮时触发事件,返回参数为uniSearchBar的value,e={value:Number}
  56. * @event {Function} clear 点击清除按钮时触发事件,返回参数为uniSearchBar的value,e={value:Number}
  57. * @event {Function} blur input失去焦点时触发事件,返回参数为uniSearchBar的value,e={value:Number}
  58. */
  59. export default {
  60. name: "UniSearchBar",
  61. emits: ['input', 'update:modelValue', 'clear', 'cancel', 'confirm', 'blur', 'focus'],
  62. props: {
  63. placeholder: {
  64. type: String,
  65. default: ""
  66. },
  67. radius: {
  68. type: [Number, String],
  69. default: 5
  70. },
  71. clearButton: {
  72. type: String,
  73. default: "auto"
  74. },
  75. cancelButton: {
  76. type: String,
  77. default: "auto"
  78. },
  79. cancelText: {
  80. type: String,
  81. default: ""
  82. },
  83. bgColor: {
  84. type: String,
  85. default: "#F8F8F8"
  86. },
  87. textColor: {
  88. type: String,
  89. default: "#000000"
  90. },
  91. maxlength: {
  92. type: [Number, String],
  93. default: 100
  94. },
  95. value: {
  96. type: [Number, String],
  97. default: ""
  98. },
  99. modelValue: {
  100. type: [Number, String],
  101. default: ""
  102. },
  103. focus: {
  104. type: Boolean,
  105. default: false
  106. },
  107. readonly: {
  108. type: Boolean,
  109. default: false
  110. }
  111. },
  112. data() {
  113. return {
  114. show: false,
  115. showSync: false,
  116. searchVal: ''
  117. }
  118. },
  119. computed: {
  120. cancelTextI18n() {
  121. return this.cancelText || t("uni-search-bar.cancel")
  122. },
  123. placeholderText() {
  124. return this.placeholder || t("uni-search-bar.placeholder")
  125. }
  126. },
  127. watch: {
  128. // #ifndef VUE3
  129. value: {
  130. immediate: true,
  131. handler(newVal) {
  132. this.searchVal = newVal
  133. if (newVal) {
  134. this.show = true
  135. }
  136. }
  137. },
  138. // #endif
  139. // #ifdef VUE3
  140. modelValue: {
  141. immediate: true,
  142. handler(newVal) {
  143. this.searchVal = newVal
  144. if (newVal) {
  145. this.show = true
  146. }
  147. }
  148. },
  149. // #endif
  150. focus: {
  151. immediate: true,
  152. handler(newVal) {
  153. if (newVal) {
  154. if(this.readonly) return
  155. this.show = true;
  156. this.$nextTick(() => {
  157. this.showSync = true
  158. })
  159. }
  160. }
  161. },
  162. searchVal(newVal, oldVal) {
  163. this.$emit("input", newVal)
  164. // #ifdef VUE3
  165. this.$emit("update:modelValue", newVal)
  166. // #endif
  167. }
  168. },
  169. methods: {
  170. searchClick() {
  171. if(this.readonly) return
  172. if (this.show) {
  173. return
  174. }
  175. this.show = true;
  176. this.$nextTick(() => {
  177. this.showSync = true
  178. })
  179. },
  180. clear() {
  181. this.searchVal = ""
  182. this.$nextTick(() => {
  183. this.$emit("clear", { value: "" })
  184. })
  185. },
  186. cancel() {
  187. if(this.readonly) return
  188. this.$emit("cancel", {
  189. value: this.searchVal
  190. });
  191. this.searchVal = ""
  192. this.show = false
  193. this.showSync = false
  194. // #ifndef APP-PLUS
  195. uni.hideKeyboard()
  196. // #endif
  197. // #ifdef APP-PLUS
  198. plus.key.hideSoftKeybord()
  199. // #endif
  200. },
  201. confirm() {
  202. // #ifndef APP-PLUS
  203. uni.hideKeyboard();
  204. // #endif
  205. // #ifdef APP-PLUS
  206. plus.key.hideSoftKeybord()
  207. // #endif
  208. this.$emit("confirm", {
  209. value: this.searchVal
  210. })
  211. },
  212. blur() {
  213. // #ifndef APP-PLUS
  214. uni.hideKeyboard();
  215. // #endif
  216. // #ifdef APP-PLUS
  217. plus.key.hideSoftKeybord()
  218. // #endif
  219. this.$emit("blur", {
  220. value: this.searchVal
  221. })
  222. },
  223. emitFocus(e) {
  224. this.$emit("focus", e.detail)
  225. }
  226. }
  227. };
  228. </script>
  229. <style lang="scss">
  230. $uni-searchbar-height: 36px;
  231. .uni-searchbar {
  232. /* #ifndef APP-NVUE */
  233. display: flex;
  234. /* #endif */
  235. flex-direction: row;
  236. position: relative;
  237. padding: 10px;
  238. // background-color: #fff;
  239. }
  240. .uni-searchbar__box {
  241. /* #ifndef APP-NVUE */
  242. display: flex;
  243. box-sizing: border-box;
  244. justify-content: left;
  245. /* #endif */
  246. overflow: hidden;
  247. position: relative;
  248. flex: 1;
  249. flex-direction: row;
  250. align-items: center;
  251. height: $uni-searchbar-height;
  252. padding: 5px 8px 5px 0px;
  253. }
  254. .uni-searchbar__box-icon-search {
  255. /* #ifndef APP-NVUE */
  256. display: flex;
  257. /* #endif */
  258. flex-direction: row;
  259. // width: 32px;
  260. padding: 0 8px;
  261. justify-content: center;
  262. align-items: center;
  263. color: #B3B3B3;
  264. }
  265. .uni-searchbar__box-search-input {
  266. flex: 1;
  267. font-size: 14px;
  268. color: #333;
  269. margin-left: 5px;
  270. margin-top: 1px;
  271. /* #ifndef APP-NVUE */
  272. background-color: inherit;
  273. /* #endif */
  274. }
  275. .uni-searchbar__box-icon-clear {
  276. align-items: center;
  277. line-height: 24px;
  278. padding-left: 8px;
  279. /* #ifdef H5 */
  280. cursor: pointer;
  281. /* #endif */
  282. }
  283. .uni-searchbar__text-placeholder {
  284. font-size: 14px;
  285. color: #B3B3B3;
  286. margin-left: 5px;
  287. text-align: left;
  288. }
  289. .uni-searchbar__cancel {
  290. padding-left: 10px;
  291. line-height: $uni-searchbar-height;
  292. font-size: 14px;
  293. color: #333333;
  294. /* #ifdef H5 */
  295. cursor: pointer;
  296. /* #endif */
  297. }
  298. </style>