index.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. import baseComponent from '../helpers/baseComponent'
  2. import classNames from '../helpers/libs/classNames'
  3. import styleToCssString from '../helpers/libs/styleToCssString'
  4. import warning from '../helpers/libs/warning'
  5. import { omit } from '../helpers/shared/omit'
  6. import { defaults as dialogConfig, defaultOptions as dialogOptions } from '../dialog/utils'
  7. import { defaults as loadingConfig } from '../loading/utils'
  8. import { defaults as notificationConfig } from '../notification/utils'
  9. import { defaults as toastConfig } from '../toast/utils'
  10. import { defaults as toptipsConfig } from '../toptips/utils'
  11. let uuid = 0
  12. const appConfig = {
  13. dialog: omit({
  14. ...dialogConfig,
  15. ...dialogOptions,
  16. resetOnClose: true,
  17. }, ['onCancel', 'onConfirm']),
  18. loading: { ...loadingConfig },
  19. notification: omit(notificationConfig, ['onClick', 'onClose']),
  20. toast: omit(toastConfig, ['success']),
  21. toptips: omit(toptipsConfig, ['success']),
  22. }
  23. const warningUnhooked = (valid, componentName) => {
  24. if (!valid && console !== undefined) {
  25. warning(false, `<${componentName} /> 无法找到对应的组件,请按文档说明使用组件`)
  26. }
  27. }
  28. const useComponentRef = (componentName, vm) => {
  29. const { prefixCls, uuid } = vm.data
  30. const selector = `#${prefixCls}__${componentName}-${uuid}`
  31. const componentCtx = vm.querySelector(selector)
  32. return {
  33. current: componentCtx,
  34. }
  35. }
  36. const useDialog = (props, vm) => {
  37. const holderRef = useComponentRef('dialog', vm)
  38. const wrapAPI = {}
  39. const keys = ['show', 'open', 'alert', 'confirm', 'prompt']
  40. keys.forEach((type) => {
  41. wrapAPI[type] = (config) => {
  42. if (!holderRef.current) {
  43. warningUnhooked(false, 'Dialog')
  44. const fakeResult = () => {}
  45. fakeResult.then = () => {}
  46. return fakeResult
  47. }
  48. return holderRef.current[type]({ ...props, ...config })
  49. }
  50. })
  51. return [
  52. wrapAPI,
  53. holderRef,
  54. ]
  55. }
  56. const useLoading = (props, vm) => {
  57. const holderRef = useComponentRef('loading', vm)
  58. const show = (config) => {
  59. if (!holderRef.current) {
  60. warningUnhooked(false, 'Loading')
  61. const fakeResult = () => {}
  62. fakeResult.then = () => {}
  63. return fakeResult
  64. }
  65. return holderRef.current.show({ ...props, ...config })
  66. }
  67. const hide = () => {
  68. if (holderRef.current) {
  69. holderRef.current.hide()
  70. }
  71. }
  72. return [
  73. { show, hide },
  74. holderRef,
  75. ]
  76. }
  77. const useNotification = (props, vm) => {
  78. const holderRef = useComponentRef('notification', vm)
  79. const show = (config) => {
  80. if (!holderRef.current) {
  81. warningUnhooked(false, 'Notification')
  82. const fakeResult = () => {}
  83. fakeResult.then = () => {}
  84. return fakeResult
  85. }
  86. return holderRef.current.show({ ...props, ...config })
  87. }
  88. const hide = () => {
  89. if (holderRef.current) {
  90. holderRef.current.hide()
  91. }
  92. }
  93. return [
  94. { show, hide },
  95. holderRef,
  96. ]
  97. }
  98. const useToast = (props, vm) => {
  99. const holderRef = useComponentRef('toast', vm)
  100. const wrapAPI = {}
  101. const keys = ['show', 'success', 'warning', 'info', 'error']
  102. keys.forEach((type) => {
  103. wrapAPI[type] = (config) => {
  104. if (!holderRef.current) {
  105. warningUnhooked(false, 'Toast')
  106. const fakeResult = () => {}
  107. fakeResult.then = () => {}
  108. return fakeResult
  109. }
  110. return holderRef.current[type]({ ...props, ...config })
  111. }
  112. })
  113. return [
  114. wrapAPI,
  115. holderRef,
  116. ]
  117. }
  118. const useToptips = (props, vm) => {
  119. const holderRef = useComponentRef('toptips', vm)
  120. const wrapAPI = {}
  121. const keys = ['show', 'success', 'warn', 'info', 'error']
  122. keys.forEach((type) => {
  123. wrapAPI[type] = (config) => {
  124. if (!holderRef.current) {
  125. warningUnhooked(false, 'Toptips')
  126. const fakeResult = () => {}
  127. fakeResult.then = () => {}
  128. return fakeResult
  129. }
  130. return holderRef.current[type]({ ...props, ...config })
  131. }
  132. })
  133. return [
  134. wrapAPI,
  135. holderRef,
  136. ]
  137. }
  138. baseComponent({
  139. useExport: true,
  140. properties: {
  141. prefixCls: {
  142. type: String,
  143. value: 'wux-app',
  144. },
  145. config: {
  146. type: Object,
  147. value: appConfig,
  148. },
  149. shadowRoot: {
  150. type: Boolean,
  151. value: false,
  152. },
  153. // 自定义类名
  154. wrapCls: {
  155. type: String,
  156. value: '',
  157. },
  158. // 自定义样式
  159. wrapStyle: {
  160. type: [String, Object],
  161. value: '',
  162. observer(newVal) {
  163. this.setData({
  164. extStyle: styleToCssString(newVal),
  165. })
  166. },
  167. },
  168. },
  169. data: {
  170. extStyle: '',
  171. uuid,
  172. memoizedAPI: null,
  173. },
  174. observers: {
  175. ['prefixCls, config'](...args) {
  176. this.updateMemoizedAPI(args[1])
  177. },
  178. },
  179. computed: {
  180. classes: ['prefixCls, uuid', function(prefixCls, uuid) {
  181. const wrap = classNames(prefixCls)
  182. const dialog = `${prefixCls}__dialog-${uuid}`
  183. const loading = `${prefixCls}__loading-${uuid}`
  184. const notification = `${prefixCls}__notification-${uuid}`
  185. const toast = `${prefixCls}__toast-${uuid}`
  186. const toptips = `${prefixCls}__toptips-${uuid}`
  187. return {
  188. wrap,
  189. dialog,
  190. loading,
  191. notification,
  192. toast,
  193. toptips,
  194. }
  195. }],
  196. },
  197. methods: {
  198. updateMemoizedAPI(config) {
  199. const [dialogAPI] = useDialog(appConfig.dialog, this)
  200. const [loadingAPI] = useLoading(config.loading, this)
  201. const [notificationAPI] = useNotification(config.notification, this)
  202. const [toastAPI] = useToast(config.toast, this)
  203. const [toptipsAPI] = useToptips(config.toptips, this)
  204. const memoizedAPI = {
  205. dialog: dialogAPI,
  206. loading: loadingAPI,
  207. notification: notificationAPI,
  208. toast: toastAPI,
  209. toptips: toptipsAPI,
  210. }
  211. if (this.data.memoizedAPI !== memoizedAPI) {
  212. this.setData({
  213. memoizedAPI,
  214. })
  215. }
  216. },
  217. ['export']() {
  218. return {
  219. useApp: () => this.data.memoizedAPI,
  220. }
  221. },
  222. },
  223. attached() {
  224. this.setData({
  225. uuid: ++uuid,
  226. })
  227. this.updateMemoizedAPI(this.data.config)
  228. },
  229. })