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