ASP.NET AJAX(13)__利用Microsoft AJAX Library开发客户端组件Sys.Component成员Sys.IDisposable成员Sys.INotifyDisposin

Microsoft AJAX Library定义了一个客户端组件的模型,它的基类是Sys.Component,它实现了三个接口Sys.IDisposable,Sys.INotifyDisposing,Sys.INotifyPropertyChange

Sys.Component成员

  • get_events()
  • get_id();
  • set_id();
  • get_isInitialized();
  • initialize();
  • dispose();
  • raisePropertyChanged();

Sys.IDisposable成员

  • dispose();

Sys.INotifyDisposing成员

  • add_disposing();
  • remove_disposing();

Sys.INotifyPropertyChange成员

  • add_propertyChanged();
  • remove_propertyChanged();

可视组件和不可视组件

可视组件,就是对DOM进行了封装,在Microsoft AJAX Library中可分为两种Sys.UI.Control和Sys.UI.Behavior,不可视组件不继承于Control和Behavior,它是一种辅助对象

Control和Behavior

  • Sys.UI.Control:封装了DOM元素,概念上为一个组合的控件
  • Sys.UI.Behavior:扩展了DOM元素,为DOM元素提供了额外的功能

全局容器

  • Sys._Application为一个全局的容器类
  • 维护着全局的所有Component对象的生命周期

客户端生命周期

这里的声明周期,很像我们的c#语言,实际上,它就是按照这种高级语言的声明周期来开发的,如果我们要创建对象,需要在Sys.Application.init事件中创建,并且调用Component的initialize方法,这样在load事件中,就可以在代码中控制它,这以为着,在Sys.Application的load阶段,所有的组件已经必须准备好

一个客户端与组件生命周期的示例

首先创建一个名为SimpleComponent.js的文件

/// <referenct name="MicrosoftAjax.js"/>

Type.registerNamespace("Demo");//注册一个命名空间

Demo.SimpleComponent = function() {
    Demo.SimpleComponent.initializeBase(this);//调用父类的构造函数
}

Demo.SimpleComponent.prototype =//添加成员
{
    initialize: function() {
        Demo.SimpleComponent.callBaseMethod(this, "initialize"); //调用父类名为initialize的方法
        alert("I've been initialized!");
    },
    dispose: function() {
        alert("I'm being disposed!");
        Demo.SimpleComponent.callBaseMethod(this, "dispose");
    },
    sayHi: function() {
        alert("Hello,i'm you first component!");
    }
}

Demo.SimpleComponent.registerClass("Demo.SimpleComponent", Sys.Component);//注册这个类,继承自Sys.Component

然后创建一个aspx页面

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="SimpleLifeCycle.aspx.cs" Inherits="Demo12_SimpleLifeCycle" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:ScriptManager ID="ScriptManager1" runat="server">
            <Scripts>
                <asp:ScriptReference Path="~/Demo12/SimpleComponent.js" />
            </Scripts>
        </asp:ScriptManager>
        
        <script language="javascript" type="text/javascript">
            function pageInit() {
                alert("Page is initializaing!");
                $create(//Microsoft AJAX Library提供的创建对象的简单方法
                    Demo.SimpleComponent,//第一个参数,构造组件的类型
                    { "id": "simpleComponent" },//第二个参数,设置属性,这里只设置一个id
                    { "disposing": onDisposing });//第三个参数,设置事件
            }

            function pageLoad() {//页面加载完成后被调用
                var simple = $find("simpleComponent"); //找到simpleComponent这个组件
                simple.sayHi();//调用组件的sayHi方法
            }
            
            function onDisposing() {//Component释放的时候被调用
                alert("Component is being disposed");
            }

            Sys.Application.add_init(pageInit); //把pageInit方法添加到Sys.Application的init事件中,这样在Sys.Application的init事件中方法被调用
        </script>
    </form>
</body>
</html>

我们打开这个页面,一步一步的观察调用步骤

1.Sys.Application.init事件被触发

2.Component的initialize被调用

3.pageLoad被调用Component的sayHi方法被执行

4.离开页面,组件的dispose方法被调用

