LayaAir destroy 销毁与 removeChild 移除节点

 

目录

destroy  释放内存

编码示例

removeChild 移除节点


destroy  销毁节点

1、JavaScript 运行时无法启动垃圾回收器,要确保一个对象能够被回收,需要删除对该对象的所有引用。Sprite 提供的 destory() 方法会帮助设置对象内部引用为 null。

2、例如,以下代码确可保对象能够被作为垃圾回收:

var sp = new Laya.Sprite();//创建一个Sprite实例
sp.destroy();//将sp内部引用设置为null

3、当对象设置为 null ,并不会立即将其从内存中删除,只有系统认为内存足够低时,垃圾回收器才会运行。内存分配会触发垃圾回收(而不是对象删除)。

4、垃圾回收期间可能占用大量CPU并影响性能。通过重用对象,尝试限制使用垃圾回收。此外,尽可能将引用设置为null,以便垃圾回收器用较少时间来查找对象。有时(比如两个对象相互引用),无法同时设置两个引用为null,垃圾回收器将扫描无法被访问到的对象,并将其清除,这会比引用计数更消耗性能。

5、释放内存是内存优化方式之一,官方文档:https://ldc.layabox.com/doc/?nav=zh-js-3-2-1

destroy(destroyChild:Boolean = true):void

扫描二维码关注公众号,回复: 4886450 查看本文章

[override] 销毁此对象。destroy对象默认会把自己从父节点移除,并且清理自身引用关系,等待js自动垃圾回收机制回收。destroy后不能再使用。 destroy时会移除自身的事情监听,自身的timer监听,移除子对象及从父节点移除自己。

S

编码示例

中间是一个 Label 对象,通过按钮点击来控制创建与销毁,实现代码如下:

//初始化引擎,设置宽高并开启WebGL渲染模式
Laya.init(1080, 1820, Laya.WebGL);

//atlas_comp:打包好的图集资源路径,./ 表示当前路径也就是项目输出路径 bin 目录,"./"" 可写可不写
//skin_button:button按钮的路径。这里注意:因为 button 组件被打包在了图集 comp.atlas 中,所以组件的路径接着图集的路径写
var atlas_comp = "./res/atlas/comp.atlas";//也可以直接是 res/atlas/comp.atlas
var skin_button = "comp/button.png";//comp是图集的名称,button.png是图集中组件的全名
var label_show = null;
//加载资源成功后,执行 onLoaded 回调方法
Laya.loader.load(atlas_comp, Laya.Handler.create(this, onLoaded));

function onLoaded() {
	var btn_1 = createBtn("创建对象");
	var btn_2 = createBtn("销毁对象");
	btn_1.pos(30, 10);//按钮显示的位置
	btn_2.pos(400, 10);//按钮显示的位置

	btn_1.on(Laya.Event.CLICK, this, function () {//为按钮绑定单击事件
		/**当舞台中不含有 label_show 对象时,则创建*/
		if (label_show == null || !Laya.stage.contains(label_show)) {
			createLabel();
			console.log("创建标签");
		}
	});
	btn_2.on(Laya.Event.CLICK, this, function () {//为按钮绑定单击事件
		/**当舞台中已经含有 label_show 对象时,则销毁*/
		if (label_show != null && Laya.stage.contains(label_show)) {
			/**
			 * destroy():销毁此对象。
			 * destroy对象默认会把自己从父节点移除,并且清理自身引用关系,等待js自动垃圾回收机制回收。
			 * destroy后不能再使用。 destroy时会移除自身的事情监听,自身的timer监听,移除子对象及从父节点移除自己
			 */
			label_show.destroy();
			console.log("销毁对象");
		}
	});
	createLabel();
}

function createBtn(text) {
	var btn = new Laya.Button(skin_button);//创建一个 Button 实例
	btn.label = text;//按钮上显示的文本内容
	btn.labelSize = 25;//按钮文本标签的字体大小
	btn.width = 120;//设置按钮的宽度
	btn.height = 50;//设置按钮的高度
	Laya.stage.addChild(btn);//将Button添加到舞台上
	return btn;
}

//显示一个标签
function createLabel() {
	label_show = new Laya.Label("LayaAir");//创建标签对象
	label_show.fontSize = 40;//设置标签字体为20px
	label_show.color = "#fff";//字体颜色白色
	label_show.pos(200, 20);//标签显示位置
	Laya.stage.addChild(label_show);//添加到舞台
}

removeChild 移除节点

1、优化 Sprite 可以通过尽量减少不必要的层次嵌套,减少Sprite数量,以及非可见区域的对象尽量从显示列表移除或者设置visible=false

