1 | import { enqueueRender } from './render-queue'
|
2 | import { updateComponent } from './lifecycle'
|
3 | import { isFunction, 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 | $router = {
|
33 | params: {},
|
34 | path: ''
|
35 | }
|
36 |
|
37 | _afterScheduleEffect = false
|
38 | _disableEffect = false
|
39 | hooks = []
|
40 | effects = []
|
41 | layoutEffects = []
|
42 |
|
43 | constructor (props = {}, isPage) {
|
44 | this.state = {}
|
45 | this.props = props
|
46 | this.$componentType = isPage ? 'PAGE' : 'COMPONENT'
|
47 | this.$prefix = genCompPrefix()
|
48 | this.isTaroComponent = this.$componentType && this.$router && this._pendingStates
|
49 | }
|
50 | _constructor (props) {
|
51 | this.props = props || {}
|
52 | }
|
53 | _init (scope) {
|
54 | this.$scope = scope
|
55 | }
|
56 | setState (state, callback) {
|
57 | if (state) {
|
58 | (this._pendingStates = this._pendingStates || []).push(state)
|
59 | }
|
60 | if (isFunction(callback)) {
|
61 | (this._pendingCallbacks = this._pendingCallbacks || []).push(callback)
|
62 | }
|
63 | if (!this._disable) {
|
64 | enqueueRender(this, callback === forceUpdateCallback)
|
65 | }
|
66 | }
|
67 |
|
68 | getState () {
|
69 | const { _pendingStates, state, props } = this
|
70 | const stateClone = Object.assign({}, state)
|
71 | delete stateClone.__data
|
72 | if (!_pendingStates.length) {
|
73 | return stateClone
|
74 | }
|
75 | const queue = _pendingStates.concat()
|
76 | this._pendingStates.length = 0
|
77 | queue.forEach((nextState) => {
|
78 | if (isFunction(nextState)) {
|
79 | nextState = nextState.call(this, stateClone, props)
|
80 | }
|
81 | Object.assign(stateClone, nextState)
|
82 | })
|
83 | return stateClone
|
84 | }
|
85 |
|
86 | forceUpdate (callback) {
|
87 | if (isFunction(callback)) {
|
88 | (this._pendingCallbacks = this._pendingCallbacks || []).push(callback)
|
89 | }
|
90 | this._isForceUpdate = true
|
91 | updateComponent(this)
|
92 | }
|
93 |
|
94 | $preload (key, value) {
|
95 | const preloadData = cacheDataGet(PRELOAD_DATA_KEY) || {}
|
96 | if (typeof key === 'object') {
|
97 | for (const k in key) {
|
98 | preloadData[k] = key[k]
|
99 | }
|
100 | } else {
|
101 | preloadData[key] = value
|
102 | }
|
103 | cacheDataSet(PRELOAD_DATA_KEY, preloadData)
|
104 | }
|
105 |
|
106 |
|
107 | __triggerPropsFn (key, args) {
|
108 | const keyChain = key.split('.')
|
109 | const reduxFnPrefix = '__event_'
|
110 | const reduxFnName = reduxFnPrefix + keyChain.shift()
|
111 |
|
112 | if (reduxFnName in this) {
|
113 | const scope = args.shift()
|
114 | let fn
|
115 | if (keyChain.length > 0) {
|
116 | fn = safeGet(this[reduxFnName], keyChain.join('.'))
|
117 | } else {
|
118 | fn = this[reduxFnName]
|
119 | }
|
120 | fn.apply(scope, args)
|
121 | } else {
|
122 |
|
123 | const keyLower = key.toLocaleLowerCase()
|
124 | const detail = {
|
125 | __isCustomEvt: true,
|
126 | __arguments: args
|
127 | }
|
128 | if (args.length > 0) {
|
129 | detail.value = args.slice(1)
|
130 | }
|
131 | this.$scope.triggerEvent(keyLower, detail)
|
132 | }
|
133 | }
|
134 | }
|
135 |
|
136 | export default BaseComponent
|