5.我们已经在创建对象的时候响应了对象的disposing事件,onDisposing方法被执行

开发一个Component

  • Sys.Component类(非必须)
  • 在构造函数里定义私有变量(将变量设置为默认值)
  • 覆盖initialize方法,初始化所有私有变量
  • 覆盖dispose方法,释放所有私有变量,避免资源泄漏
  • 定义其他成员
一个简单的Component的示例

创建一个名为Timer.js的文件

Type.registerNamespace("Demo");

Demo.Timer = function() {
    Demo.Timer.initializeBase(this);//调用基类构造函数
    this._interval = 1000;//私有变量设置为默认值
    this._timer = null; //私有变量设置为默认值
}

Demo.Timer.prototype =
{
    get_interval: function() {
        return this._interval;
    },
    set_interval: function(value) {
        if (this._interval != value) {//判断现在已有interval的值,是否等于要设置的值
            this._interval = value;
            this.raisePropertyChanged("interval");//告诉外接interval属性被改变
            if (this._timer) {
                this.stop();
                this.start();
            }
        }
    },
    add_tick: function(handler) {
        this.get_events().addHandler("tick", handler);//添加一个事件tick为事件名
    },
    remove_tick: function(handler) {
        this.get_events().removeHandler("tick", handler); //去除一个事件tick为事件名
    },
    _timerCallback: function() {
        var handler = this.get_events().getHandler("tick");//得到我们设置的事件
        if (handler) {//如果这个事件存在
            handler(this, Sys.EventArgs.Empty);
        }
    },
    start: function() {
        if (this._interval > 0) {
            this._timer = window.setInterval(//这里使用的是javascript的原生方法
                Function.createDelegate(this, this._timerCallback), //使_timerCallback的指针指向组件本身,而不是window
                this._interval);
        }
    },
    stop: function() {
        if (this._timer) {//如果_timer已经被赋值,证明已经开始啦
            window.clearInterval(this._timer);
            this._timer = null;
        }
    }
}

Demo.Timer.registerClass("Demo.Timer", Sys.Component);

创建一个aspx页面

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Timer.aspx.cs" Inherits="Demo12_Timer" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:ScriptManager ID="ScriptManager1" runat="server">
            <Scripts>
                <asp:ScriptReference Path="~/Demo12/Timer.js" />
            </Scripts>
        </asp:ScriptManager>
        
        Interval:
        <input type="text" value="1000" id="txtInterval" />
        <input type="button" value="Change" onclick="changeInterval()" /><br />
        
        <div id="display"></div>
        
        <script language="javascript" type="text/javascript">
            Sys.Application.add_init(function() {
            $create(Demo.Timer,//创建这个Component
                { "id": "timer" },//定义一个ID
                { "tick": onTick, "propertyChanged": onPropertyChanged });//创建事件处理程序
            });

            function onPropertyChanged(sender, args) {//propertyChanged被触发的时候,此方法被调用
                var property=args.get_propertyName();//得到改变属性的名称
                var value = sender["get_" + property].apply(sender);//apply指定指针指向组件对象
                alert(property+" is changed to "+value);
            }
            
            window.counter = 0;//一个计数器

            function onTick() {//组件的tick事件被触发时,此方法被调用
                $get("display").innerHTML = window.counter++;
            }

            function pageLoad() {//页面加载完成,timer开始工作
                $find("timer").start();
            }

            function changeInterval() {
                $find("timer").set_interval(
                    parseInt($get("txtInterval").value, 10));
            }
        </script>
    </form>
</body>
</html>

这里就使用到了我们创建的Component,实现一个计数器的效果,类似一个客户端的Timer

Sys.Component成员

  • events只读属性//事件集合
  • id属性//组件的id
  • initialize方法
  • isInitialized只读属性//是否在构造中
  • raisePropertyChanged方法//告诉外界哪个属性改变
  • propertyChanged事件//属性改变后触发
  • dispose方法
  • disposing事件
  • beginUpdate方法//开始Update
  • isUpdating只读属性//是否处于Update状态
  • endUpdate方法
  • updated方法