如上所示当雨箭射击到横杆上的时候就会从舞台中移除此节点,然后回收到对象池 Pool,实现代码如下:

class Arrow {
    constructor() {
        Laya.init(1136, 640, Laya.WebGL);//初始化引擎,不支持 WebGL自动切换为Canvas
        Laya.Stat.show(0, 0);/**显示性能面板 */
        Laya.stage.scaleMode = Laya.Stage.SCALE_SHOWALL;//按照最小比率缩放

        this.count = 0;//成员变量,用于记录每一次创建的雨箭的个数
        this.total = 100;//成员变量,设置每一次雨箭创建的总数
        this.penetrate = 5;//雨箭穿透横杆的深度,后一次都在前一次的基础上加上 penetrate

        this.showBar();//显示一个横杆(矩形表示)
        /**
         * 帧动画,每间隔 1 帧调用一次回调函数
         * 注意:如果直接使用 Laya.timer.frameOnce(10, Laya.stage, this.animation); 则是不对的,此时其中的 this 表示的是 Stage 对象
         * 使用了 ES6 的箭头函数,此时其中的 this 才表示当前类 Arrow
         */
        Laya.timer.frameLoop(1, Laya.stage, () => { this.createArrow() });
    }

    /**顶部随机位置创建雨箭*/
    createArrow() {
        if (this.count < this.total) {
            /**
             * getItemByClass(sign: string, cls: any) 根据传入的对象类型标识字符,获取对象池中此类型标识的一个对象实例.
             *      当对象池中无此类型标识的对象时,则根据传入的类型,创建一个新的对象返回.
             *      sign 对象类型标识字符.cls 用于创建该类型对象的类.@return 此类型标识的一个对象
             * Image 和 Clip 组件是唯一支持异步加载的两个组件,比如 img.skin = "abc/xxx.png",其他 UI 组件均不支持异步加载
             */
            var image_arrow = Laya.Pool.getItemByClass("arrow", Laya.Image);
            image_arrow.skin = "res/arrow.png";//设置 Image 组件皮肤
            var random_x = Math.random() * 1136;//设置 Image 随机的 x 的坐标
            var random_y = Math.random() * 100;//设置 Image 随机的 y 的坐标
            image_arrow.pos(random_x, random_y);//设置组件显示的位置
            Laya.stage.addChild(image_arrow);//将组件添加到舞台

            /**当创建的雨箭数量达到总数的 3分之1时,让雨箭开始移动 */
            if (this.count > (this.total / 3)) {
                this.animation();
            }
            this.count++;//每创建一个雨箭,将记录数加1
        } else {
            //当创建的雨箭数量达到总数时,移动雨箭
            this.animation();
        }
        console.log("当前箭头数:" + this.count + ",箭头总数:" + this.total);
    }

    /**雨箭动画——向下移动 */
    animation() {
        //获取舞台中当前所有的子节点,包含了所有的雨箭以及 下面的横杆
        var stage_numChildren = Laya.stage.numChildren;
        for (var i = 0; i < stage_numChildren; i++) {
            //变量所有舞台中的所有子节点,当是横杆时,则直接进入下一个,否则是雨箭时则移动 y 坐标
            var image_arrow = Laya.stage.getChildAt(i);
            if (image_arrow == null || image_arrow.name == "bar") {
                continue;
            }
            image_arrow.y += 5;//改变y坐标,移动雨箭
            /**当雨箭达到横杆以及穿透进入时,则移除节点(雨箭) */
            if (image_arrow.y > (500 - image_arrow.height + this.penetrate)) {
                Laya.stage.removeChild(image_arrow);//移除子节点
                Laya.Pool.recover("arrow", image_arrow);//回收到对象池
            }
        }
        console.log("stage_numChildren=" + Laya.stage.numChildren + ",penetrate=" + this.penetrate);
        if (Laya.stage.numChildren == 1) {
            //当舞台中只有横杆一个子节点时,说明雨箭以及全部消失,此时将 cout 置0,进入下一波
            this.count = 0;
            this.penetrate += 10;//将穿透横杆的值增加
        }
    }

    /**
     * 显示一个横杆——箭头运动到此时就清除箭头
     */
    showBar() {
        var sprite = new Laya.Sprite();
        sprite.graphics.drawRect(0, 500, Laya.stage.width, 10, "#795815");
        Laya.stage.addChild(sprite);
        sprite.name = "bar";
    }
}

new Arrow();//运行本类

示例图片资源:

猜你喜欢

转载自blog.csdn.net/wangmx1993328/article/details/86156999