![[计算机软件及应用]3-1-Ext应用架构.doc_第1页](http://file.renrendoc.com/FileRoot1/2019-2/22/5749e486-c07c-41e8-9ace-b0926214ee6f/5749e486-c07c-41e8-9ace-b0926214ee6f1.gif)
![[计算机软件及应用]3-1-Ext应用架构.doc_第2页](http://file.renrendoc.com/FileRoot1/2019-2/22/5749e486-c07c-41e8-9ace-b0926214ee6f/5749e486-c07c-41e8-9ace-b0926214ee6f2.gif)
![[计算机软件及应用]3-1-Ext应用架构.doc_第3页](http://file.renrendoc.com/FileRoot1/2019-2/22/5749e486-c07c-41e8-9ace-b0926214ee6f/5749e486-c07c-41e8-9ace-b0926214ee6f3.gif)
![[计算机软件及应用]3-1-Ext应用架构.doc_第4页](http://file.renrendoc.com/FileRoot1/2019-2/22/5749e486-c07c-41e8-9ace-b0926214ee6f/5749e486-c07c-41e8-9ace-b0926214ee6f4.gif)
![[计算机软件及应用]3-1-Ext应用架构.doc_第5页](http://file.renrendoc.com/FileRoot1/2019-2/22/5749e486-c07c-41e8-9ace-b0926214ee6f/5749e486-c07c-41e8-9ace-b0926214ee6f5.gif)
已阅读5页,还剩29页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Ext应用架构应用的可扩展性、可维护性和灵活性取决于应用架构的质量,但这并不被重视。概念设计和原型变成了大规模的应用,许多应用的基础基本就是示例代码的复制与粘贴,这很诱人,因为这可以让你在项目在开始阶段有一个快速的进度。然而,节省下来的时间相对于项目后期的维护、扩展甚至重构应用的时间来说,算不得什么。比较好的的方式是写一个可靠的架构,在实施前编写好遵循的约定和定义应用的视图、模型、存储和控制器等。在这篇文章,我们将会看到一个受欢迎的应用并讨论如何构建用户接口,从而创建可靠的架构。代码结构应用程序架构体系会为实际类和框架代码提供结构和一致性。建立一个好的架构有以下主要好处: 每个应用的工作方式是相同的,因而你只需要学习一次。 在应用之间很容易分享代码,因为工作方式是相同的。 你可以使用ExtJS的生成工具为你的应用程序优化。在ExtJS 4创建你的应用时,应该考虑一下我们定义的约定,尤其是统一的目录结构。这个结构要求所有类文件都放到app目录下,在该目录下,可根据命名空间划建立models、views、controllers和stores等4个子目录。虽然ExtJS 4提供了如何构建你的应用的最佳做法,但是你也可以根据自己需要修改我们建议的文件和类的命名约定,例如,你可以为你的控制器在“Controller”前加上前缀,如“Users”修改为“UsersController”。在这种情形下,记得给所有的控制器文件和类加前缀。最重要的一点是,要在开始编写应用程序前定义好这些约定并遵守它。这样,你就可以在任何需要的地方调用这些类。我们强烈建议要遵守控制器、模型、Store、视图这4个文件夹的命名约定,这可以确保你可以使用SDK Tools beta 对应用进行优化。寻找平衡点视图将应用程序的UI分割成视图是好的开始。通常做法是,你提供线框,而设计师创建UI实体模型。尝试一下使用以下模型,让我们的设计师如何使用ExtJS重建潘多拉应用。我们需要在视图粒度与通用性之间寻求一个平衡。让我们看看当划分太多视图的时候会发生什么。将UI划分成太多小的视图将会让视图在控制器中变得难以管理、引用和控制。另外,由于每个视图都有其自己的文件,创建过多的视图会让定义UI块或视图逻辑时很难找到视图文件。另一方面,我们不希望视图变得太通用,因为这样在修改时会失去灵活性。在这种情况下,每个视图已经过于简化。当视图的几个部件需要自定义视图逻辑的时候,视图类最终会有太多的负担,产生的视图类变得很难维护。另外,当设计师考虑改变UI时,我们不得不重构视图定义和视图逻辑,这是相当烦人的事。当我们可以轻松的在页面上重新排列视图,并不需要每次都重构它们的时候,说明已经取得了平衡。例如,我们可以把广告作为独立视图,这样,我就可以很容器移动它,甚至删除它。在这一版本,我们根据视图的任务来划分UI。一旦你对使用视图组合UI有整体思路,那么,你就可以在实现它们时对其粒度作出调整。有时候,你会觉得两个视图应该成为一个,或是视图太通用,需要将其划分成多个视图,这是一个良好的开端的基础。我相信我们已经做到了这一点。模型现在我们已经有了视图的基本结构,是时候考虑模型的问题了。通过考察UI中动态数据的类型,我们可以获得应用中所需的不同模型。我们已经决定只使用两个模型:Song和Station。我们可以定义多两个模型:Artist和Album。然而,与视图类似,我们并不想定义模型时也变得太通用。在当前情况下,我们并不需要将artist和album信息独立出来,因为当前应用不允许用户根据指定的artist选择song。相反,数据是根据station组织的,song是重点,而artist和album是song的属性。这意味着我们不能将song、artist和album结合到一个模型。这可以大大简化应用的数据边界。这也能简化在服务器端的API,因而我们不需要加载artists和albums。因而,对于这个示例,只需要2个模型:Song和Station。存储器现在我们需要考虑如何在应用中使用模型,也就是如何设计存储器的问题。要搞清楚需要使用那些存储器是比较容易的。一个好的策略是先确定页面上所有需要绑定数据的组件。在当前情况下,我们需要列出用户收喜爱stations,一个显示近期播放过的歌曲的scroller,一个搜索区域以显示搜索结果。每一个这样的视图度需要绑定一个存储器。控制器有几种方法可以让你通过应用控制器发布应用的响应。让我们开始考虑当前例子需要那些控制器。SongController和StationController是2个基本控制器。ExtJS 4允许你使用一个控制器同时其控制几个视图。StationController要处理的事情包括创建新的stations,以及当用户喜爱的station加载后,将其应用到StationList视图。SongController负责管理SongInfo视图和根据用户的liking、disliking、暂停和跳过操作更新RecentSong Store。控制器可通过应用事件的触发和监听实现相互之间的交互。当我们可以创建余下的控制器,一个用于管理playback,另外一个用于搜索stations,我想我们已经找到了好的划分响应的方法。三思而后行我们分享我们的想法,重点在于希望有助于你写代码前的应用架构的规划。我们期望通过细节讨论有助于你建立更灵活的更容易维护架构。具体开发定义应用在ExtJS 4,我们推出了类似MVC模式,该模式可以让你在创建应用程序时遵循最佳做法:使用Ext.application方法作为入口。该方法将创建一个Ext.app.Application实例,并在页面准备好以后触发launch方法。它取代了在Ext.onReady内添加诸如创建Viewport和设置命名空间等功能的这种写法。Ext.application( name: Panda, autoCreateViewport: true, launch: function() / This is fired as soon as the page is ready ); 配置项name将创建一个命名空间。所有视图、模型和存储器和控制器都会以该命名空间为命名。设置autoCreateViewport为true,框架将字段加载app/view/Viewport.js文件。在该文件内,将会定义一个名称为Panda.view.Viewport的类,类名必须使用应用中name指定的命名空间。视图在UI中的视图,都是独立的部件,因而需要使用Viewport将它们粘合起来。它会加载要求的视图及它们的定义需要的配置项,以实现应用的整体布局。我们发现,通过定义视图并将它们加载到viewprot,是创建UI基本结构最快的方法。重要的是,这个过程的重点在搭建视图,而不是单个视图本身,就如雕刻一样,先开始创建视图的粗糙形状,然后细化它们。创建构造块利用前文中的工作,我们现在可以开始定义视图了。Ext.define(Panda.view.NewStation, extend: Ext.form.field.ComboBox, alias: widget.newstation, store: SearchResults, . more configuration . );Ext.define(Panda.view.SongControls, extend: Ext.Container, alias: widget.songcontrols, . more configuration . );Ext.define(Panda.view.StationsList, extend: Ext.grid.Panel, alias: widget.stationslist, store: Stations, . more configuration . );Ext.define(Panda.view.RecentlyPlayedScroller, extend: Ext.view.View, alias: widget.recentlyplayedscroller, itemTpl: , store: RecentSongs, . more configuration . ); Ext.define(Panda.view.SongInfo, extend: Ext.panel.Panel, alias: widget.songinfo, tpl: About , . more configuration . ); 我们只是列了一些定义,组件的具体配置将不讨论。在上述配置,可看到使用了三个Store,这些Store的名称都是上一篇文章定义的。现在,我们开始创建Store。模型和存储器通常,在初始阶段,以包含数据的静的json文件作为服务器端是相当有用。以后,这些静态文件可以作为实际的服务器端动态文件的参考。在当前应用,要使用Station和Song两个模型,还需要定义使用这两个模型并绑定到数据组件的存储器。每个存储器都会从服务器端加载数据,模拟的数据文件格式如下:静态数据/data/songs.json success: true, results: name: Blues At Sunrise (Live), artist: Stevie Ray Vaughan, album: Blues At Sunrise, description: Description for Stevie, played_date: 1, station: 1 , . /data/stations.json success: true, results: id: 1, played_date: 4, name: Led Zeppelin, id: 2, played_date: 3, name: The Rolling Stones, id: 3, played_date: 2, name: Daft Punk /data/searchresults.json success: true, results: id: 1, name: Led Zeppelin, id: 2, name: The Rolling Stones, id: 3, name: Daft Punk, id: 4, name: John Mayer, id: 5, name: Pete Philly & Perquisite, id: 6, name: Black Star, id: 7, name: Macy Gray 模型ExtJS 4可以在模型上定义代理、验证和关联。可以看到,在模型中定义了代理,这是一个好的方式,这样,就可以直接在模型加载和保存模型实例,而不需要经过存储器。而且,当有多个存储器使用该模型的时候,也不需要重新为每个存储器定义一次代理。应用中的模型Song代码如下:Ext.define(Panda.model.Song, extend: Ext.data.Model, fields: id,name,artist,album,played_date,station, proxy: type: ajax, url: data/recentsongs.json, reader: type: json,root: results ); 下面继续定义Station 模型:Ext.define(Panda.model.Station, extend: Ext.data.Model, fields: id, name, played_date, proxy: type: ajax, url: data/stations.json, reader: type: json,root: results ); 存储器在ExtJS 4,多个存储器可以使用相同的数据模型,即使存储器需要从不同的来源加载数据。在实例中,模型Station将会在SearchResults和Stations这两个存储器中使用,而它们会从不同的位置加载数据。其中,SearchResults将返回返回搜索结果,而另一个则返回用户收藏的Station。为了实现这一点,其中一个存储器需要重写模型中定义的代理。/app/store/SearchResults.jsExt.define(Panda.store.SearchResults, extend: Ext.data.Store, requires: Panda.model.Station, model: Panda.model.Station, proxy: /Overriding the models default proxy type: ajax, url: data/searchresults.json, reader: type: json,root: results );app/store/Stations.jsExt.define(Panda.store.Stations, extend: Ext.data.Store, requires: Panda.model.Station, model: Panda.model.Station );SearchResults重写了Station模型中代理的定义,当调用存储器的load方法时,其代理将调用存储器的的代理以替换模型中定义的代理。当然,也可以在服务器端使用相同的接口实现返回搜索结果和用户收藏的station,这样,两个存储器就可以使用模型中定义的默认代理了,只是加载数据时请求的参数不同。接着创建RecentSongs:/app/store/RecentSongs.jsExt.define(Panda.store.RecentSongs, extend: Ext.data.Store, model: Panda.model.Song, / Make sure to require your model if you are / not using Ext JS 4.0.5 requires: Panda.model.Song ); 要注意,在当前版本的ExtJS中,在存储器中的model属性还不能自动创建一个依赖,因而需要通过requires配置项指定模型以便能够实现动态加载模型。另外,根据约定,存储器的类名要使用复数,而模型的类名要使用单数。增加存储器和模型到应用定义好模型和存储器后,现在可以把它们加到应用里:/app/Application.jsExt.application( . models: Station, Song, stores:Stations,RecentSongs,SearchResults . ); 使用ExtJS 4 MVC包的另外一个好处是,应用会自动加载在stores和models中定义的存储器和模型。当存储器加载后,会为每个存储器创建一个实例,并将其名称作为storeId。这样,就可以使用该名称将其绑定到视图中数据组件,例如“SearchResults”。应用粘合剂在开始的时候,可以将视图逐一加到Viewport,这样比较容易调试出视图错误的配置。先在Panda应用中构建Viewport,通常,应用的Viewport类扩展自Ext.container.Viewport,这会让应用把浏览器的可用空间作为应用的空间。然后设置viewprot依赖的视图, 这样,就可以使用视图中通过alias属性定义的名称作为xtype配置项的值来定义视图。最后,因为Viewport扩展自Container,而Container没有停靠项,因而必须添加一个面板作为viewport的第一个子组件,并让使用fit布局让面板与viewprot有相同的大小。Ext.define(Panda.view.Viewport, extend: Ext.container.Viewport, requires: Panda.view.NewStation, Panda.view.SongControls, Panda.view.StationsList, Panda.view.RecentlyPlayedScroller, Panda.view.SongInfo , layout: fit, initComponent: function() this.items = xtype: panel, dockedItems: dock: top, xtype: toolbar, height: 80, items: xtype: newstation, width: 150 , xtype: songcontrols, height: 70, flex: 1 , xtype: component, html: PandaInternet Radio , layout: type: hbox, align: stretch , items: width: 250, xtype: panel, layout: type: vbox, align: stretch , items: xtype: stationslist, flex: 1 , html: Ad, height: 250, xtype: panel , xtype: container, flex: 1, layout: type: vbox, align: stretch , items: xtype: recentlyplayedscroller, height: 250 , xtype: songinfo, flex: 1 ; this.callParent(); 在架构方面,需要特别注意的是,不要在实际视图中定义有具体配置的布局,例如,不要定义flex、width或height等配置项,这样,就可以很容易的调整其在应用程序中某个位置的整体布局,从而增加架构的可维护性和灵活性。应用逻辑在ExtJS 4,通过MVC包提供的控制器,可响应视图或其它控制器中的监听事件,并执行对应的应用逻辑。有几个好处:第一个好处是,应用逻辑不用绑定到视图实例。另外,相比ExtJS3,会有许多嵌套视图,而每一个都会添加一层应用逻辑。当将应用逻辑移动到控制器,将它们集中起来,这样就易于维护和修改。最后,控制器基类会提供一些功能,让其易于执行应用逻辑。创建控制器现在,已经有了UI的基本架构、模型和存储器的配置,是时候为应用定义控制器了。我们计划定义两个控制器,Station和Song,定义如下:/app/controller/Station.jsExt.define(Panda.controller.Station, extend: Ext.app.Controller, init: function() . , ); /app/controller/Song.js Ext.define(Panda.controller.Song, extend: Ext.app.Controller, init: function() . , ); 在应用中包含控制器后,框架会在调用init方法的时候字段加载控制器。在init方法内,可以定义监听视图和应用的事件。在大型应用,有时需要在运行时加载额外的控制器,可以使用getController方法加载:someAction: function() var controller = this.getController(AnotherController); / Remember to call the init method manually controller.init(); 当在运行时加载额外的控制器时,一定要记得手动调用加载的控制器的init方法。在实例应用,只要将控制器加到controllers配置项中的数组,让框架加载和初始化控制器就可以了。/app/Application.jsExt.application( . controllers: Station, Song ); 定义监听现在要在控制器的init方法内调用其control方法控制UI部件, 方法control会通过对象的关键字查询组件。在示例中,会通过视图的xtypes配置项查询组件。然而,使用组件查询,必须确保能指向UI中的指定部件。init: function() this.control( stationslist: selectionchange: this.onStationSelect , newstation: select: this.onNewStationSelect );每一个查询都会绑定一个监听配置对象,在每个监听配置对象内,事件名就是监听对象的关键字,而事件是由查询的目标组件提供的。在示例中,将使用Grid(在StationsList视图扩展出的)提供的selectionchange事件,及ComboBox(从NewStation视图中扩展出的)提供的select事件。监听配置对象中的值是事件触发后执行的函数。函数的作用范围将是控制器本身。除了监听RecentlyPlayedScroller视图的selectionchange事件外,这里还需要监听应用事件。这需要使用application实例的on方法。每一个控制都可以使用this.application直接访问application实例。现在为Song控制器添加一些监听:/app/controller/Song.js . init: function() this.control( recentlyplayedscroller: selectionchange: this.onSongSelect ); this.application.on( stationstart: this.onStationStart, scope: this ); . 当在应用中有许多控制器都需要监听同一个事件的时候,应用事件这时候非常有用。与在每一个控制器中监听相同的视图事件一样,只需要在一个控制器中监听视图的事件,就可以触发一个应用范围的事件,这样,等于其它控制器也监听了该事件。这样,就实现了控制器之间进行通信,而无需了解或依赖于对方是否存在。控制器Song需要知道新的station是否已开始,以便更新song滚动条和song信息。现在在Station控制器内,编写当应用事件stationstart触发时的响应代码:/app/controller/Station.js . onStationSelect: function(selModel, selection) this.application.fireEvent(stationstart, selection0); . 这里只是简单在触发stationstart事件时,将selectionchange事件中的第一个选择项作为唯一参数传递给事件。 在该系列文章的前两篇文章中(一、二),我们探讨了如何使用ExtJS 4的新特性构建一个潘多拉风格的应用程序,并开始将MVC架构应用到多视图、Store和模型的复杂UI中,而且了解应用架构的基本技术,如通过控制器控制视图、在控制器中通过监听触发应用事件。在本文,将继续完成应用的MVC架构内的控制逻辑。获取引用在继续完成应用之前,先重温一些MVC包中的高级功能。Ext.application的配置项的stores和models的数组中定义的Store和模型会字段加载,而且加载后,会自动创建Store的实例,并将类名作为storeId的值。/app/Application.js Ext.application( . models: Station, Song, stores: Stations, RecentSongs, SearchResults . ); 在stores和models的数组中定义这些类,除了会自动加载和实例化这些类外,还会为它们创建get方法。控制器和视图也是这样的。配置项stores、models、controllers和views也可以在控制器中使用,其功能与在应用实例中使用是一样的。这意味着,为了在Station控制器内获得Stations的引用,需要在其内加入stores数组:/app/controller/Station.js . stores: Stations, . 现在在控制内的任何位置都可以使用自动生成的getStationsStore方法返回Stations的引用。这个约定是简单而明确的:/ creates getter namedgetStationsListView views: StationsList / creates getter named getStationModelmodels: Station/ creates getter named getSongControllercontrollers: Song / creates getter named getStationsStorestores: Stations 要注意的是,视图和模型返回的是类的引用(要求实例化),而Store和控制器则是实例化后的对象。引用视图实例在上一节,讲述了如何定义stores、models、controllers和views配置项以自动创建get方法以返回它们的引用。方法getStationsListView将返回视图类的引用,而在应用流程中,StationsList将选择第一记录,因而,在viewport中,引用的是视图的实例而不是视图类。在ExtJS 3,通常做法是使用Ext.getCmp方法引用页面中存在的组件实例。在ExtJS 4中,可以继续使用该方法,但不建议这样使用,这是因为使用Ext.getCmp方法需要为每一个组件定义一个唯一ID,才能在应用中引用它。在MVC包中,可以通过在控制器内使用ExtJS 4的新特性ComponentQuery对象获取视图实例的引用:/app/controller/Station.js . refs: / A component query selector: viewport #west-region stationslist, ref: stationsList . 在refs配置项,可以定义视图实例的引用,这样,就可以在控制器中返回和操作页面中的组件。要描述引用组件的,需要使用到ComponentQuery配置对象的selector配置项。另外一个必须的配置项是ref,它将会是refs数组内自动产生的get方法名称的一部分,例如,定义为“ref: stationsList ”(注意大写L),会在控制内生成getStationsList方法。当然,如果你不想在控制器内定义引用,也可以继续使用Ext.getCmp方法,然而,我们希望你不要这样做,因为它需要在项目中管理组件的唯一ID,随着应用的增长一般都会出现问题。一定要记住的是,无论视图是否已经存在页面中,都会独立的创建这些get方法。当调用get方法并通过选择符成功获取页面组件后,它会在缓存这些结果以便后续get方法的调用变得迅速。而当通过选择符找不到页面中任何视图的时候,get方法会返回null,这意味着,存在应用逻辑依赖一个视图,而该视图在页面不存在的情况,这时,必须根据应用逻辑进行排查,以确保get方法能返回结果,并正确执行应用逻辑。另外要注意的是,如果通过选择符会返回多个组件,那么,只会返回第一个组件。因此,让选择符只能返回单一的视图是好的编写方式。最后,当引用的组件被销毁的时候,调用get方法也会返回null,除非在页面中找到另外一个与选择符匹配的组件。在launch方法内级联控制器逻辑当应用开始运行的时候,如果希望加载用户已经存在的station,可以将逻辑放在应用的onReady方法内。而在MVC架构,提供了onLaunch方法,它会在每一个控制内,当所有控制器、模型和Store被初始化后,初始化视图被渲染前触发。这可让你清晰区分那些是全局应用逻辑,那些是控制器逻辑。步骤1/app/controller/Station.js . onLaunch: function() / getStationsStore()为自动生成的方法 var stationsStore = this.getStationsStore(); stationsStore.load( callback: this.onStationsLoad, scope: this ); . Station控制器的onLaunch方法是调用Station的laod方法的一个完美地方。在代码中,Station加载后会执行一个回调函数。步骤2app/controller/Station.js . onStationsLoad: function() var stationsList = this.getStationsList(); stationsList.getSelectionModel().select(0); . 在回调函数中,通过自动产生的StationsList实例的get方法,选择第一个记录,这会触发StationsList内的selectionchange事件。步骤3/app/controller/Station.js init: function() this.control( stationslist: selectionchange: this.onStationSelect , ); , onStationSelect: function(selModel, selection) this.application.fireEvent(stationstart, selection0); , 当在应用中有许多控制器都需要监听同一个事件的时候,应用事件这时候非常有用。与在每一个控制器中监听相同的视图事件一样,只需要在一个控制器中监听视图的事件,就可以触发一个应用范围的事件,这样,等于其它控制器也监听了该事件。这样,就实现了控制器之间进行通信,而无需了解或依赖于对方是否存在。在onStationSelect操作中,将触发应用事件stationstart。步骤4:在Song控制器init方法内,定义了监听应用事件stationstart的方法。当事件触发时,需要加载station的song到RecentSongs。这将会在onStationStart方法内进行处理,通过get方法引用RecentSongs,然后调用其load方法,当加载完成后,需要指向控制器的操作。/app/controller/Song.js . refs: ref: songInfo,selector: songinfo ,ref:recentlyPlayedScroller,selector: recentlyplayedscroller, stores: RecentSongs, init: function() this.applic
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 丙烯酸树脂生产线项目实施方案
- 2025年整形外科美容手术操作技能考核模拟试卷答案及解析
- 2025年皮肤科疑难疾病诊断鉴别考察答案及解析
- 2025年国家公务员考试行测模拟试题及答案解析
- 2025年传染病学病例分析与防治对策考察答案及解析
- 国家电投集团招聘考试试题及答案
- 2025年医保定点申请医药机构医保政策考核试题及答案
- 2025年整形外科手术操作演示答案及解析
- 外国乐器介绍课件
- 飞天姑娘课件
- 电梯大修协议合同
- 电气安全标准化班组
- 湖北省武汉市武昌区2024-2025学年八年级上学期期末考试数学试卷(原卷版+解析版)
- 整本书阅读《格林童话》导读课课件
- 酒店卫生应急预案
- 人教版一年级数学上册教学计划(及进度表)
- 初中道德与法治课外辅导计划
- 幼儿教育中彝族元素的使用
- 心理健康 开学第一课班会课件
- 2025年度在线教育平台股东出资合同
- 慢性鼻窦炎鼻息肉护理查房
评论
0/150
提交评论