组件处于正在更新的状态称为Update状态,处于更新状态时候组件的数据可能出于不一致的状态,因此,出于更新状态的组件,允许组件处于不一直的状态,但是应该尽量避免与外接的交换,尤其是处于DOM元素有关的交互,有时候,合理的利用Update状态也能够在一定程序上提高性能

Update状态的使用

  • Sys.Component._setProperties方法:批量修改组件的属性(在非Update状态下)(调用beginUpdate方法->设置组件属性->调用endUpdate方法)

Update状态在系统中的使用

windows的DOM事件load被触发

           Sys.Application对象的beginCreatComponent方法被调用

           SysApplication对象的Init事件被触发

                   $Creat方法被调用,用于创建对象

                        组件的beginUpdate方法被调用

                        部分组件的endUpdate方法被调用

                             如果他们还没有被初始化,而initialize方法被调用

                             他们的Updated方法被调用

          Sys.Application对象的endCreatComponent方法被调用

               剩余组件的endUpdate方法被调用

开发时Update状态的使用方式

  1. 调用beginUpdate方法
  2. 修改属性
  3. 调用endUpdate方法,此外,经常重写Updated方法,提交组件更新信息
一个改进版的Timer示例

创建一个名为BetterTimer.js的文件

/// <reference name="MicrosoftAjax.js"/>
Type.registerNamespace("Demo");

Demo.Timer = function() {
    Demo.Timer.initializeBase(this);
    this._interval = 1000;
    this._enabled = false;
    this._timer = null;
}

Demo.Timer.prototype =
{
    add_tick: function(handler) {
        this.get_events().addHandler("tick", handler);
    },
    remove_tick: function(handler) {
        this.get_events().removeHandler("tick", handler);
    },
    _timerCallback: function() {
        var handler = this.get_events().getHandler("tick");
        if (handler) {
            handler(this, Sys.EventArgs.Empty);
        }
    },
    _startTimer: function() {
        this._timer = window.setInterval(
          Function.createDelegate(this, this._timerCallback),
          this._interval);
    },
    _stopTimer: function() {
        window.clearInterval(this._timer);
        this._timer = null;
    },
    get_interval: function() {
        return this._interval;
    },
    set_interval: function(value) {
        if (this._interval != value) {
            this._interval = value;
            this.raisePropertyChanged("interval");
            if (!this.get_isUpdating() && this._timer != null) {//timer正在执行,而且组件不出于Update状态
                this._stopTimer();
                this._startTimer();
            }
        }
    },
    updated: function() {//重写父类的updated方法
        Demo.Timer.callBaseMethod(this, "updated");//调用父类的updated方法
        this._stopTimer();
        if (this._enabled) {
            this._startTimer();
        }
    },
    get_enabled: function() {
        return this._enabled;
    },
    set_enabled: function(value) {
        if (value != this._enabled) {
            this._enabled = value;
            this.raisePropertyChanged("enabled");

            if (!this.get_isUpdating()) {//不出于更新状态
                if (value) {
                    this._startTimer();
                }
                else {
                    this._stopTimer();
                }
            }
        }
    },
    dispose: function() {
        this.set_enabled(false);
        this._stopTimer();
        Demo.Timer.callBaseMethod(this, "dispose");
    }
}

Demo.Timer.registerClass("Demo.Timer", Sys.Component);

创建一个aspx的页面

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="BetterTimer.aspx.cs" Inherits="Demo12_BetterTimer" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:ScriptManager ID="ScriptManager1" runat="server">
            <Scripts>
                <asp:ScriptReference Path="~/Demo12/BetterTimer.js" />
            </Scripts>
        </asp:ScriptManager>
        
        Interval:<input type="text" value="1000" id="txtInterval" /><br />
        <input type="checkbox" id="chkEnabled" checked="checked" />
        <label for="chkEnabled">Enabled</label><br />
        <input type="button" value="Change" onclick="changeStatus()" />
        <hr />
        <div id="display"></div>
        <script language="javascript" type="text/javascript">
            Sys.Application.add_init(function() {
                $create(Demo.Timer,
                    { "id": "timer", "enabled": true },
                    { "tick": onTick });
                });
            window.counter = 0;
            function onTick() {
                $get("display").innerHTML = window.counter++;
            }

            function changeStatus() {
                var timer = $find("timer");
                timer.beginUpdate();
                timer.set_interval(parseInt($get("txtInterval").value, 10));
                timer.set_enabled($get("chkEnabled").checked);
                timer.endUpdate();
            }
            
        </script>
    </form>
