1 | import { enqueueRender } from './render-queue'
|
2 | import { updateComponent } from './lifecycle'
|
3 | import { genCompPrefix } from './util'
|
4 | import {
|
5 | internal_safe_get as safeGet,
|
6 | internal_force_update as forceUpdateCallback
|
7 | } from '@tarojs/taro'
|
8 | import { cacheDataSet, cacheDataGet } from './data-cache'
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 | const PRELOAD_DATA_KEY = 'preload'
|
16 |
|
17 | class BaseComponent {
|
18 |
|
19 | __computed = {}
|
20 |
|
21 | __props = {}
|
22 | __isReady = false
|
23 |
|
24 | __mounted = false
|
25 | nextProps = {}
|
26 | _dirty = true
|
27 | _disable = true
|
28 | _isForceUpdate = false
|
29 | _pendingStates = []
|
30 | _pendingCallbacks = []
|
31 | $componentType = ''
|
32 | refs = {}
|
33 | $router = {
|
34 | params: {},
|
35 | path: ''
|
36 | }
|
37 |
|
38 |
|
39 | _afterScheduleEffect = false
|
40 | _disableEffect = false
|
41 | hooks = []
|
42 | effects = []
|
43 | layoutEffects = []
|
44 |
|
45 | constructor (props = {}, isPage) {
|
46 | this.state = {}
|
47 | this.props = props
|
48 | this.$componentType = isPage ? 'PAGE' : 'COMPONENT'
|
49 | this.$prefix = genCompPrefix()
|
50 | this.isTaroComponent = this.$componentType && this.$router && this._pendingStates
|
51 | }
|
52 | _constructor (props) {
|
53 | this.props = props || {}
|
54 | }
|
55 | _init (scope) {
|
56 | this.$scope = scope
|
57 | }
|
58 | setState (state, callback) {
|
59 | if (state) {
|
60 | (this._pendingStates = this._pendingStates || []).push(state)
|
61 | }
|
62 | if (typeof callback === 'function') {
|
63 | (this._pendingCallbacks = this._pendingCallbacks || []).push(callback)
|
64 | }
|
65 | if (!this._disable) {
|
66 | enqueueRender(this, callback === forceUpdateCallback)
|
67 | }
|
68 | }
|
69 |
|
70 | getState () {
|
71 | const { _pendingStates, state, props } = this
|
72 | const stateClone = Object.assign({}, state)
|
73 | delete stateClone.__data
|
74 | if (!_pendingStates.length) {
|
75 | return stateClone
|
76 | }
|
77 | const queue = _pendingStates.concat()
|
78 | this._pendingStates.length = 0
|
79 | queue.forEach((nextState) => {
|
80 | if (typeof nextState === 'function') {
|
81 | nextState = nextState.call(this, stateClone, props)
|
82 | }
|
83 | Object.assign(stateClone, nextState)
|
84 | })
|
85 | return stateClone
|
86 | }
|
87 |
|
88 | forceUpdate (callback) {
|
89 | if (typeof callback === 'function') {
|
90 | (this._pendingCallbacks = this._pendingCallbacks || []).push(callback)
|
91 | }
|
92 | this._isForceUpdate = true
|
93 | updateComponent(this)
|
94 | }
|
95 |
|
96 | $preload (key, value) {
|
97 | const preloadData = cacheDataGet(PRELOAD_DATA_KEY) || {}
|
98 | if (typeof key === 'object') {
|
99 | for (const k in key) {
|
100 | preloadData[k] = key[k]
|
101 | }
|
102 | } else {
|
103 | preloadData[key] = value
|
104 | }
|
105 | cacheDataSet(PRELOAD_DATA_KEY, preloadData)
|
106 | }
|
107 |
|
108 |
|
109 | __triggerPropsFn (key, args) {
|
110 | const keyChain = key.split('.')
|
111 | const reduxFnPrefix = '__event_'
|
112 | const reduxFnName = reduxFnPrefix + keyChain.shift()
|
113 |
|
114 | if (reduxFnName in this) {
|
115 | const scope = args.shift()
|
116 | let fn
|
117 | if (keyChain.length > 0) {
|
118 | fn = safeGet(this[reduxFnName], keyChain.join('.'))
|
119 | } else {
|
120 | fn = this[reduxFnName]
|
121 | }
|
122 | fn.apply(scope, args)
|
123 | } else {
|
124 |
|
125 | const keyLower = key.toLocaleLowerCase()
|
126 |
|
127 | const payload = {
|
128 | __isCustomEvt: true,
|
129 | __arguments: args
|
130 | }
|
131 |
|
132 | const detail = this.$scope.dataset
|
133 | if (Object.keys(detail).length) {
|
134 | payload.__detail = detail
|
135 | }
|
136 |
|
137 | this.$scope.triggerEvent(keyLower, payload)
|
138 | }
|
139 | }
|
140 | }
|
141 |
|
142 | export default BaseComponent
|