荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: Jobs (温少), 信区: Visual
标  题: The Visual InterDev 6.0 Scripting Object Model Event Sequence
发信站: BBS 荔园晨风站 (Mon Nov 29 17:12:49 1999), 站内信件



The Visual InterDev 6.0 Scripting Object Model Event Sequence
Steve Millet
Microsoft Corporation

September 1998

Click to copy the sample file associated with this article.

Summary: Explains the execution and event sequencing of the Microsoft? Visual
InterDev? version 6.0 scripting object model. (9 printed pages) Includes:

Descriptions of the object construction, object initialization, page entry,
dispatch, content rendering, page exit, and destruction phases of the scripting
object model event sequence.


A brief description of the sample .asp files that accompany the article.


A code summary of the execution of the scripting object model.
Contents
Introduction
Execution and Eventing Sequence
Samples
Scripting Object Model Execution Model Summary

Introduction
The scripting object model in Visual InterDev 6.0 provides an event-based
execution model for Active Server Pages (ASP). While a scripting object model朾
ased page is executed serially as any other ASP page, the scripting object
model provides a framework for programming to an event-based model.

At a high level, the execution and event sequence is similar to the DHTML
browser execution sequence. Objects on the page are constructed and
initialized. An onenter event is fired to indicate the page is loaded and all
objects are ready to be scripted (equivalent to the window onload event in
DHTML). Implementing an event handler for the onenter event is ideal for
initializing variables and objects. After the onenter event is fired, execution
is transferred to an entry point or event handler, by default invoking the show
entry point. In many cases, execution will transfer to a server-side handler as
a result of a button click or some other user action that takes place in the
client browser. An onshow event is fired just prior to executing the content
portion of the page. Implementing an event handler for the onshow event is
ideal for setting the state of any objects just prior to rendering their HTML
output. After the content portion of the page is executed, an onexit event is
fired to indicate the page is unloading (equivalent to the window onunload
event in DHTML). Finally, all of the objects on the page will be destroyed and
page execution is complete.

Execution and Eventing Sequence
Object Construction Phase
Execution begins by constructing each Script object on the page. This is
accomplished by executing all Microsoft JScript? functions that conform to the
following naming convention: "xxxx_ctor". The design-time controls (DTCs)
provided in Visual InterDev 6.0 will generate a _ctor function for the run-time
object they represent. The current implementation will execute each _ctor
sequentially, in the order it appears on the page, but this behavior should not
be assumed. An object constructor should be self-contained and should not
expect any other object to have been constructed prior to its constructor.

Construction of the "thisPage" object
The first object constructed will be a scripting object named thisPage. This
object provides properties, methods, and events that comprise the scripting
object model. Other objects will use the thisPage object for state services,
event notification, and other purposes.

Registering an initialization function
The constructor function of each object will register an initialization
function with the thisPage object via an advise method. The initialization
functions will be invoked during the initialization phase, after all object
constructors have been invoked. A pointer to the initialization function is
provided as a parameter to the constructor, and the initialization function
implementation is generated by a DTC based on the properties set at
design-time. A Recordset object will register its initialization function with
a higher priority than other objects. This action ensures that the Recordset
objects will be initialized before any other objects that may depend on the
recordset for databinding.

Registering default event handlers
The constructor function for most objects will register any default event
handler for the object. A default event handler is a method that conforms to
the naming convention "object_event." The Recordset object will defer
registration of its default event handlers until the end of the initialization
phase (with the exception of the onbeforeopen event). This action ensures that
the default Recordset event handlers will not be fired until all other objects
have been both constructed and initialized.

Object Initialization Phase
The initialization functions that were registered in the constructors will be
invoked in this phase of the execution. The functions are invoked in priority
order, with functions of the same priority being invoked in the order
registered.