</body>
</html>

Control模型(可视化组件模型)

  • 封装一个DOM元素
  • 提供统一的开发模型
  • 可以用于开发复杂组件
  • 构造函数接受一个element参数,表示这个组件封装的DOM元素

Sys.UI.Control类成员

  • element只读属性//要封装的元素
  • visibilityMode属性//枚举:hide(0)相当于style.visibility,collapse(1)相当于style.display
  • visable属性//bool,可见性
  • addCssClass方法//添加一个class样式
  • removeCssClass方法//去除一个class样式
  • toggleCssClass方法//如果没有一个class样式,而添加,如果有则去除
  • parent属性//
  • onBubbleEvent方法
  • raiseButtleEvent方法
一个使用Control模型的示例

创建一个名为TextBox.js的文件

/// <reference name="MicrosoftAjax.js"/>

Type.registerNamespace("Demo");
Demo.TextBox = function(element) {//注意这里有一个参数,是要封装的DOM元素
    Demo.TextBox.initializeBase(this, [element]);
    this._originalText = null;//保存元素中原先有的值
}

Demo.TextBox.prototype =
{
    initialize: function() {
        Demo.TextBox.callBaseMethod(this, "initialize"); //调用父类方法
        //响应文本框的change事件
        $addHandler(this.get_element(), "change",
            Function.createDelegate(this, this._onTextChange));
    },
    _onTextChange: function(e) {
        if (this.get_isUpdating()) {
            return;
        }
        var handler = this.get_events().getHandler("textChange");
        if (handler) {
            var args = new Sys.CancelEventArgs();
            handler(this, args);

            if (args.get_cancel()) {
                this.beginUpdate(); //这样做,是为了设置文本框的text改变的时候,又会触发一个textChange事件
                this.set_text(this._originalText);
                this.endUpdate();
            }
        }
        this._originalText = this.get_element().value;
    },
    add_textChange: function(handler) {
        this.get_events().addHandler("textChange", handler);
    },
    remove_textChange: function(handler) {
        this.get_events().removeHandler("textChange", handler);
    },

    //一个text属性
    get_text: function() {
        return this.get_element().value; //get_element方法,返回封装的DOM元素
    },
    set_text: function(value) {
        if (value != null) {
            this.get_element().value = value;
        }
        else {
            this.get_element().value = "";
        }
    }
}

Demo.TextBox.registerClass("Demo.TextBox", Sys.UI.Control);

创建一个aspx页面

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="TextBox.aspx.cs" Inherits="Demo12_TextBox" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:ScriptManager ID="ScriptManager1" runat="server">
            <Scripts>
                <asp:ScriptReference Path="~/Demo12/TextBox.js" />
            </Scripts>
        </asp:ScriptManager>
        
        <input type="text" id="textBox" />
        
        <script language="javascript" type="text/javascript">
            Sys.Application.add_init(function() {
            $create(Demo.TextBox,//创建的组件类型
                 null,//这里不设置ID
                { "textChange": onTextChange },//响应事件
                null,
                $get("textBox"));//需要封装的元素
            });

            function onTextChange(sender, args) {
                var message = String.format("The text would be changed to '{0}',are you sure?", sender.get_text());
                if (!confirm(message)) {
                    args.set_cancel(true);//确定“取消操作”
                }
            }
        </script>
    </form>
</body>
</html>

这样,我们实现了文本在改变以后,提示用户是不是确定操作,如果不确定这次操作,则可以撤销这次操作,注意,textChange是在改变文本后,焦点离开文本框以后触发的

我们使用这个组件,对一个普通的textbox进行的封装,这就是一个Control模型的使用示例

