# Custom Component Extensions
To better customize the functionality of a custom component, you can use the custom component extension mechanism. Mini Program base library version 2.2.3 Start supporting.
# Effect of Extended
To better understand the effect of the extension, let's take an example:
{% Minicode ('STePQRmH7Q5H') %}
// behavior.js
module.exports = Behavior({
definitionFilter(defFields) {
defFields.data.from = 'behavior'
},
})
// component.js
Component({
data: {
from: 'Component'
},
behaviors: [Require('behavior.js')],
ready() {
console.log(this.data.from) // You'll find the output here. behavior Instead of component
}
})
Through the example, it can be found that the extension of custom components is actually providing the ability to modify the custom component definition segment, the above example is to modify the custom component in the Data
Define what's in the paragraph.
# Using Extensions
Behavior()
The constructor provides a new definition segment definitionFilter
, is used to support custom component extensions. definitionFilter
Is a function that injects two arguments when it is called. The first argument is to use the behavior of component/behavior The second argument is the definition object of the behavior Used by behavior of definitionFilter
List of functions.
Here's an example to illustrate:
// behavior3.js
module.exports = Behavior({
definitionFilter(defFields, definitionFilterArr) {},
})
// behavior2.js
module.exports = Behavior({
behaviors: [Require('behavior3.js')],
definitionFilter(defFields, definitionFilterArr) {
// definitionFilterArr[0](defFields)
},
})
// behavior1.js
module.exports = Behavior({
behaviors: [Require('behavior2.js')],
definitionFilter(defFields, definitionFilterArr) {},
})
// component.js
Component({
behaviors: [Require('behavior1.js')],
})
The above code declares 1 custom component and 3 Behavior, each behavior All used definitionFilter
Definition paragraph. In the order of declarations, the following things will happen:
- When carrying out behavior2 Is called when the declaration of the behavior3 of
definitionFilter
Function, in whichdefFields
The parameters are behavior2 Of the definition paragraph,definitionFilterArr
The argument is an empty array because behavior3 Did not use other behavior 。 - When carrying out behavior1 Is called when the declaration of the behavior2 of
definitionFilter
Function, in whichdefFields
The parameters are behavior1 Of the definition paragraph,definitionFilterArr
Argument is an array of length 1,definitionFilterArr[0]
to be considered to be behavior3 ofdefinitionFilter
Function, because the behavior2 Used the behavior3。The user can decide at his own discretion. behavior1 You want to call the behavior3 ofdefinitionFilter
Function, if you need to call it, add the code heredefinitionFilterArr[0](defFields)
Can be,definitionFilterArr
Parameters are fed in by the base library. - Similarly, in carrying out component Is called when the declaration of the behavior1 of
definitionFilter
Function.
In a nutshell,definitionFilter
Function can be understood as a function when A Used the B When, A The declaration calls the B of definitionFilter
Function and pass in the A The definition object lets B To filter. At this time if B Also used C and D , Then B You can decide for yourself whether to call C and D of definitionFilter
Function to filter A The definition object of the.
Code example:
{% Minicode ('WaqPbxmN7E1j') %}
# Real cases
The following is a simple implementation of the Compute Properties feature for custom components with extensions:
// behavior.js
module.exports = Behavior({
lifetimes: {
created() {
this._originalSetData = this.setData // Original setData
this.setData = this._setData // Encapsulated setData
}
},
definitionFilter(defFields) {
const computed = defFields.computed || {}
const computedKeys = Object.keys(computed)
const computedCache = {}
// Calculation computed
const calcComputed = (scope, InsertToData ) => {
const needUpdate = {}
const Data = defFields.data = defFields.data || {}
for (let key of computedKeys) {
const value = computed[key].call(scope) // Calculate the new value
if (computedCache [key] !== value) needUpdate[key] = computedCache [key] = value
if (InsertToData ) Data[key] = needUpdate[key] // Insert directly into the Data Operations that are only needed at initialization
}
return needUpdate
}
// Rewrite setData method
defFields.methods = defFields.methods || {}
defFields.methods._setData = function (data, callback) {
const originalSetData = this._originalSetData // Original setData
originalSetData.call(this, data, callback) // do Data of setData
const needUpdate = calcComputed(this) // Calculation computed
originalSetData.call(this, needUpdate) // do computed of setData
}
// to initialize computed
calcComputed(defFields, true) // Calculation computed
}
})
Use in components:
const beh = Require('./behavior.js')
Component({
behaviors: [beh],
data: {
a: 0,
},
computed: {
b() {
return this.data.a + 100
},
},
methods: {
onTap() {
this.setData({
a: ++this.data.a,
})
}
}
})
<view>data: {{a}}</view>
<view>computed: {{b}}</view>
<button bindtap="onTap" >click</button>
The implementation principle is simple, for existing setData For secondary encapsulation, in each setData Time to calculate. computed The value of each field, and then set to Data In order to achieve the effect of calculating properties.
This implementation is shown as a simple example and should not be used directly in a production environment.
# Official Expansion Pack
- [computed](https://github.com/WeChat mini-program /computed)