Recordset initialization
The Recordset initialization functions are registered with a high priority,
such that all Recordset objects will be initialized before any other objects.
The initialization function of the recordset will set up the connection and
command for the recordset based upon settings chosen via the Recordset DTC
property pages at design time. If the recordset is set to "autoopen," or if the
recordset was left open on the previous roundtrip to this same page, the
recordset will automatically be opened in its initialization function. To
prevent a recordset from being opened during this initialization phase, the
"autoopen" flag should be disabled in the DTC property page, and the recordset
should be explicitly closed prior to exiting the page. The thisPage_onexit
handler is an ideal place for closing recordsets prior to exiting the page.

Object initialization
Object initialization functions are registered with a neutral priority and will
be invoked after high-priority initialization functions, such as those for the
recordset. Objects that are set to databind to a recordset will use an advise
method of the appropriate recordset to register a handler on the onrowenter
event and possibly the onbeforeupdate event. The onrowenter handler will be
used to bind data from the recordset into the object. The onbeforeupdate
handler will be used to bind data from the object into the recordset.

If the recordset is already open when an object registers an onrowenter handler,
 that handler will be invoked immediately in order to bind the object to the
current row of the recordset.

Following the registration of databinding handlers, the object will restore any
state that has been roundtripped back to this page. This means that any data
that may have been bound to an open recordset during this initialization phase
will be overwritten with the restored state of the object that was roundtripped
back to the page. This behavior is required to support the data update scenario,
 because it ensures that a subsequent update to the recordset will be bound
with the data that was returned from the browser and restored into the
databound object.

Recordset default event handler registration
The default event handlers for the recordset will not be registered until after
all of the other objects on the page have been initialized (with the exception
of the onbeforeopen event).  This ensures that all other objects, in particular
databound objects, have been both constructed and initialized. The programmer
will be guaranteed that all objects that need to bind to a recordset have done
so before the default event handler is invoked.

Because the registration of the default event handlers has been deferred,
several of the default handlers will be invoked immediately if the recordset
has already been opened. These default handlers are for the onrowenter,
ondatasetchanged, and ondatasetcomplete events. These events are fired when the
recordset is opened, but because registration of the default handlers was
deferred until after all the objects have been initialized, they will be both
registered and invoked at this point.

Page Entry Phase
At this point in the execution, all objects have been constructed and
initialized. In addition, all databound objects have registered handlers with a
recordset, and the Recordset objects may have already been opened and fired the
events associated with opening (onbeforeopen, onrowenter, ondatasetchanged, and
ondatasetcomplete).

Now the page will fire the onenter event. The default event handler,
thisPage_onenter, will be invoked first, followed by any other handlers that
have been registered via an advise with the thisPage object. The onenter event
handler is an ideal location for the programmer to provide initialization code
for manipulating the objects in the page. While the DTC property page can be
used to set up an initial state for each object, it is often useful to
dynamically alter the state of an object based upon programmatic conditions and
for subsequent roundtrips to the page.

The thisPage object exposes a property that is especially useful when
implementing a handler for the onenter event. This is the firstEntered
property. The programmer can use the thisPage.firstEntered property to
determine whether this page was entered from some other page, or entered as a
result of a roundtrip back to itself. This is necessary in determining whether
the objects and the page are in an initial state or in a restored state.

Here is an example of a default onenter event handler using the
thisPage.firstEntered property:

function thisPage_onenter()
{
   if (!thisPage.firstEntered)
   { // initialize Listbox1 with colors
      Listbox1.addItem('red');
      Listbox1.addItem('blue');
      Listbox1.addItem('yellow');
   }

   // otherwise Listbox1 state already restored
   // do not want to add colors again
}

Dispatch Phase
After the onenter event has been fired, the scripting object model will
determine if an entry point has been provided in the QueryString or Request
header. If an entry point has been provided, execution flow will be dispatched
to that method. The details of how the entry point is defined in the
QueryString or Request header is not relevant to the programmer using the
scripting object model and Script objects.

From the scripting object model, an entry point may be defined in one of three
ways:

As an event handler of a Script object
An object will map a client event back to an entry point on the server using a
default event handler naming convention of object_event()

As a navigation method
The Page object can be used to export an entry point on the server as a
navigation method on the client using the naming convention
page.navigate.method()

As a default show method
When an explicit entry point is not provided in the QueryString or Request
header, the programmer may provide a default entry point by implementing a
method on the server named show().

If an entry point is not provided in the QueryString or Request header and the
default show entry point is not implemented, the dispatch phase will do nothing.

Content Rendering Phase
Having dispatched and returned from the designated entry point, the page is now
ready to be rendered. This is where the traditional content portion of the ASP
page will be executed. The programmer may have placed inline script within the
content, but more likely the content will contain Script objects that will
render themselves based upon the state they have been initialized and
programmed to in the prior execution phases.

Just prior to executing the content portion of the ASP, the Page object will
fire the onshow event. The default event handler, thisPage_onshow, will be
invoked first, followed by any other handlers that have been registered via an
advise with the thisPage object. The onshow event provides the programmer one
last hook to program the objects on the page before it is rendered. So, this
event provides a place to execute code after the entry point has been
dispatched to, but before the page has been rendered. After the onshow event is
fired, the content portion of the page is executed, rendering the contents of
the page.

Page Exit Phase
Having completed the rendering phase, the page will fire the onexit event. The
default event handler, thisPage_onexit, will be invoked first, followed by any
other handlers that have been registered via an advise with the thisPage
object. This allows the programmer to modify Page state or the state of any
objects prior to the state persistence and destruction phase. One typical usage
is to close any open Recordset objects in the thisPage_onexit handler so they
will not be automatically opened on a subsequent roundtrip back to the page.
This behavior is often required when doing parameterized queries based on some
user preferences sent back from the client.

Destruction Phase
Finally, the execution ends by destroying each object on the page. This is
accomplished by executing all JScript functions that conform to the following
naming convention: "xxxx_dtor". A DTC may generate a _dtor function for the
run-time object it represents. The current implementation will execute each
_dtor sequentially, in the order it appears on the page, but this behavior
should not be assumed.

The DTC for the Recordset object generates a destructor for bookmarking the
current record (if bookmarking options were chosen at design time) and
persisting the current state of the recordset. This will allow the recordset to
be automatically opened to the current record on a subsequent roundtrip back to
the page.

Samples
Simple (simple.asp)
This is a simple example demonstrating the use of the scripting object model
with several Script objects. It does not include a recordset or databinding. It
demonstrates use of the page onenter and onshow events, as well as handling an
onclick event of a button and an onchange event of a list box.

Parameterized databinding (databind1.asp)
This example demonstrates the use of a recordset and binding controls to that
recordset. In this example, the data in the recordset simply displayed in a
table, where paging and navigation through the recordset are not allowed. It
does allow a filter to be applied to modify the view on the recordset.

This is a good example of when to use the onshow event to open a recordset and
the onexit event to close a recordset.

Parameterized databinding with navigation (databind2.asp)
This example is similar to databind1.asp, but supports paging and navigation
through the recordset being displayed in the table. It still supports the
ability to apply a filter to the recordset. This is a good example of when to
leave a recordset open such that it will maintain and automatically reopen the
current recordset and bookmark upon a subsequent roundtrip to the page.

Master/Detail databinding (masterdetail.asp)
This is a more complicated databinding example, where a detail recordset will
be parameterized based on a field in the current record of a master recordset.
The master recordset supports navigation and paging, while the detail recordset
is simply displayed.

Installation Instructions for the Samples
Note   Samples 2, 3, and 4 require the Northwind database (nwind.mdb). This
database is included with Microsoft Access and with Microsoft Visual Basic?. To
work with these sample .asp pages, nwind.mdb must be available on a server.

Add the four sample .asp files to the root of an existing project or new
project.


Add to the project a data connection named NWIND that references a Northwind
database.


View sample pages in the browser.
Scripting Object Model Execution Model Summary
Construction phase
if (thisPage.hasState())   // restore state for thisPage
   thisPage.restoreState()
Object_ctor()         // construct all objects in sequence

Initialization phase ( oninit event )
Recordset_init()
{   // recordset objects are initialized first
   if (autoOpen || wasOpen())
   {   // recordset object may be opened during initialization
      Recordset.open()
            {   // opening a recordset fires a sequence of events
               fireEvent(onbeforeopen)
               rsADO.open()
               fireEvent(onrowenter)
               fireEvent(ondatasetchanged)
               fireEvent(ondatasetcomplete)
            }
   }
}

Object_init()
{   // remaining objects are initialized in sequence
   if (object is databound)
   {   // databound objects bind to a recordset object
      Recordset.advise(onrowenter)
      if (Recordset.isOpen())
            bind object to current record
   }
   if (hasState())
         restoreState()   // will overwrite bound data
}

Recordset_adviseDefaultHandlers()
{
   Recordset.adviseDefaultHandler(onrowenter)
   {   // if recordset is already open, invoke default handler
      if (Recordset.isOpen())   Recordset_onrowenter()
   }
   Recordset.adviseDefaultHandler(ondatasetchanged)
   {   // if recordset is already open, invoke default handler
      if (Recordset.isOpen())   Recordset_ondatasetchanged()
   }
   Recordset.adviseDefaultHandler(ondatasetcomplete)
   {   // if recordset is already open, invoke default handler
      if (Recordset.isOpen())   Recordset_ondatasetcomplete()
   }
   Recordset.adviseDefaultHandler(onrowexit)
   Recordset.adviseDefaultHandler(onbeforeupdate)
   Recordset.adviseDefaultHandler(onafterupdate)
}

Page entry phase ( onenter event )
fireEvent(onenter)
{
   thisPage_onenter()      // default onenter invoked
   // invoke any other handlers that advised for onenter event
}

Dispatch phase
if (entry point for ObjectEvent)
   fireEvent(object_event)
else if (entry point for navigate method)
   invoke thisPage.navigate.method
else if (typeof(show) == 'function')
   invoke thisPage.navigate.show

Content rendering phase  ( onshow event )
fireEvent(onshow)
{
   thisPage_onshow()      // default onshow invoked
   // invoke any other handlers that advised for onshow event
}
//serially execute content portion of page

Page exit phase ( onexit event )
fireEvent(onexit)
{
   thisPage_onexit()      // default onexit invoked
   // invoke any other handlers that advised for onexit event
}

Destruction phase
Object_dtor()
{   // destruct all objects in sequence
   if (maintainState == true)
         preserveState()   // preserve state of object
}
thisPage.preserveState()   // preserve state of thisPage

Recordset Event Model Summary
Recordset.open()
{   // opening a recordset fires a sequence of events
      fireEvent(onbeforeopen)
      rsADO.open()      // open ADO recordset
      fireEvent(onrowenter)
      fireEvent(ondatasetchange)
      fireEvent(ondatasetcomplete)
}

Notes
The Recordset_onbeforeopen() handler is an ideal place to centralize the
setting of the SQL text just prior to opening the ADO recordset.


The Recordset_DEFAULT handlers will not be registered until AFTER all other
objects have been initialized, with the exception of the Recordset_onbeforeopen
handler.


Databound objects advise to the Recordset onrowenter event to bind the data
from the recordset into the control.


Databound objects advise to the Recordset onbeforeupdate event to bind data
from the control into the recordset.


The default Recordset_onrowenter handler will be invoked AFTER all databound
objects have been bound.


The default Recordset_onbeforeupdate handler will be invoked AFTER all
databound objects have been bound. This is an ideal place to do validation
logic and possibly cancel an update.


? 1999 Microsoft Corporation. All rights reserved. Terms of use.

--
☆ 来源:.BBS 荔园晨风站 bbs.szu.edu.cn.[FROM: bbs@192.168.11.111]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店