$creat方法

  • 原型:$creat(type,properties,events,references,element);
  • referencts是一个字典,保存对象属性与其他对象的关系,key为属性名,value为其他对象id
  • 保证initialize方法调用时,属性已经被设置为所需要的对象,几十调用$creat方法时,其他对象还没有创建

复合控件

复合控件主要会涉及到Control模型中的以下两个方法

  • raiseBubbleEvent(source,args);//由子控件调用,将触发的事件向父控件传递
  • onBubbleEvent(source,args);//父控件重写该方法,用于接受子控件向上传递过来的事件

这两个方法的主要作用是降低父控件和子控件之间的耦合关系,例如子控件不需要知道它的父控件是谁,只需要调用这个方法,把触发的事件向上传递就好啦,至于由谁来接受,这属于另外一个控件的设计啦

一个复合控件的示例

创建一个名为ButtonList.js的文件

/// <reference name="MicrosoftAjax.js"/>

Type.registerNamespace("Demo");

Demo.Button = function(element) {
    Demo.Button.initializeBase(this, [element]);

    this._context = null;//上下文对象,用于保存控件的一些信息
    this._onClickHandler = null;//click事件的监听器
}

Demo.Button.prototype =
{
    initialize: function() {
        Demo.Button.callBaseMethod(this, "initialize");//调用基类方法
        this._onClickHandler = Function.createDelegate(this, this._onClick);
        $addHandler(this.get_element(), "click", this._onClickHandler);
    },
    //释放资源,防止资源泄漏
    dispose: function() {
        this._onClickHandler = null;
        $clearHandlers(this.get_element());
        Demo.Button.callBaseMethod(this, "dispose");
    },
    //元素点击后会调用
    _onClick: function(e) {
        var eventArgs = new Demo.ButtonClickEventArgs(this._context);
        this.raiseClick(eventArgs);
    },
    
    //context属性
    get_context: function() {
        return this._context;
    },
    set_context: function(value) {
        this._context = value;
    },
    //把事件向上传递
    raiseClick: function(args) {
        this.raiseBubbleEvent(this, args);
    }
}

Demo.Button.registerClass("Demo.Button", Sys.UI.Control);//注意,继承自Sys.UI.Control


//自定义的EventArgs
Demo.ButtonClickEventArgs = function(context) {
    Demo.ButtonClickEventArgs.initializeBase(this);
    this._context = context;
}
Demo.ButtonClickEventArgs.prototype =
{
    get_context: function() {
        return this._context;
    }
}

Demo.ButtonClickEventArgs.registerClass("Demo.ButtonClickEventArgs", Sys.EventArgs);//继承自Sys.EventArgs



Demo.ButtonList = function(element) {
    Demo.ButtonList.initializeBase(this, [element]);
    this._itemDataList = null;//存储组件内包含的组件对象
}

Demo.ButtonList.prototype =
{
    initialize: function() {
        Demo.ButtonList.callBaseMethod(this, "initialize");
        for (var i = 0; i < this._itemDataList.length; i++) {
            this._createNewButton(this._itemDataList[i]);
        }
    },
    _createNewButton: function(data) {
        var buttonElement = document.createElement("input");//创建一个Input元素
        buttonElement.type = "button";//元素的type为button(按钮)
        buttonElement.value = data.text;//按钮上的文字
        this.get_element().appendChild(buttonElement);//按钮添加到这个组件上
        
        //把创建的元素,用上面定义的组件进行封装
        $create(Demo.Button,
            { "context": data.context, "parent": this },//指定父控件为自身(ButtonList)
            null, null, buttonElement);
    },
    get_itemDataList: function() {
        return this._itemDataList;
    },
    set_itemDataList: function(value) {
        this._itemDataList = value;
    },
    //当有事件被传递上来的时候调用
    onBubbleEvent: function(source, e) {
        this.raiseItemClick(e);
        return true;//表示事件已经被处理掉了,不需要向上传递
    },
    add_itemClick: function(handler) {
        this.get_events().addHandler("itemClick", handler);
    },
    remove_itemClick: function(handler) {
        this.get_events().removeHandler("itemClick", handler);
    },
    raiseItemClick: function(args) {
        var handler = this.get_events().getHandler("itemClick");
        //如果有这个事件
        if (handler) {
            handler(this, args);
        }
    }
}

