1.Vue2源码解析?2?初始化
2.tomcat服务器加载报异常如何解决
3.GetxController生命周期详解
4.blazor组件生命周期
5.Failed to initialize connector [Connector[HTTP/1.1-8084]]
6.Error deploying configuration descriptor anager.xml
Vue2源码解析?2?初始化
活着,最有意义的事情,就是不遗余力地提升自己的认知,拓展自己的认知边界。在搭建源码调试环境一节中,我们已经找到了Vue的抄底公式源码构造函数,接下来开始探索Vue初始化的流程。
一个小测试在精读源码之前,我们可以在一些重要的方法内打印一下日志,熟悉一下这些关键节点的执行顺序。(执行npmrundev后,源码变更后会自动生成新的Vue.js,我们的测试html只需要刷新即可)
在初始化之前,Vue类的构建过程?在此过程中,大部分都是原型方法和属性,意味着实例vm可以直接调用
注意事项:
1、以$为前缀的属性和方法,在调用_init原型方法的那一刻即可使用
2、以_为前缀的原型方法和属性,谨慎使用
3、本章旨在了解Vue为我们提供了哪些工具(用到时,深入研究,不必要在开始时花过多精力,后边遇到时会详细说明)
4、类方法和属性在newVue()前后都可以使用,原型方法和属性只能在newVue()后使用
定义构造函数//src/core/instance/index.jsfunctionVue(options){ //形式上很简单,就是ccic溯源码一个_init方法this._init(options)}挂载原型方法:_init//src/core/instance/init.jsVue.prototype._init=function(options?:Object){ }挂载与state相关的原型属性和原型方法//src/core/instance/state.jsconstdataDef={ }dataDef.get=function(){ returnthis._data}constpropsDef={ }propsDef.get=function(){ returnthis._props}Object.defineProperty(Vue.prototype,'$data',dataDef)Object.defineProperty(Vue.prototype,'$props',propsDef)Vue.prototype.$set=setVue.prototype.$delete=delVue.prototype.$watch=function(expOrFn:string|Function,cb:any,options?:Object):Function{ //略}挂载与事件相关的原型方法//src/core/instance/events.jsconsthookRE=/^hook:/Vue.prototype.$on=function(event:string|Array<string>,fn:Function):Component{ }Vue.prototype.$once=function(event:string,fn:Function):Component{ }Vue.prototype.$off=function(event?:string|Array<string>,fn?:Function):Component{ }Vue.prototype.$emit=function(event:string):Component{ }挂载与生命周期相关的原型方法//src/core/instance/lifecycle.jsVue.prototype._update=function(vnode:VNode,hydrating?:boolean){ }Vue.prototype.$forceUpdate=function(){ }Vue.prototype.$destroy=function(){ }挂载与渲染相关的原型方法//installruntimeconveniencehelpersinstallRenderHelpers(Vue.prototype)Vue.prototype.$nextTick=function(fn:Function){ }Vue.prototype._render=function():VNode{ }挂载Vue类方法和类属性//src/core/global-api/index.js//configconstconfigDef={ }configDef.get=()=>configObject.defineProperty(Vue,'config',configDef)Vue.util={ warn,extend,mergeOptions,defineReactive}Vue.set=setVue.delete=delVue.nextTick=nextTick//2.6explicitobservableAPIVue.observable=<T>(obj:T):T=>{ observe(obj)returnobj}Vue.options=Object.create(null)ASSET_TYPES.forEach(type=>{ Vue.options[type+'s']=Object.create(null)})Vue.options._base=Vueextend(Vue.options.components,builtInComponents)initUse(Vue)//挂载类方法use,用于安装插件(特别特别重要)initMixin(Vue)//挂载类方法mixin,用于全局混入(在Vue3中被新特性取代)initExtend(Vue)//实现Vue.extend函数initAssetRegisters(Vue)//实现Vue.component,Vue.directive,Vue.filter函数挂载平台相关的属性,挂载原型方法$mount//src/platforms/web/runtime/index.js//installplatformspecificutilsVue.config.mustUseProp=mustUsePropVue.config.isReservedTag=isReservedTagVue.config.isReservedAttr=isReservedAttrVue.config.getTagNamespace=getTagNamespaceVue.config.isUnknownElement=isUnknownElement//installplatformruntimedirectives&componentsextend(Vue.options.directives,platformDirectives)extend(Vue.options.components,platformComponents)//installplatformpatchfunctionVue.prototype.__patch__=inBrowser?patch:noopconsole.log('挂载$mount方法')//publicmountmethodVue.prototype.$mount=function(el?:string|Element,hydrating?:boolean):Component{ }拓展$mount方法//src/platforms/web/entry-runtime-with-compiler.jsconstmount=Vue.prototype.$mount//保存之前定义的$mount方法Vue.prototype.$mount=function(el?:string|Element,hydrating?:boolean):Component{ //执行拓展内容returnmount.call(this,el,hydrating)//执行最初定义的$mount方法}Vue的初始化过程(很重要哦!!!)熟悉了初始化过程,就会对不同阶段挂载的实例属性了然于胸,了解Vue是如何处理options中的数据,将初始化流程抽象成一个模型,从此,当你看到用户编写的options选项,都可以在这个模型中演练。
前边我们提到过,Vue的构造函数中只调用了一个_init方法
执行_init方法//src/core/instance/init.jsVue.prototype._init=function(options?:Object){ constvm:Component=this//此刻,Vue的实例已经创建,只是雏形,但Vue的所有原型方法可以调用//aflagtoavoidthisbeingobserved//(observe会在后面的响应式章节详细说明)vm._isVue=true//mergeoptionsif(options&&options._isComponent){ //在后面的Vue组件章节会详细说明//optimizeinternalcomponentinstantiation//sincedynamicoptionsmergingisprettyslow,andnoneofthe//internalcomponentoptionsneedsspecialtreatment.initInternalComponent(vm,options)}else{ vm.$options=mergeOptions(//合并optionsresolveConstructorOptions(vm.constructor),//主要处理包含继承关系的实例()options||{ },vm)}//exposerealselfvm._self=vminitLifecycle(vm)//初始化实例中与生命周期相关的属性initEvents(vm)//处理父组件传递的事件和回调initRender(vm)//初始化与渲染相关的实例属性callHook(vm,'beforeCreate')//调用beforeCreate钩子,即执行beforeCreate中的代码(用户编写)initInjections(vm)//resolveinjectionsbeforedata/props获取注入数据initState(vm)//初始化props、methods、data、computed、watchinitProvide(vm)//resolveprovideafterdata/props提供数据注入callHook(vm,'created')//执行钩子created中的代码(用户编写)if(vm.$options.el){ //DOM容器(通常是指定id的div)vm.$mount(vm.$options.el)//将虚拟DOM转换成真实DOM,然后插入到DOM容器内}}initLifecycle:初始化与生命周期相关的实例属性//src/core/instance/init.jsVue.prototype._init=function(options?:Object){ }0initEvents(vm):处理父组件传递的事件和回调//src/core/instance/init.jsVue.prototype._init=function(options?:Object){ }1initRender(vm):初始化与渲染相关的实例属性//src/core/instance/init.jsVue.prototype._init=function(options?:Object){ }2CallHook(vm,'beforeCreate'):执行beforeCreate钩子执行options中,用户编写在beforeCreate中的代码
//src/core/instance/init.jsVue.prototype._init=function(options?:Object){ }3initInjections(vm):resolveinjectionsbeforedata/props获取注入数据//src/core/instance/init.jsVue.prototype._init=function(options?:Object){ }4initState(vm):初始化props、methods、data、评估源码phpcomputed、watch(划重点啦!!!)//src/core/instance/init.jsVue.prototype._init=function(options?:Object){ }5initProps:初始化props此处概念比较多,propsData、props、vm._props、propsOptions,后续会结合实例来分析其区别,此处只做大概了解。
//src/core/instance/init.jsVue.prototype._init=function(options?:Object){ }6initMethods:初始化methods//src/core/instance/init.jsVue.prototype._init=function(options?:Object){ }7initData:初始化data//src/core/instance/init.jsVue.prototype._init=function(options?:Object){ }8initComputed:初始化computed选项//src/core/instance/init.jsVue.prototype._init=function(options?:Object){ }9initWatch:初始化watchcreateWatcher:本质上执行了vm.$watch(expOrFn,handler,options)
//src/core/instance/state.jsconstdataDef={ }dataDef.get=function(){ returnthis._data}constpropsDef={ }propsDef.get=function(){ returnthis._props}Object.defineProperty(Vue.prototype,'$data',dataDef)Object.defineProperty(Vue.prototype,'$props',propsDef)Vue.prototype.$set=setVue.prototype.$delete=delVue.prototype.$watch=function(expOrFn:string|Function,cb:any,options?:Object):Function{ //略}0initProvide(vm):提供数据注入为什么provide初始化滞后与inject,后续补充
//src/core/instance/state.jsconstdataDef={ }dataDef.get=function(){ returnthis._data}constpropsDef={ }propsDef.get=function(){ returnthis._props}Object.defineProperty(Vue.prototype,'$data',dataDef)Object.defineProperty(Vue.prototype,'$props',propsDef)Vue.prototype.$set=setVue.prototype.$delete=delVue.prototype.$watch=function(expOrFn:string|Function,cb:any,options?:Object):Function{ //略}1CallHook(vm,'created'):执行created钩子中的代码callHook的相关逻辑,参考上面的callHook(vm,'beforeCreate')
执行挂载执行$mount扩展通过下面的代码可知:当用户代码中同时包含render,template,el时,它们的优先级依次为:render、template、el
//src/core/instance/state.jsconstdataDef={ }dataDef.get=function(){ returnthis._data}constpropsDef={ }propsDef.get=function(){ returnthis._props}Object.defineProperty(Vue.prototype,'$data',dataDef)Object.defineProperty(Vue.prototype,'$props',propsDef)Vue.prototype.$set=setVue.prototype.$delete=delVue.prototype.$watch=function(expOrFn:string|Function,cb:any,options?:Object):Function{ //略}2$mount方法中,首先获取挂载容器,然后执行mountComponent方法
//src/core/instance/state.jsconstdataDef={ }dataDef.get=function(){ returnthis._data}constpropsDef={ }propsDef.get=function(){ returnthis._props}Object.defineProperty(Vue.prototype,'$data',dataDef)Object.defineProperty(Vue.prototype,'$props',propsDef)Vue.prototype.$set=setVue.prototype.$delete=delVue.prototype.$watch=function(expOrFn:string|Function,cb:any,options?:Object):Function{ //略}3//src/core/instance/state.jsconstdataDef={ }dataDef.get=function(){ returnthis._data}constpropsDef={ }propsDef.get=function(){ returnthis._props}Object.defineProperty(Vue.prototype,'$data',dataDef)Object.defineProperty(Vue.prototype,'$props',propsDef)Vue.prototype.$set=setVue.prototype.$delete=delVue.prototype.$watch=function(expOrFn:string|Function,cb:any,options?:Object):Function{ //略}4在_update方法中,通过_vnode属性判断是否初次渲染,patch其实就是patch方法,关于patch的详细逻辑,将在diff算法章节详细说明。
//src/core/instance/state.jsconstdataDef={ }dataDef.get=function(){ returnthis._data}constpropsDef={ }propsDef.get=function(){ returnthis._props}Object.defineProperty(Vue.prototype,axi iic源码'$data',dataDef)Object.defineProperty(Vue.prototype,'$props',propsDef)Vue.prototype.$set=setVue.prototype.$delete=delVue.prototype.$watch=function(expOrFn:string|Function,cb:any,options?:Object):Function{ //略}5原文:/post/tomcat服务器加载报异常如何解决
在用Tomcat服务器发布一个由jsp,servlet等技术组成的web项目时,出现下面错误,
严重 [RMI TCP Connection(3)-.0.0.1] org.apache.catalina.core.ContainerBase.addChildInternal ContainerBase.addChild: start:
org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[]]
at org.apache.catalina.util.LifecycleBase.handleSubClassException(LifecycleBase.java:)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:)
at org.apache.catalina.startup.HostConfig.manageApp(HostConfig.java:)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:)
at java.lang.reflect.Method.invoke(Method.java:)
at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:)
at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:)
at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:)
at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:)
at java.lang.reflect.Method.invoke(Method.java:)
at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:)
at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:)
at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:)
at javax.management.remote.rmi.RMIConnectionImpl.access$(RMIConnectionImpl.java:)
at javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:)
at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:)
at javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:)
at java.lang.reflect.Method.invoke(Method.java:)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:)
at sun.rmi.transport.Transport$1.run(Transport.java:)
at sun.rmi.transport.Transport$1.run(Transport.java:)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:)
at java.lang.Thread.run(Thread.java:)
Caused by: java.lang.IllegalArgumentException: Invalid <url-pattern> [active] in servlet mapping
at org.apache.catalina.core.StandardContext.addServletMappingDecoded(StandardContext.java:)
at org.apache.catalina.Context.addServletMappingDecoded(Context.java:)
at org.apache.catalina.startup.ContextConfig.configureContext(ContextConfig.java:)
at org.apache.catalina.startup.ContextConfig.webConfig(ContextConfig.java:)
at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:)
at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:)
at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:)
... more
查看上面错误提示,可以看到这么一句:Caused by: java.lang.IllegalArgumentException: Invalid <url-pattern> [active] in servlet mapping
于是进入 web.xml文件查看配置文件的 <url-pattern>,发现文件是
<servlet-mapping>
<servlet-name>ActiveServlet</servlet-name>
<url-pattern>active</url-pattern>
</servlet-mapping>
在active前面少了一个“/”,加上/后变为
<servlet-mapping>
<servlet-name>ActiveServlet</servlet-name>
<url-pattern>/active</url-pattern>
</servlet-mapping>
重新启动Tomcat服务器,问题解决。
GetxController生命周期详解
在上篇文章中,我们讨论了将网络请求等异步操作置于 GetxController 的 onReady 生命周期函数中处理的最佳实践。本文将深入介绍 GetxController 的生命周期函数。
我们的自定义 Controller 继承结构如下所示:
```plaintext
GetxController
├── update
│ └── ...
└── ...
```
`GetxController` 除了 `update` 方法用于通知组件刷新外,没有其他特殊之处。在 `DisposableInterface` 中,我们覆盖了 `onInit` 方法,实际上多做了一件事:
```plaintext
DisposableInterface
│ └── onInit: VoidCallback => void
└── ...
```
我们将 `onReady` 方法作为回调,在 `onInit` 完成后的下一帧调用。这就是我们上篇文章提到的,`onReady` 会在 `onInit` 完成后的一帧后调用。这里有三个方法:
1. `onInit`
2. `onReady`
3. `onClose`
再往上是 `GetLifeCycle` 类,这个类在构造函数中配置了生命周期,实际上也是调用了 `mixin` 的 `GetLifeCycleBase` 的 `$configureLifeCycle` 方法。实际上,所有生命周期的方法都在这个 `mixin` 中定义。具体的方法如下:
```plaintext
GetLifeCycleBase
│ ├── onCreate: void => void
│ ├── onStart: void => void
│ ├── onReady: void => void
│ ├── onUpdate: void => void
│ └── onDelete: void => void
└── ...
```
实际上,`onStart` 和 `onDelete` 分别绑定了内部的 `_onStart` 和 `_onDelete` 方法,在这两个方法里调用了 `onInit` 和 `onClose` 方法。
也就是unio空投源码说,`onStart` 是在 controller 内存分配的时间点调用的,完成内存分配后就马上调用了:
```plaintext
_onStart: void => void
└── ...
```
有了 GetxController 的生命周期后,我们就可以完全替代 StatefulWidget 了。
基于上述分析,我们得出 GetxController 的生命周期及对应说明如下:
```plaintext
GetxController Lifecycle
│ ├── onInit: VoidCallback => void
│ ├── onReady: VoidCallback => void
│ └── onClose: VoidCallback => void
└── ...
```
通过对 GetxController 的生命周期的理解,我们知道每个生命周期适合做的事情。
blazor组件生命周期
翻译自: Component lifecycles
blazor组件包含一组虚方法,我们可通过重写这些方法来影响应用行为。这些方法会在组件生命周期的不同阶段执行。以下图展示了生命周期钩子方法的执行流程:
SetParametersAsync 方法在每次父组件渲染时执行。
传递给组件的参数被包含在ParameterView结构体中。这是根据传递到组件的状态对服务器进行异步调用的好时机。
原文:Parameters that were passed into the component are contained in a ParameterView. This is a good point at which to make asynchronous calls to a server (for example) based on the state passed into the component.
在重写的SetParametersAsync中调用base.SetParametersAsync(parameters)时,组件的[Parameter]修饰属性会被赋值。
此方法也适合为参数分配默认值,更多细节请参考 Optional route parameters。
OnInitialized / OnInitializedAsync 方法在为组件的[Parameter]属性赋值后执行。与SetParametersAsync类似,但可以使用组件状态。
这些方法仅在组件创建时执行一次。如果父组件稍后更改了组件的参数,则这些方法会被跳过。
注意:当组件是一个@page时,且Blazor应用在新的URL下重新渲染此@page,Blazor会重用此@page。因为它是同一个对象,Blazor不会调用IDisposable.Dispose方法,也不会执行OnInitialized方法。
这句话我就没有理解明白,我做了一个实验,一个@page组件有两个路由,一个是/page-one,另一个是/pageone,那么这两个路由来回跳转的话不单单不会执行OnInitialized,其他的方法也不会执行啊。
OnParametersSet / OnParametersSetAsync 方法在组件的新实例中,在OnInitializedAsync之后立即执行。如果它是一个已存在的组件,因为父组件正在重新呈现,所以OnInitialized*方法会被跳过,而这个方法将在SetParametersAsync之后立即执行。
StateHasChanged 方法会标记组件即将被渲染。
当组件希望通知Blazor发生了可能导致呈现输出不同的更改时,将调用此方法。例如,在一个Clock组件中,我们可以设置一个循环的1秒计时器,然后执行StateHasChanged以重新呈现正确的时间。
另一个用途是指导Blazor通过异步方法部分地执行重渲染。
ShouldRender 方法可以通过返回false来阻止组件的RenderTree被重新计算。注意,在第一次创建和呈现组件时,不会执行此方法。
例如,当我们知道我们的状态自上次渲染以来没有改变,或者只是以一种会导致相同输出被渲染的方式改变时,指示Blazor不要经过BuildRenderTree过程可以节省处理时间并改善用户体验。
这个方法不会在组件第一次被渲染的时候执行
BuildRenderTree 方法将应呈现给用户的内容放入内存中(虚拟DOM,即RenderTree)。
上述代码中,向渲染树添加一个h1,内容为“People”。然后它将为people变量中的每个currentPerson局部变量创建一个ShowPersonDetails的新实例。
如果我们的组件在稍后的时间重新渲染,在people中添加一个额外的项,那么ShowPersonDetails组件的一个新实例将被创建并添加到组件的RenderTree中。如果人的条目减少了,那么之前创建的一些ShowPersonDetails组件实例将从组件的RenderTree中被丢弃,如果它们实现了IDisposable, Dispose()将对它们执行。
注意:为了更有效地执行渲染,当在一个循环的上下文中执行渲染时,任何时候都应该添加一个 @key 指令
OnAfterRender / OnAfterRenderAsync 这最后两个方法在Blazor重新生成组件的RenderTree时执行。这可能是由于组件的父组件重新呈现,用户与组件交互(例如鼠标点击),或者组件执行它的StateHasChanged方法来调用重新呈现的结果。
这些方法只有一个名为firstRender的参数。只有在当前组件上第一次调用该方法时,该参数才为true,此后它将始终为false。在需要附加组件连接(例如,通过JavaScript)的情况下,知道这是第一次呈现是很有用的。
只有在OnAfterRender方法执行之后,才可以安全地使用通过@ref指令设置的对组件的引用。
同样的,直到OnAfterRender方法已经执行firstRender设置为true,才可以安全地使用任何通过@ref指令引用的HTML元素集。
Dispose 尽管这不是严格意义上的ComponentBase生命周期方法之一,但如果一个组件实现了IDisposable,那么一旦该组件从其父渲染树中移除,Blazor就会执行Dispose。为了实现IDisposable,我们需要在razor文件中添加@implements IDisposable。
Awaiting within Async lifecycle methods/在异步的生命周期方法中等待
值得注意的是,Blazor将尽可能快地触发渲染,而不是等待长时间运行的异步方法完成后才能呈现组件。
这使得组件能够在执行后台任务(如从服务器检索数据)时为用户呈现内容。
单个方法的等待行为SetParametersAsync
注意:如果重写了该方法,基类的SetParametersAsync方法必须在方法中的任何await指令之前执行,否则将抛出InvalidOperationException。
OnInitializedAsyncOnParametersSetAsyncOnAfterRenderAsync
(记住上述逻辑的一个)简单的规则是SetParametersAsync是唯一不能通过等待任务挂起生命周期进程的方法(观察SetParametersAsync的源码会发现,这个方法中根本就没有await任何东西,所以。。。)。
所有其他异步方法都可以挂起生命周期进程,直到执行退出该方法,而第一个await将导致通过BuildRenderTree进行渲染,以防止用户不得不等待查看更新。
OnRenderAsync可能看起来有些异常,因为它在两种情况下(第一次await时和退出方法时都没有什么动作)都不执行进一步的操作。如果我们考虑到渲染是执行链的最终目标这一事实,那么我们可以将渲染视作是执行链的最终结果,而不是什么都不做。至于在await上渲染,如果需要,那么程序员必须通过调用StateHasChanged来显式地完成(这个方法中调用StateHasChanged,我实在想不出什么场景能够做这样的操作,关键是容易出现渲染无限循环),否则OnAfterRenderAsync中将导致一个无限循环。
OnAfterRenderAsync这个方法在ComponentBase的源码中它直接了Task.CompletedTask
异步方法和多个await
在async方法中,Blazor执行的代码只会在第一次等待时执行。随后的await不会导致多个渲染。例如
上述例子是原文中的,可能并不好懂,我们来写一个更好懂的:
在上述代码中,如果我没有添加任何StateHasChanged()的话,那么在整个方法结束时页面上会输出_count的值是3,但是中间的变化过程会被忽略掉。
如果我们想要在额外的点上呈现,那么我们必须在所有额外的await语句之前调用StateHasChanged。
有关如何在同一组件上运行不同线程时安全工作的更多信息,请参阅多线程呈现一节。Multi-threaded rendering.
Failed to initialize connector [Connector[HTTP/1.1-]]
åæ , :: ä¸å org.apache.catalina.core.StandardService initInternal
严é: Failed to initialize connector [Connector[HTTP/1.1-]]
org.apache.catalina.LifecycleException: åè®®å¤çç¨åºåå§å失败
at org.apache.catalina.connector.Connector.initInternal(Connector.java:)
at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:)
at org.apache.catalina.core.StandardService.initInternal(StandardService.java:)
at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:)
at org.apache.catalina.core.StandardServer.initInternal(StandardServer.java:)
at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:)
at org.apache.catalina.startup.Catalina.load(Catalina.java:)
at org.apache.catalina.startup.Catalina.load(Catalina.java:)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:)
at java.lang.reflect.Method.invoke(Method.java:)
at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:)
Caused by: java.lang.Exception: Socket bind failed: [] [?Ã(Ð?é//)Ã?]
at org.apache.tomcat.util.net.AprEndpoint.bind(AprEndpoint.java:)
at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:)
at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:)
at org.apache.catalina.connector.Connector.initInternal(Connector.java:)
... more
解å³æ¹æ³ï¼
C:\Users\Administrator>taskkill /f /t /im java.exe
Error deploying configuration descriptor anager.xml
遇到跟你一样的问题 还没有解决。。。。。。。。。。。。。
严重: Error deploying configuration descriptor E:\待用文件\软件\apache-tomcat-7.0.\conf\Catalina\localhost\webdemo.xml
com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException: Invalid byte 2 of 2-byte UTF-8 sequence.
at com.sun.org.apache.xerces.internal.impl.io.UTF8Reader.invalidByte(UTF8Reader.java:)
at com.sun.org.apache.xerces.internal.impl.io.UTF8Reader.read(UTF8Reader.java:)
at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.load(XMLEntityScanner.java:)
at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.arrangeCapacity(XMLEntityScanner.java:)
at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.skipString(XMLEntityScanner.java:)
at com.sun.org.apache.xerces.internal.impl.XMLVersionDetector.determineDocVersion(XMLVersionDetector.java:)
at com.sun.org.apache.xerces.internal.parsers.XMLConfiguration.parse(XMLConfiguration.java:)
at com.sun.org.apache.xerces.internal.parsers.XMLConfiguration.parse(XMLConfiguration.java:)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:)
at org.apache.tomcat.util.digester.Digester.parse(Digester.java:)
at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:)
at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:)
at java.util.concurrent.FutureTask.run(FutureTask.java:)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:)
at java.lang.Thread.run(Thread.java:)
-5- :: org.apache.catalina.startup.ContextConfig processContextConfig
严重: Parse error in context.xml for /webdemo
com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException: Invalid byte 2 of 2-byte UTF-8 sequence.
at com.sun.org.apache.xerces.internal.impl.io.UTF8Reader.invalidByte(UTF8Reader.java:)
at com.sun.org.apache.xerces.internal.impl.io.UTF8Reader.read(UTF8Reader.java:)
at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.load(XMLEntityScanner.java:)
at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.arrangeCapacity(XMLEntityScanner.java:)
at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.skipString(XMLEntityScanner.java:)
at com.sun.org.apache.xerces.internal.impl.XMLVersionDetector.determineDocVersion(XMLVersionDetector.java:)
at com.sun.org.apache.xerces.internal.parsers.XMLConfiguration.parse(XMLConfiguration.java:)
at com.sun.org.apache.xerces.internal.parsers.XMLConfiguration.parse(XMLConfiguration.java:)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:)
at org.apache.tomcat.util.digester.Digester.parse(Digester.java:)
at org.apache.catalina.startup.ContextConfig.processContextConfig(ContextConfig.java:)
at org.apache.catalina.startup.ContextConfig.contextConfig(ContextConfig.java:)
at org.apache.catalina.startup.ContextConfig.init(ContextConfig.java:)
at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:)
at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:)
at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:)
at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:)
at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:)
at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:)
at java.util.concurrent.FutureTask.run(FutureTask.java:)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:)
at java.lang.Thread.run(Thread.java:)
-5- :: org.apache.catalina.core.ContainerBase addChildInternal
严重: ContainerBase.addChild: start: