How do I customize Egret components without modifying the engine code?

Understand JavaScript Object.defineProperty in depth

Requirement Description:

Development WeChat little game, is just “get head is nickname the” need to authorize the user interaction, if the user agrees to the game using the head of WeChat return address, if failed to get head don’t agree with, the server to its random one virtual avatar: cdn.xxxxxx.com/project/img… This is a very long and variable address. For flexibility and to reduce server storage space, we want to store only 1 ID in the database, not the entire URL image path, and configure the domain name folder path externally.

Requirement Realization 1:

Normally, we would do this by determining the avatar address separately in the business code:

var img:eui.Image;
var headurl = userinfo.headurl;// The avatar address stored by the user (it may be the complete wechat avatar address, or it may be the ID constructed by the server)
if(!isNaN(headurl)){
   img.source = "http://cdn.xxxxxx.com/project/img/avatar/head/" + headurl + ".jpg";
}
else{
   img.source = headurl;
}
Copy the code

If you need to show the user’s avatar in many places, then repetitive code is spread out in many places, which is not good coding practice. You can encapsulate this code into a method that you can call wherever you need it

fuction setImgSource(img, headurl){
	if(!isNaN(headurl)){
	   img.source = "http://cdn.xxxxxx.com/project/img/avatar/head/" + headurl + ".jpg";
	}
	else{
	   img.source = headurl;
	}
}
setImgSource(img, userinfo.headurl);
Copy the code

It’s easy to add just one line of code to display your avatar address, but admittedly it’s easy to miss.

Here is an alternative to rewriting the Source method of the Egret engine without modifying the engine code file (possible but not recommended), see Requirements Implementation 2 below.

Requirement Realization 2:

How do you rewrite code without modifying the engine code file? DefineProperty is the Object. DefineProperty method.

Object.defineProperty(person,'name', {configurable:false.// Can delete be used, can attributes be changed, or can accessor attributes be modified, false indicates that the accessor attributes cannot be redefined, and the default value is true
    enumerable:false.// Whether object properties can be looped through for-in. Flase is non-looped. The default value is true
    writable:false.Flase is unmodifiable. The default value is true
    value:0 // The default value of the object property is undefined
});
Copy the code

Returning to the requirement in this case, execute the following code at project startup

let rootURL = "http://cdn.xxxxxx.com/project/img/avatar/head/";
        Object.defineProperty(eui.Image.prototype, "source", {
            get: function () {
                return this._source;
            },
            set: function (value) {
                if (value == this._source) {
                    return;
                }
                if(value && !isNaN(value)){ // If it is a digital avatar, the avatar path needs to be constructed
                    value = rootURL + value + ".jpg";
                }
                this._source = value;
                if (this.$stage) {
                    this.parseSource();
                }
                else {
                    this.sourceChanged = true;
                    this.invalidateProperties(); }},enumerable: true.configurable: true
        });
Copy the code

This perfectly solves the need.

Expand your thinking:

Object. DefineProperty defines enumerable, which sets whether an Object property can pass through a for-in loop. Flase is non-loop, and the default value is true

var date = new Date(a);for(var key in date){ 
    console.log(key); } the output isundefined
Copy the code

The JavaScript Date object sets enumerable to false to avoid exposing the object’s methods and properties.

Reference article: blog.csdn.net/qq_17335153…