Demo.ButtonList.registerClass("Demo.ButtonList", Sys.UI.Control);

然后,创建一个aspx页面

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="ButtonList.aspx.cs" Inherits="Demo12_ButtonList" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:ScriptManager ID="ScriptManager1" runat="server">
            <Scripts>
                <asp:ScriptReference Path="~/Demo12/ButtonList.js" />
            </Scripts>
        </asp:ScriptManager>
        
        <div id="buttonList"></div>
        
        <script language="javascript" type="text/javascript">
            Sys.Application.add_init(
                function() {
                    var datalist =
                    [
                        {
                            text: "Item1",
                            context: "Item 1 has been clicked!"
                        },
                        {
                            text: "Item2",
                            context: "Item 2 has been clicked!"
                        },
                        {
                            text: "Item3",
                            context: "Item 3 has been clicked!"
                        }
                    ];
                    $create(Demo.ButtonList,//组件类型
                        { "itemDataList": datalist },//指定属性
                        { "itemClick": onItemClick },//响应事件
                        null,
                        $get("buttonList"));//要封装的元素
                }
            );

                function onItemClick(sender, args) {
                    alert(args.get_context());//得到args的context属性
                }
        </script>
    </form>
</body>
</html>

运行页面,我们点击按钮就会看到弹出的结果,注意,这里的click事件虽然是子控件(Button)发起的,但是最后处理它的是我们创建的复合控件(ButtonList),这就是我们的raiseBubbleEvent方法和onBubbleEvent方法的功能和它们的使用方法

Behavior模型

  • 另外一种可视化组件模型,继承与Sys.UI.Behavior
  • Control包装DOM元素,Behavior为DOM元素提供功能
  • 一个DOM元素智能由一个Control来包装,但是可以使用多个Behavior进行装饰

Behavior成员

  • 与Component组件相比唯一增加的属性是name
  • 由于一个M元素上可以添加多个Behavior,因此如果要通过元素获得Behavior对象就需要通过name属性获得
  • $get("elementId")["name_of_behavior"]

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏闻道于事

使用easypoi导出excel

1510
来自专栏BaronTalk

RxJava系列六(从微观角度解读RxJava源码)

前言 通过前面五个篇幅的介绍,相信大家对RxJava的基本使用以及操作符应该有了一定的认识。但是知其然还要知其所以然;所以从这一章开始我们聊聊源码,分析RxJ...

3487
来自专栏中国Android研究院

如何优雅的对Webview进行截屏?

通过调用webview.capturePicture(),得到一个picture对象,根据图像的宽和高创建一个Bitmap,再创建一个canvas,绑定bitm...

522
来自专栏前端技术总结

附实例!图解React的生命周期及执行顺序

(1) componentWillMount()  仅在render()方法前被调用一次,如果在该方法中调用了setState方法去改变组件的状态值,那么调用r...

1.2K47
来自专栏Java Edge

React.js实战之React 生命周期1 组件的生命周期

1384
来自专栏我和未来有约会

核心代码(未注释)

//---------------------------------------------------Over var Over = new Object(...

1695
来自专栏Theo Tsao

Angular学习笔记(一)

Angular 应用是模块化的,并且 Angular 有自己的模块系统,它被称为 Angular 模块 或 NgModules。 Angular 模块都是一个带...

972
来自专栏非典型技术宅

ViewController及View的生命周期1. 起因2. Controller的生命周期3. View的生命周期4. 内存警告

1253
来自专栏青蛙要fly的专栏

Android技能树 — Rxjava取消订阅小结(1):自带方式

现在很多项目都在使用Rxjava了,对于RxJava的使用,估计都很熟悉了,但是很多人在使用RxJava的时候容易产生内存泄漏问题,比如我们在用RxJava配合...

693
来自专栏软件开发 -- 分享 互助 成长

外观模式

一、简介 1、外观模式为子系统中的一组接口提供一个统一的高层接口,这一接口使得子系统更加容易使用。 2、举例 :房间里有3盏灯,每一盏灯都有一个开关控制它的开和...

1846

扫描关注云+社区