原文链接:http://div.io/topic/801

原文在此

对Angular 2.0的策略有疑问吗?就在这里提吧。在接下来的这篇文章里,我会解释Angular 2.0的主要特性区域,以及每个变化背后的动机。每个部分之后,我将提供自己在设计过程中的意见和见解,包括我认为仍然需要改进设计的重要部分。

注意:本文所反映是2014年11月6日的状态记录。如果你在较长时间之后读到此文,请检查一下我设计上是否有所变更。

AngularJS 1.3

在开始讨论Angular的未来之前,我们先花点时间看看当前的版本。AngularJS 1.3是迄今为止最优的Angular版本,它是几周之前发布的。它提供了大量的bug修复,功能增强和性能提升。如果你正在使用Angular,会有升级的愿望。如果将要开始用Angular做新的项目,这也会是你想要使用的版本。这是一个强大而成熟的框架,已经摆在我们面前了。

评注

可能你现在会对AngularJS的未来有很多疑问。什么时候2.0会出来?1.x怎么办?会有从1.x到2.0的升级路径吗?AngularJS团队在回答这些问题上,可以做得更好一些,你应当鼓励他们这么做。我可以告诉你们的是,在Google内部,有1600个应用是基于Angular 1.2或者1.3构建的。所以,看起来Google对当前版本是会有很大兴趣的,也会需要支持它们一段时间。在ngEurope的Q&A环节中,Brad Green说在Angular 2.0的RTM版本发布之后,对Angular 1.3的支持会持续至少1.5-2年。我们也刚针对Angular 1.3的支持作了一些团队结构和领导的变更,即使是正在为Angular 2.0而努力,我们仍然保持了一个专有团队全职处理Angular 1.3。这个团队是由Pete Bacon Darwin领导的,我敢肯定你一定知道他在AngularJS上的丰富经验。我想要鼓励你们向Angular的引领者询问这些变化,并且一起设法完善官方的支持。

当2.0可用时,如果有人想要把Angular1.x的应用迁移到2.0,目前也没有什么可行的计划。我认为我们可以在这一块做些事。如果这对你来说也很重要,请大声说出来,当然要友善一点,但要让Angular团队知道这对你而言很重要,他们应当对此有所考虑,并且也有所规划。

Angular 2.0的动机

那么,你可能会想知道,为什么要做Angular 2.0呢?为什么一步跨到2.0,并且作了这么多不兼容变更?这一切都是很随意的吗?我能够处理少量变更,但我所听到的消息,在2.0中有很多较大的变更,它们真的合理吗?值得吗?

在深入特性细节之前,我很乐意花点时间来探讨一些较高层次的动机,关于2.0所带来的变化。我希望这能够对后续细节建立一个基本的认识,在此基础上可以作一些有意义的批评(其中有些我打算自己提供)。

性能

差不多五年前,当AngularJS刚创建出来的时候,它并不是给开发人员用的。它是一个工具,更倾向于给需要快速创建持久化HTML表单的设计人员用。随着时间推移,它作了改变以适应各种场景,开发人员也用它建造更多、更复杂的应用程序。Angular 1.x团队多年来一直努力增量化地改进设计,允许它适应现代Web应用程序需求的变更。然而,在所能做到的改进上,是有很大局限的,根源在于原始设计中的一些潜规则。很多这种限制,导致了当前的绑定与模板基础架构的性能问题。为了解决这些问题,需要新的策略。

变化的Web

从最初设想Angular所开始的五年中,Web有了明显的改变。比如说,5年前没有jQuery之类框架的帮助,是基本不可能建立一个合适的跨浏览器网站的。但是,当今的浏览器DOM实现不仅更加一致,而且这些实现更快了,也提供了与应用程序框架相关的新特性。

而且web还在继续变化……

虽然在过去几年中,发生了巨大的变化,但与未来1-3年相比,这些变化还是显得微不足道。在几个月内,ES6规范将定稿。如果我们觉得在2015年就能看到完全实现此规范的浏览器,并非不可能。今天的浏览器已经支持其中一些特性了,并且正在实现其他剩余部分。这意味着浏览器支持像module、class、lambda、generator之类东西。这些特性从根本上改变JavaScript的编程体验。但是,大的变化并不是只体现在JavaScript上,Web Components也喷薄欲出。术语Web Components通常是指四个相关的W3C规范:

  • 自定义元素,允许通过自定义标签来扩展HTML
  • HTML Imports,允许对各种资源的打包(HTML,CSS,JS等等)
  • 模板元素,允许在一个文档中包含inert HTML
  • Shadow DOM,允许对DOM和CSS的封装

通过组合这四种能力,web开发人员可以创建声明式的组件(自定义元素),并且是完全封装的(Shadow DOM)。这些组件可以描述它们自己的视图(模板元素),并且能很容易打包发布给其他开发人员(HTML Imports)。当这些规范在所有主流浏览器都可用的时候,我们就可能会看到开发人员的创造力爆发,作很多努力来创建可复用的组件,以解决常见问题,或者是弥补标准的HTML工具集所存在的不足(摘自Web Components与数据绑定)。今天,这已经变得可能,在Chrome和其他浏览器里,这些标准中有些已经实现,有些正在实现。未来显得很美好,对不对?只剩下一个问题了:当今的多数数据绑定框架尚未准备好应对这些。多数框架,包括Angular 1.x,包含一个数据绑定系统,它构建在一小部分已知的HTML元素和常用事件、行为的基础上。为了能让Angular开发人员享有Web Components,很需要有一个全新的数据绑定实现。

移动端

想想5年前……噢,计算的情景已经有了多么大的改变!现在到处都是手机和平板了!虽然Angular可以被用于创建移动应用,但它的理念并非为它们设计的。这包括了所有的东西,从我刚提到过的基本的性能问题,到它的路由的能力缺失,以及不能缓存预编译视图,甚至是过于普通的触摸支持。其中有些东西可以借助Angular 1.3来实现(比如说路由),但其余的需要根本的变更来修复。

易用性

老实说……AngularJS不是太容易学。是的,你选择了它,内心想着“这太美好,很简单,很魔幻!!!”然后开始建立自己的应用,发觉变成“TMD这什么啊!!??我不懂!!!”这种事我听得多了,甚至还有个直观的图用来描述它。如此种种,还是回头看看这个库最初的设计意图吧。比如,最开始是没有自定义指令的,它们都是硬编码的,然后,就有了一个用于添加指令的API。最开始是没有控制器的,然后……你懂的。这种绑死的特性,很多成为了现在的核心理念,导致了API的不优雅。如果Angular真想变的易学易用,那么,从一开始,它就必须对自己的核心特性有清晰的认识。对一个框架而言,如果把指令和控制器当作初始设计的一部分,肯定要比后面逐步拼凑起来要好几个数量级。

小结

了解了Angular的设计起源,以及Web和通用计算情景的逐步变化,很明显需要作一些变更了。事实上,如果不开始解决这些问题,Angular很可能在一年内就有被淘汰的风险。一个框架,如果没法跟Web Components协作,在移动端上一塌糊涂,还继续推进自己的非标准的module和class API,离死也不远了。Angular团队对这些问题的回答是一个新版本:Angular 2.0。它本质上是为了现代Web而对AngularJS的重新想象,并且融合过去五年所得到的各种认识。

评注

尽管我尚未涉及详细的部分,你已经可以发现AngularJS 2.0是与1.x大为不同的了。可能有人会问,这还是不是同一个框架了?我觉得这是个好问题。我之前提到,我认为Angular团队需要提供对1.x支持的具体时间表,到2.0的迁移路径,以及给企业一些指引,供当前决策或者是想要升级为2.0的计划用。对于充满技术思维的Angular团队来说,这可能是很无趣的任务,但我认为它们对社区而言,是有必要的,有帮助的,也是一种尊重。

Angular 2.0的特性与设计

现在,你已经对创建Angular 2.0的动机有了一点相关背景了,我们来看看一些关键的特性区域。

AtScript

AtScript是一门语言,它是ES6的超集,被用来编写Angular 2.0。它使用TypeScript的类型语法来表达可选类型,这可以用来做运行时的类型推断,而不是编译时的检测。它也使用了元数据注解来扩展语言。这里有一个示例,有些AtScript代码就长这样:

import {Component} from 'angular';
import {Server} from './server';@Component({selector: 'foo'})
export class MyComponent {constructor(server:Server) {this.server = server;}
}

在这里,我们在基线ES6代码上添加了一些AtScript附属物。示例顶部的import语句和class语法是直接从ES6里来的,没什么特别的,但是,看一下构造函数,注意server参数指定了一个类型。在AtScript中,这个类型是用于生成运行时类型推断的,引用也会存在于已知的位置,这样,一个框架,比如说依赖注入框架,可以定位到类型信息,并且使用它。也注意一下class定义上面的@Component语法,这是一个元数据注解。组件是一个普通的类,跟其他的一样。当你使用注解来装饰一个东西的时候,编译器会生成代码,初始化注解,并且储存在一个具体的位置,这样它可以被像Angular这样的框架访问到。考虑到这一点,这就是上面的代码转译成ES6语法之后的结果:

import * as rtts from 'rtts';
import {Component} from 'angular';
import {Server} from './server';export class MyComponent {constructor(server) {rtts.types(server, Server);this.server = server;}
}MyComponent.parameters = [{is:Server}];
MyComponent.annotate = [new Component({selector: 'foo'})
];

RTTS的意思是运行时类型系统(RunTime Type System),这是一个小型的关于运行时类型检测的推断库。在此,编译器插入一些代码,以便把server变量推断为类型Server。你也可以编写自定义的类型推断以使用结构化类型,或者使用临时的类型规则。当部署到生产的时候,编译器可以省略这些推断以提高性能。

一个好的事情是,与类型推断相独立,类型注解和元数据注解是能够被跟踪到的。所有这些注解会被翻译成非常简单的ES5兼容数据结构,存储在MyComponent函数自身上。这使得任意框架或者库都能很容易发现这些元数据并且使用它们。多年来,这已经在像.NET和Java这样的平台上被证明是很方便的工具。它也和Ruby的元编程功能有一些相似之处。实际上,当跟一个库组合的时候,注解可以被用于做元编程,Angular 2.0就是借此简化指令的创建的。稍后将进行更详细的讨论。

评注

我个人是喜欢AtScript的,但我已经是一个TypeScript的爱好者了,所以你可能会说我是有前提条件的。我知道有些开发人员抵制在JavaScript中加入类型,我没法责怪他们。我自己已经在类型系统上有过相当广泛的经验了,有些是好的,有些不好。AtScript有个有意思的地方,你可以只把类型语法当成向其他库提供元数据的某种简单方式,而完全不用它来作类型检测。我觉得AtScript最强大的特性之一是,在运行时拥有类型和元数据信息,可供框架利用,或者是在自己的元编程中使用。如果其他的解释型语言也加上这种特性的话,我是不会感到惊讶的。

也就是说,我持有保留意见。

我很乐于看到AtScript变得更正式些,我意思是说,我认为它应当从Angular团队自身中释放出来,它应当有自己的发言权,Angular作为它的一个重要客户。应当至少有几个开发人员全职围绕AtScript工作,实现功能,修复bug,提升代码生成,构建工具等等,同时也应当有一个长期支持计划。当一个开发人员或者团队选择一种语言来编写他们应用的时候,他们所作出的是一种重大投资。我乐于看到Google能够为了未来,在AtScript上作出相当的投资。

关于AtScript,还有另外个问题,是跟Dart相关的。Dart是Google开发的另一种语言。它跟某种简单的解释性语言有所不同,是因为它有自己的运行时和基础类库。结果就是,Dart拥有自己的API,用于DOM处理,集合,事件,正则表达式等等。这些API在它们自己的领域中都很优秀,但跟已有的JavaScript代码不兼容。由于这种阻抗不匹配,Dart和外界的任何通讯都必须通过一个特殊的编组API来完成。所以,虽然从技术上可以调用现有的JavaScript库,一般来说不太实用。对AngularJS来说,性能上的损耗将是不可接受的。所以,Google创建了Angular Dart,一种用Dart重新思考过的AngularJS版本。

问题解决了……好吧,可能没有。

现在,就有了两个Angular的版本,要在里面修改bug,实现新特性,发布,等等,使用不同的语言编写,由不同的团队维护。所以,解决了一个问题,却带来了更多问题。

现在你可能有疑问了:这跟AtScript有什么关系呢?

Angular 2.0的想法是把Angular和Angular Dart统一起来。一个团队在一个代码库上工作,要比两个团队在两个代码库上工作好多了。AtScript能在这个事情上起作用,因为它是在Traceur上面实现的,这个东西可扩展性很好。所以,Angular团队能够用AtScript编译出JavaScript和Dart两个版本。

太棒了!那么,问题在哪里呢?

记得我提到过Dart在DOM之类的东西上有不同的对象模型,这些东西就不是简单转译代码所能解决的了。因此,Angular 2.0的构建过程实际上就会复杂一些了。当开发Angular的时候,必须创建不同的门面(facade)以屏蔽JavaScript和Dart之间的API差异。然后编译器使用对应的门面来编译成每种指定的语言。这个事情在技术上肯定是令人印象深刻了,但是,却大大提高了想要转向Angular 2.0的准入门槛。值得注意的是,这方面的发展还处于试验阶段,这个问题可能会有其他的解决方案。我知道你们中的很多人已经转向了Angular,并且很珍惜这种经验。Angular团队也很珍惜它们,我们正在深度思考如何去改进这些,不过,到目前为止,还不是很理想。

注意:Angular 2.0是使用AtScript编写的,但这并不意味着你就需要用AtScript编写你的应用,或者为了使用Angular 2.0,要学AtScript的什么东西。你可以很轻松地使用TypeScript,ES6,ES5,CoffeeScript……随便什么喜欢的东西来写。目前来说,如果利用AtScript的话,能够获得最佳的Angular体验,因为它能够从语言原语自动生成元数据,不过,最终它还是会翻译成简单的ES5。最终的ES5在概念上某种程度类似于Angular 1.x里面的DDO对象,但在此情况下,它是被生成给任意JavaScript函数使用的,而不是某种指令相关的技术,需要用特殊的注册API来编写。

依赖注入

Angular 1.x的核心特性之一是依赖注入(DI,Dependency Injection)。通过DI,你可以很容易地在软件开发过程中遵循“分而治之”的实践。复杂的问题可以根据其角色和职责进行概念化,然后表示成对象,共同协作以完成最终目标。使用这种方式解构的大型(或者小型)系统可以通过使用DI框架在运行时进行组装。这种系统通常是容易测试的,因为结果的设计更加模块化,也允许了更容易的组件隔离。当然,这一切在Angular 1.x中都是可以的,不过有一些问题。

困扰1.x DI实现的第一个问题是由压缩(minification)引起的。鉴于DI依赖于从函数解析参数名,本质上是把它们当作字符串令牌,而在压缩过程中,这些名称会被改变,就不再匹配于注册的服务、控制器和其他组件了。结果就是应用挂了。为了使得DI对压缩友好,添加了一个API,但它缺乏原始的优雅。在.NET和Java的世界中,先进的服务端DI框架里存在更多特性,1.x的实现主要就缺乏这些东西。欠缺的特性导致开发人员受到约束,两个大的例子是:生命周期/作用域的控制,以及子注射器。

注解

通过AtScript,我们引入了一种广义的将元数据附加到任意函数的机制。同时,AtScript元数据格式是不怕压缩的,也容易使用ES5手工编写。这使得它能够出色地支撑一个DI库,提供其所需要用于构造对象实例的信息。不必见怪,这就是新DI的运作方式。

当DI需要实例化一个类(或者调用一个函数)的时候,会检测一下,看看它上面有没有带附属的元数据。回顾一下上面从AtScript转译出来的代码:

MyComponent.parameters = [{is:Server}];

如果新DI发现了parameters值,会用它来判断将要尝试调用的函数的依赖项。在本例中,它可以得知仅有一个类型为Server的参数。所以它会获取一个Server的实例,并且在调用这个函数之前传进去。你也可以显式提供一个特定的Inject注解给DI用,这会覆盖parameter数据。如果你在使用一种不能自动生成parameter元数据的语言,也很容易支持,下面就是用原生ES5代码写的样子:

MyComponent.annotate = [new Inject(Server)];

这个的运行时效果跟parameter数据是一样的。值得注意的是,你可以使用任意东西当作注入令牌,所以可以这样:

MyComponent.annotate = [new Inject('my-string-token')];

只要你在DI上配置过能映射到'my-string-token'的东西,它就能运行。也就是说,推荐的使用方式是通过构造函数的实例,正如我之前所有的例子所示。

实例作用域

在Angular 1.x中,DI容器中的所有实例都是单例。在Angular 2.0中,默认也是这样。为了获得不同的行为,你需要使用Service,Provider,Constant等等。那都挺容易让人迷惑的。幸运的是,新DI拥有一个新的,更通用,更强大的特性。它现在有实例作用域控制了。所以,如果你希望每次请求的时候,DI都创建一个类的新实例,可以这么做:

@TransientScope
export class MyClass { ... }

当你组合子注射器来创建自己的作用域标识符的时候,这会更加强大……

子注射器

子注射器是一个主要的新特性。子注射器从其父项那里继承到所有父项的服务,但能够在子级别上覆盖它们。当它与作用域标识符组合使用的时候,你可以很轻松地在系统中调用到特定类型的对象,这些对象应当在不同作用域中被覆盖,这非常强大。新的路由有一个“子路由”的功能,就是使用它的一个例子。在内部,每个子路由创建自己的子注射器,这使得路由的每个部分能够从父路由继承服务,或者在不同的导航场景中覆盖这些服务。

注意:自定义作用域和子注射器会被认为是对注射器的中高级用法。我不希望太多的应用代码用到它。但是,既然它在Angular的内部被使用到了,如果你需要类似功能,也可以用。

更多……

在新DI中,还有一些其他特性,比如provider(自定义函数,用于提供一个注入值),懒注入(指定你所期望注入的东西,但又不立即需要,稍后才要),还有基于promise的异步注入(注入一个promise,可以从中获取异步的依赖项)。

评注

从个人角度,我非常喜欢新DI。我又有偏见了,因为我用DI好多年了,在我创建的其他UI框架中,它也是核心组件。新DI在Angular 2.0中扮演了很重要的角色,像子注射器等功能带来了巨大的变更。现在这个功能有了,它能够被模板引擎和路由利用,这两者都有创建作用域和隔离不同服务的需求。

然后我们就来到了一个从Angular中移除的重要特性:$scope。不过,虽然$scope自身被移除了,它的有些特性还在。这些特性被作为此设计的一个部分,重新换了个位置,也有所提升。你可能会被$scope的缺失搞得措手不及,但新的设计既简化了Angular内部的东西,也简化了提供给你,开发人员的东西。我提到这些,是因为DI的有些新功能,比如说子注射器,与$scope中之前的一些功能重叠了。在这个情况下,我认为新DI系统拿出来的是一个更好的解决方案。它更加通用,所以不但能解决Angular的内部需求,还给你们开放了很多种可能性。

不幸的是,玫瑰带着刺。我们来讨论下一些其他问题。在Angular 1.x中,还有个相关功能我没有提到:module,你可能想知道它的位置在哪。Angular 2.0的方案是吸收ES6中关于module的标准。在Angular的之前版本中,处理模块的方式是Angular特有的方式。五年前,当Angular刚开始构思时,并没有用于完成此事的标准方式。今天,事情不同了,已经有了一个明确路径。这当然是一种不兼容升级,如果有人要作迁移的话,需要对代码重新作点调整。要作这么一种不兼容变更,是很恶心,但这就是Web的变化影响框架的一个实例,如果这事现在不解决,2.0将面临被边缘化的风险。

关于DI,还有另外一个坑,特别是如果你在用ES5写代码的话。Angular 2.0依托作为元数据的注解,支持了基于类的设计。类和注解的语法在ES5中并不太好,事实上,ES5压根就没这些语法。你可以使用原型之类来表示一切,但就没有AtScript甚至ES6或者TypeScript那么清晰了,它们可是有类和静态的类成员的。我想知道能不能为不准备迁移到ES6的开发人员做点什么,也许是一个简单的可选降级库,给出一种简单的方式来创建带元数据的类?可能会类似于Angular 1.x中的DDO对象,但是更通用,这样能创建任意的类和元数据。我很想听听你对这个想法的意见,或者其他可能会解决ES5开发问题或对迁移能有所提升的主意。

模板与数据绑定

如果你已经看了这么多,一定属于对Angular 2.0非常好奇的,感谢花了这么多时间。我们还有一条路要走,现在我们要进入真正有意思的地方了:模板和绑定。我打算把它们放在一起讨论,虽然从技术上看,数据绑定系统是与模板系统分离的,你在编写应用的时候却会感觉它们是一个整体。所以,我觉得把它们拿到一起来说会比较好。

我们先从理解视图到屏幕的显示过程,然后一点一点地看。本质上,你是从一段HTML片段开始的,这会存在于一个<template>元素中。这个HTML片段被传递给模板编译器,编译器遍历模板,辨识任意的指令,绑定表达式,事件处理函数等等。所有这些数据从DOM自身中提取,放到最终用于初始化模板的数据结构里。作为这个阶段的一部分,在数据上作了一些处理工作,比如说解析绑定表达式。每个包含上面这种特殊指令节点会被打上一个特殊的class。这一过程的结果会被缓存,这样才不至于需要重复这些工作。我们把这种结果称为一个ProtoView。一旦我们有了ProtoView,就可以用它来创建View。当一个ProtoView生成了View,所有刚才辨识出的指令就会初始化,并且附加到它们的DOM节点上,绑定表达式上建立了监控,事件处理器也配置好了。明白了吧。在编译阶段,之前处理过的数据结构能够让我们很快地做这些事。一旦你得到一个View了,就可以把它添加到一个ViewPort中,并且显示出来。一个ViewPort表达了屏幕的一个区域,可以在其中显示View。作为一名开发人员,大部分东西你是看不到的,你写模板就好了,它会运行的。可我还是希望在深入细节之前,在一个较高层次上把这些过程罗列出来。

动态加载

Angular 1.x所缺乏的重大功能之一是代码的动态加载。如果你想在运行中添加新的指令或者控制器,非常困难,或者就做不到。它没有被支持。在2.0中,我们从开始设计东西的时候,就把异步放在心里。所以,当你开始编译一个模板的时候,实际上它是个异步过程。

现在我需要详细讨论上面一笔带过的模板编译了。当你编译一个模板的时候,你并不仅仅为编译器提供了一个模板,也同时提供了一个Component的定义。我们稍微深入一点。在模板中使用的时候,Component的定义就包含了什么指令啊,过滤器啊之类的元数据。这确保了在模板被编译器处理之前,所有必要的依赖项都已加载。由于我们的代码架设在ES6 module规范的基础上,只需简单地在Component定义中引用依赖项,如果他们尚未加载,module加载器就会加载它们。因此,通过这种结合ES6 module的方式,我们不费事就得到了各种东西的动态加载。

指令

在我们深入模板的语法之前,需要先看一看指令——Angular用于扩展HTML自身的方式。在Angular 1.x中,使用指令定义对象(DDO,Directive Definition Object)来创建指令。这好像是很多Angular开发人员巨大痛苦的来源之一。

如果我们能把指令弄简单点,会怎样呢?

我们已经讨论过模块、类和注解了,如果我们能用这些核心建筑来构建指令会怎样呢?好吧,我们当然就是这么干的。

在Angular 2.0中,有三种指令类型。

  • 组件指令(Component Directive)创建一个组合了View和Controller的自定义组件,你可以把它当成一个自定义HTML元素。路由也可以映射到组件。
  • 装饰指令(Decorator Directive)使用附加行为来装饰一个已有的HTML元素,一个经典的例子是ng-show。
  • 模板指令(Template Directive)把HTML转换成一个可复用的模板。指令的作者可以控制模板何时、怎样初始化,并且插入DOM中。示例包括ng-if和ng-repeat。

你可能听说过在Angular 2.0里面,Controller没了。好吧,不完全正确。其实,Controller成为了我们称之为Component的一部分。Component拥有一个View和一个Controller。View就是你的HTML模板,Controller就是你的JavaScript行为。不像在1.x中那样,要用显式的或者非标准的API来注册控制器,在2.0中,只需创建一个普通的带一些注解的类。这里是选项卡容器组件的控制器的一个部分(稍后会看到它的视图):

@ComponentDirective({selector:'tab-container',directives:[NgRepeat]
})
export class TabContainer {constructor(panes:Query<Pane>) {this.panes = panes;}select(selectedPane:Pane) { ... }
}

这里有几个特性值得注意。

首先,组件的控制器只是一个类。它的构造函数会被自动注入其依赖项。因为使用了子注射器,它可以获得沿DOM树向上所有服务的访问,还包括从属于自己元素的本地服务。比如说,这里它就被注入了一个Query,这是一个特殊的集合,会自动跟子Pane元素保持同步,让你获知何时出现新增或者移除。同时,你也被注入了Element自身,这能让你处理与Angular 1.x中$link回调相同的逻辑,但却是通过类构造函数,用一种更一致的方式来处理的。

现在,看一看@ComponentDirective注解吧。它把类标识为一个Component,并且提供了编译器所需用于挂接的元数据。比如说,selector:'tab-container'是一个CSS选择器,会被用于匹配HTML。任何匹配这个选择器的元素都会被转换成一个TabContainer。同时,directives:[NgRepeat]表明了这个组件的模板的依赖项。到现在还没给你们看过,马上讲语法的时候就会看到了。

一个重要的需要注意的细节是,模板将会直接绑定到这个类上,意味着类的任何属性和方法都能直接在模板上访问。这根Angular 1.2中的“controller as”语法很相似。在类和模板之间,不再有$scope了。结果就是Angular内部得到了简化,开发人员也得到了更简单的语法,那种在$scope对象上搞来搞去的事情变少了。

接下来,我们来看看Decorator Directive。一个简单的NgShow是怎样的呢?

@DecoratorDirective({selector:'[ng-show]',bind: { 'ngShow': 'ngShow' },observe: {'ngShow': 'ngShowChanged'}
})
export class NgShow {constructor(element:Element) {this.element = element;}ngShowChanged(newValue){if(newValue){this.element.style.display = 'block';}else{this.element.style.display = 'none';}}
}

这里,我们可以看到指令的更多方面。我们又写了个带注解的类,构造函数注入了装饰器要附加到的HTML元素。因为有DecoratorDirective,编译器知道这是一个装饰器,也知道把它添加到任意匹配于selector:'[ng-show]' CSS选择器的元素上。

在这个注解上,还有其他一些奇怪的属性。

bind: { 'ngShow': 'ngShow' }用于把类属性映射到HTML attribute。不是所有的类属性都直接暴露成HTML的attribute的,如果你想要让属性在HTML中可绑定,需要在bind元数据中指定它。observe: {'ngShow': 'ngShowChanged'}告诉绑定系统,你想要在每次ngShow属性变更的时候得到通知,并且使用ngShowChanged方法作为回调。注意ngShowChanged回调响应变更的方式是,改变附加到的HTML元素的display。(注意,这只是个非常幼稚的实现,仅作演示之用)。

好了,那Template Directive长什么样呢?为什么不看看NgIf呢?

@TemplateDirective({selector: '[ng-if]',bind: {'ngIf': 'ngIf'},observe: {'ngIf': 'ngIfChanged'}
})
export class NgIf {constructor(viewFactory:BoundViewFactory, viewPort:ViewPort) {this.viewFactory = viewFactory;this.viewPort = viewPort;this.view = null;}ngIfChanged(value) {if (!value && this.view) {this.view.remove();this.view = null;}if (value) {this.view = this.viewFactory.createView();this.view.appendTo(this.viewPort);}}
}

希望你能理解TemplateDirective注解。它注册了这个指令,并且提供了一些必要的元数据用于设置属性和观测,就像NgShow示例那样。这就是一个TemplateDirective,它能够访问一些特殊的服务,这些服务可以被注入它的构造函数。第一个是ViewFactory,之前我提到,Template Directive把它附加到的HTML转换为模板,模板被自动编译,然后你就能在模板指令中访问视图工厂了。调用工厂的createView API会初始化模板自身。你也可以访问ViewPort,这代表了模板从DOM中提取的位置,你可以用它在DOM上添加或者移除模板的实例。注意ngIfChanged回调是怎样响应变更,初始化模板,添加到viewport,或者从viewport上移除的。如果你在实现类似于NgRepeat的东西,可以把模板实例化很多次,甚至给createView API提供一个指定的数据项,然后可以把多个实例添加到viewport上。基本就是这样。

现在,你已经看到三种类型指令的一些典型例子了。我希望这能够大致说明了如何使用新的行为来扩展HTML编译器。

不过,还有一个重要的东西我尚未充分解释:Controllers。

怎样为应用创建一个控制器呢?设想你要建立一个路由,导航到一个控制器,然后显示它的视图。怎么做到这个呢?简单的回答就是使用一个Component Directive来做。

在Angular 1.x中,Directive和Controller是两种不同的东西,API不同,功能也不同。在Angular 2.0中,既然我们已经去掉了DDO,把Directive变成了基于类的,我们可以把Directive和Controller统一成Component模型。所以,现在可以一箭双雕,当建立路由的时候,只要把路由映射到一个ComponentDirective(本质上由一个视图和控制器构成,就像之前一样)。

所以呢,如果你创建一个假想的客户编辑控制器,可能会是这样:

@ComponentDirective
export class CustomerEditController {constructor(server:Server) {this.server = server;this.customer = null;}activate(customerId) {return this.server.loadCustomer(customerId).then(response => this.customer = response.customer);}
}

真没什么新东西,我们就是在注入假想的服务端服务,当被路由激活的时候,使用它加载客户。有意思的是,你不需要使用选择器或者是其他任何元数据,因为这个组件不是被当作自定义元素来使用的。它是被路由动态创建,然后动态渲染到DOM中的。总之,不要太在意细节了。

那么,如果你明白了怎样创建ComponentDirective,你就明白了怎样创建等同于Angular 1.x中使用路由创建的控制器。在Angular 1.x中,很难把这些统一起来,但鉴于我们在Angular 2.0中有了这么帅的类和元数据驱动系统,指令就可以很显著地简化了,用这种方式创建你的“控制器”也变得很容易了。

注意:我想指出,上面的指令代码示例基于早期的原型代码和较新的设计文档规范,它们应当被解读为一种解释的工具,而不是指令的准确语法,那东西还在不断变化。模板编译器和绑定语言现在是Angular 2.0中最不稳定的部分,设计的变更非常频繁。

模板语法

至此,你已经对编译过程有了一个概要的认识了:知道它可以异步加载代码,如何编写指令,它们是怎样装配的,控制器怎么适应这些东西的。但我们尚未看一下真正的模板。我们现在来看看刚才假想的TabContainer的模板吧。为了方便起见,把指令代码再贴一遍:

@ComponentDirective({selector:'tab-container',directives:[NgRepeat]
})
export class TabContainer {constructor(panes:Query<Pane>) {this.panes = panes;}select(selectedPane:Pane) { ... }
}
<template><div class="border"><div class="tabs"><div [ng-repeat|pane]="panes" class="tab" (^click)="select(pane)"><img [src]="pane.icon"><span>${pane.name}</span></div></div><content></content></div>
</template>

当你看到这个语法的时候,不要害怕。是啊,这是符合规范的HTML,但不是我们最后的绑定语法。不过,还是用它作例子吧,这样我们能有个比较丰富的讨论的起点。

理解数据绑定语法的关键是属性定义的左侧,考虑到这点,我们先来看一下image标签。

<img [src]="pane.icon"><span>${pane.name}</span>

当你看到一个属性名称被[]包围的时候,它意思是右侧的属性值有一个绑定表达式。

当你看到一个表达式被${}包围的时候,它意思是这是一个表达式,应当被当作字符串插入到内容中(这跟ES6用来做字符串插值的语法相同)。

从模型/控制器到视图的绑定都是单向的。

现在让我们看看这可怕的div:

<div [ng-repeat|pane]="panes" class="tab" (^click)="select(pane)">

ng-repeat是一个TemplateDirective,你可以看出我们正在使用一个表达式来绑定它,因为它外面有[]。不过,它里面还有个 | ,还有一个单词“pane”,这表明在模板中使用的局部变量名称为“pane”。

现在看看(^click),使用括号表明我们把这个表达式作为一个事件处理函数。如果在括号里还有个 ^ ,就意味着不把处理函数直接附加到DOM节点上,而是让它冒泡,在文档的级别处理它。

在这个和模板部分的其他东西上,我暂不表达自己的意见,到下面的评注章节再说。现在先不管你我第一次看到这个的想法,先讨论为什么会选择这样的语法。

Web Components改变了所有东西。这是另外一个Web的变化影响框架的例子。多数基于数据绑定的框架假定了HTML元素的一个固定集合,并且已经预知了一些特定元素的行为,比如说input等等。可是,在Web Components的世界里,没有什么可以假设。一个开发人员,不针对Angular,可以编写一个自定义的元素,带有任意数量的属性,高兴加什么事件就加什么事件。不幸的是,没有办法检测Web Component来收集有关这些元数据,驱动绑定系统需要这些数据。比如说,没有办法知道实际触发了什么事件。看这个例子:

<x-foo bar="..." baz="..."></x-foo>

看看bar和baz,你能知道哪个是事件,哪个是属性?不……不幸的是,Angular也不知道,因为Web Components规范没有包含自描述组件的概念。这很不幸,因为它意味着一个数据绑定系统没法知道:它是不是需要连接一个绑定表达式,或者是不是需要添加一个事件处理函数来调用表达式。为了解决这个问题,我们需要一个通用的数据绑定系统,语法能够让开发人员区分哪个是事件,哪个是属性绑定。

这还不是唯一的困难。此外,所提供的信息还必须以这么一种不打破Web Component自身的方式。我这话的意思是,不能让Web Component看到这些表达式,那会破坏这个组件,它只应当看到表达式执行后的结果。实际上这不仅仅影响到Web Components,也会影响原生元素。考虑一下这个:

<img src="{{some.expression}}">

这个代码会产生一个错误的http请求,企图寻找“some.expression”这个图。这压根就不是我们想要的,我们根本不想img看到这个表达式,只希望它看到值。AngularJS 1.x解决这问题的方式是使用ng-src,一个自定义指令。现在,我们回到Web Components……如果你要给任意Web Compoents的每个属性都创建一个自定义指令,会是一场灾难,是不是?我觉得不能这样,所以需要在绑定系统中更普遍地解决这个问题。

要完成这事,你有两个选择。第一个是在模板编译期间,从DOM上移除属性。这能够阻止Web Component碰到这个表达式的文本。可是,这么做就意味着检测DOM的话,跟踪不到属性上绑定表达式的执行。这会让调试更加困难。另外一个选择是把属性名编码,这样Web Component就“认不出”它。这样可以让Angular看到这些表达式,但是Web Components却看不到。我们也可以在编译后把属性留在元素上,这样检测DOM的时候可以看得到。在调试的时候,当然就好得多了。

从以上可以看到,Angular团队目前支持的是编码属性的方法,这种编码也需要区分属性和事件。上面所示的语法是完成此事的多种可选项之一。

Angular团队已经在这一块严重争论了几个月。上述语法并未获得一致同意,但被多数人认同。当制订绑定语法的时候,也有过大量的考虑。如果你对这些感兴趣,我建议你读一下关于此主题的相当广泛【丰富】的文档。

好吧,现在我们终于介绍完了模板、绑定和指令是怎么混到一起的……

评注

关于刚才这些,我有太多话要说了……真不知道从何说起……

先从编译器自身说起吧。

我们是从一个较高层次看待模板的编译过程的。虽然在这一块,还有大量的实现要做,我对编译器的设计非常满意了。在这里面有一些挺好的东西,保持小的内存占用,减少了垃圾,并且使得模板的实例化超快。这些都很伟大,当然还需要改进,但已经很稳定了。虽然我们尚未谈及脏检测(数据绑定表达式更新的机制),它的实现也有一些新的不错的想法,可能会让模板实例化和脏检测自身的性能都有所提升。当然,能够动态加载任意东西太可怕了,这是Angular 1.x非常缺乏的一个特性,对大型应用却很关键。所以,它能作为核心需求来设计,我很高兴。

现在我们来讨论指令吧。

使用类、更好的依赖注入和注解来创建指令的新机制非常棒,它比Angular 1.x所需要的要简单多了。不幸的是,对于1.x开发人员而言,这是一个相当大的不兼容变更,如果你限于使用ES5,而不能或者不想使用ES6,TypeScript或者AtScript的话,写起来也会有些困难。本文的前面部分,我提到过提供小型库用于在ES5中更方便地创建注解类,这样的API可能会搞得像DDO对象那样,也许这能让从1.x到2.0的移植过程简单点。或许我们现在就应当开始构建它了,这样你可以在1.3里面使用,然后为2.0提供一个不同的实现……一种迁移抽象层。我也不确定,我想听听你们关于这块的想法,我知道很多人很关心这个。

关于指令,还有另外一件让我很困扰的事:注解有些冗长。回顾一下NgShow指令,你看到文本‘ngShow’或者它的某种变体重复了多少次?这对我来说显得有些傻。再看看CustomerEditController,我们要ComponentDirective干什么啊?既然路由都知道它是什么了,我们只写个普通类不行吗?

在内部我说了很多约定优于配置的想法,这也是Rails流行并影响很多现代框架的原因,我认为这是一种积极的方式。我想看到一些用于创建指令的约定能把样板消除。没有它们的话,我会认为新的指令系统并未把指令简化到应有的程度,感觉就像是把DDO的一些复杂性放到另外一个地方,也就是注解中去了。你会怎么想呢?喜欢约定吗?觉得这能让指令简单吗(假设你一直选择明确 这个地方怎么翻译啊)?

(assuming you always had the option to be explicit and override the conventions with annotations)?

不幸的是,这些都还不是真正的大问题。在Component Directive中有一个严重的问题,希望你已经看到了。注意到它们破坏了展现分离(Separated Presentation)原则吗?再看看我的TabContainer示例:

@ComponentDirective({selector:'tab-container',directives:[NgRepeat]
})
export class TabContainer {constructor(panes:Query<Pane>) {this.panes = panes;}select(selectedPane:Pane) { ... }
}

有没有看到TabContainer必须在其元数据中,列出其模板使用到的所有指令?这是TabContainer(控制器)到其视图实现细节的直接耦合。之前我提到过,对编译器而言,这是有必要的,因为它在编译模板之前,需要知道要加载什么,但是,这抵消了使用MVC,MVVM或者其他展现分离模式所带来的主要优势。为了避免你觉得我在纸上谈兵,我来指出一些后果吧:

  • 没办法实现ng-include了。为了编译HTML,编译器需要ComponentDirective,因此你就没法编译它自己上面的HTML,并且将其包含到一个View里。
  • 如果你想要为同一个组件创建多个潜在的视图,会很痛苦。想象一下,你有一个组件,但是想要在手机和电脑上显示不同的视图,需要聚合所有的指令、过滤器之类,这些东西你在所有视图都要用,还要确保在单个组件的元数据里把它们都列出来。这个维护起来太可怕了。如果不检测所有的视图,从依赖列表中删任何东西都是不可靠的,也有可能会忘记加东西。
  • 对同一个组件而言,是不可能拥有多种运行时视图的。想象一下,你配置了一些路由,某些路由使用了相同的“控制器”,但是你需要不同的视图。不好意思,真做不到。
  • 完全不可能实现展现层的临时组合,最起码这会让数据驱动的UI构建更加复杂。你没法简单地组合视图和控制器(视图模型)来渲染,这抑制了UI的组合方式,也限制了可复用性,它迫使你为了得到不同的视图,把控制器拆分成子类。

幸好,设计还是会有不少变化的,我提了个建议来解决这个问题,非常简单:通过让模板指定自己的imports,使得它能够完全自包含。把元数据移出指令,放到HTML模板中。可以这样使用一个自定义元素:

<ng-import src="ngRepeat"></ng-import>

编译器可以很容易找到他们,并且确保编译模板内容的时候,所有东西都加载完成了。就这样,刚才我提到的所有问题都解决了。

好了,现在我们说完编译器和指令了……

我感觉接下来是不是该说模板语法了?

老实说,很多人看到这个模板语法的时候可能会吐了,不是所有人,但有不少。我个人是不太喜欢这种语法的,但这是多数人投票的结果(为了理解为什么它还是个草案,你需要看看这篇文档)。别怕!已经有一些技术性的问题让这种语法变不成事实,更不用说社区的反对之声了。Angular团队已经回头继续讨论最佳语法了,很多社区成员也加入了,并且提出了自己的见解,很棒。我会把我自己的推荐放在这里,这样每个人都可以评论。

这是我提议的基本语法:

property="{{expression}}" - 从模型到元素属性的单向绑定,使用{{}}标识
on-event="{{expression}}" - 给事件添加处理函数,执行表达式,使用on-前缀标识
${expression} - HTML内容和属性中的字符串插值(基于ES6语法)

就这样。然后,在实现的时候,我们需要把表达式从DOM移除,以避免各种Web Component的问题之类。仅在调试模式,我们可以通过一个前缀,比如bind-,把它们加回来,这样可以在不影响Web Components的情况下,通过检测DOM的方式看到它们。这使得你所写的和在DOM检测器中看到的东西不太对称,但我觉得为了清晰、更加标准的绑定语法起见,这是一种合理的权衡。不是所有人都同意我,你觉得呢?

这个提议解决了绑定的技术问题,也对向后的兼容性有所帮助。可能我们能够对向后兼容性做很多的事情。我们能够允许在HTML内容中使用{{expression}}来做字符串插值,但是你可能会对此有选择余地。它可能会计划在20xx年被淘汰。推荐的方式可能会是${expression},但这可以对模板提供一个更平缓的升级路径。也有可能创建一套可选的指令用于支持ng-click之类,同样将于20xx年废弃。此外,我们可以提供文档,对照显示新旧的差异,帮助人们在“截断日期”之前,逐步地转换模板。

这就是我提案的基本内容,也有其他的提案,当然我是有倾向的,我也想知道你们的看法。向后兼容对你来说重要吗?你是更倾向于使用{{}}这样的语法,还是用某种方式把属性名进行编码?有太多选择了。

嗯,现在我们的问题都解决了。没,还有个超大的。

看看双向绑定!

我不知道你注意到没有,整篇文章连一个双向绑定的例子都没有。其实,我上面解释过的所有语法都不能用于指定各种绑定选项,如:方向性,触发器,防反跳等等。那,怎样绑定一个input元素,把数据推送到模型中呢?怎样绑定一个需要更新模型的自定义Web Component呢?

在Angular 2.0是否需要双向的数据绑定,Angular团队中产生了激烈的辩论。如果你读过公开的设计文档(包括这篇文档),或者看过ngEurope关于Angular 2.0核心的演讲或Q&A,你可能会发现这一点。我强烈支持保留双向数据绑定,在我看来,这是Angular灵魂的一部分。我尚未看到哪个建议能提供一个优雅的替代,在我能提出之前,还是会认同支持保留双向绑定。

你可能想知道这到底为了什么。

我听到过一些有关为数据流执行DAG的解释。这个思路是最近被ReactJS搞得火起来的。但是坦率地说,你不能完全执行它。我只要用一个事件聚合器就足以把它搞挂,这是一个在复合应用中非常常见的模式。我觉得你应当教给人们有关DAG的事情,帮助他们在合适的情况下使用,但不能强求。这会使他们的工作变得困难。

我听说过另外一个论点,主要围绕校验能力的不足,但这不是一个移除双向绑定的理由。你可以很容易在底层放双向绑定功能,把校验系统放在它的上层。

我认为最大问题来自Angular用于实现绑定的脏检测。因为脏检测,你每做一次检测,其实是做了两次。原因在于,如果第一次检测导致了变化,作为一种副作用,它可能导致其他变化。所以,为了确认,你一定还要再检测一次。然后,如果第二次检测之后,又变化了,还得检测第三次……等等。这个事情就称为模型的稳定化。是啊,这是脏检测系统的痛苦,但是移除双向绑定并不能解决这个问题。你还需要移除所有的监控器,这样一个表达式的变化不会导致它们中的任意一个产生变更。很明显,这也就是也需要考虑移除监控器的原因。可是这样也还是不能解决问题,因为一个事件聚合器就能绕过它……坦白地说,有时候你是需要这样的。数据绑定是一个很强大的工具,人也是会犯错的,但我认为我们能解决它。我知道你们中的很多人都可以的。

可能你不同意我的观点,你觉得“good riddance to two-way binding.”,持这种观点的人肯定很多。不过,我怀疑多数Angular,Durandal,Knockout,Ember等框架的用户会认同我。所幸的是,Angular团队在此事上尚未下定决心,他们在尝试考虑所有的可能性。所以,没必要担心。不过,如果你爱双向绑定的话,要来帮我,我觉得,如果Angular团队的其他成员能听到你们有多爱双向绑定的话,就太好了。

另一方面,如果你认为双向绑定是个坏主意,请你帮我们调查替代品。到目前为止,我尚未见到一个差不多好的替代方式,但也许你有比较好的想法呢。如果是这样的话,我请你来跟我们分享一下。如果我们能一起想出一些更好的东西……那就太棒了。

路由

啊!你对Angular 2.0真够感兴趣的。我真不相信你一直看到这里了。多谢!现在我们来讨论路由……

注意:如果你看累了,想要看一段有关路由的视频的话,可以找到我在ngEurope上关于这个主题的25分钟演讲。

基础

为了让Angular 2.0成为一个能干的框架,它需要有一个强大的路由解决方案。今年早些时候,Brian Ford开始围绕Angular社区内外已有的路由解决方案,进行了大量信息的整合。我们看了已有方案的很大一部分,并且把这些案例的研究与我们从社区收到的请求整合起来。把这些放在一起之后,社区就此文档提供了反馈
,然后我尝试实现一些东西。几个短的迭代之后,我们觉得我们做了个挺酷的东西。

自然,所有你期望路由处理的基本场景,新的路由处理了……

  • 简单的基于JSON的路由配置
  • 可选的约定优于配置
  • 静态的,参数化的,splat(这个什么意思?)的路由模式
  • 查询字符串的支持
  • 使用Push State或者Hashchange
  • 导航模型(用于生成导航UI)
  • 文档标题更新
  • 404路由的处理
  • 历史的操作
  • 更多

子路由

你可能习惯了有一个路由,并且不得不提前为整个应用配置所有的路由。但是,基于我们的新路由,你拥有更多的灵活性。事实上,每个你导航到的组件都可以有一个路由。我们称之为子路由,它允许你把应用的整个功能区域进行封装。如果你有一个拥有多个团队的大型项目,或者你是个“个体户”,这能够把你的代码库良好地分割,你会喜欢这个特性的。现在你可以把应用的每个部分当做一个小型应用来构建,它们有自己的路由。然后,你只要把他们挂接到主应用上,给组件映射一个相对路径,它就能运行了。如果你想看点有意思的,看看我演讲里面的递归子路由示例。

屏幕激活

有时候,在导航中你需要对过程有所控制。也许你是从一个带有未保存数据的数据入口屏幕离开,然后需要跟用户确认一下这样行不行。也许你在实现一个向导,在显示到第三步之前,需要确保数据存在于前两步,然后做相应的重定向。为了处理这类场景,我们实现了一个显式的导航生命周期,你的控制器可以选择对导航过程作控制。这里是一个生命周期的钩子列表:

  • canActivate,允许/阻止导航到新控制器
  • activate,对成功导航到新控制器的响应
  • canDeactivate,允许/阻止从旧控制器离开
  • deactivate,对成功离开旧控制器的响应

can*回调通过返回布尔值的方式,让你控制导航。你也可以为这个值返回一个Promise,这可以让你进行异步的操作,作为过程的一部分。此外,你可以返回一个特定的NavigationCommand(比如Redirect),它能让你对过程作底层控制。

如你所愿,所有这些都可以无缝与子路由协作。

设计

我们努力让设计尽可能可插拔。所有处理导航请求的逻辑都基于管道架构来建立,这意味着你可以向管道中加入自己的步骤,甚至移除一些我们默认的步骤。例如,如果你不喜欢屏幕激活行为,你可以把它干掉。在管道中,建模了四个步骤,每个代表一个生命周期阶段。管道的另外一个重要特性是,每一步都是异步的。所以,如果你需要发起一个服务端请求来对一个用户进行身份验证,或者为一个控制器加载数据,你可以在管道中做这个,并且把这个代码从控制器中移除。

评注

我很难对路由表示中立,因为是我做的实现。我认为这对于一个新路由而言,是良好的起步。肯定还有缺失的功能,但我认为高层次的设计是非常强大的。

作为奖励,我们也将把它移植回Angular 1.3上。

总结

感谢花这么多时间阅读本文。在本文发表的时间(2014年11月6日),这是有关Angular 2.0最广泛在、最新的知识来源了。所以,你赶上啦!

我试图列举主要的功能和设计的考虑,也包含了一定程度我自己的观点。设计仍然在发展,我们还处于开发的早期。所以,我希望在最终定稿之前,还能有些变化。也有一些“未知”,比如双向绑定,团队还不确定将来要如何处理。我们在尝试考虑所有的选择,也许我们会想出一些新的,令人惊讶的东西!?请耐心等待,记住,作为网络社区的成员,你们被邀请来评判这些问题。当做这些事情的时候,我恳请你们友好、礼貌,但请跟我们分享你的主意,思想和观点。

谢谢!

查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. Angular2.0CLI安装指南

    Angular2.0CLI安装指南 2017年03月12日 12:46:53 阅读数&#xff1a;2917 搭建AngularJS-CLI首先需要在windows上装node.js。安装node.js步骤&#xff1a; 1、http://download.csdn.net/download/huiling815/9709009 这是下载地址&#xff01;&#xff01;&#xff01;&…...

    2024/4/21 2:18:45
  2. Angular 2.0 预备库 Angular Starter Kit

    Angular Starter Kit 详细介绍angular-next-starter-kit 是使用 Angular 1.x 开发的应用准备迁移到 Angular 2.0 的种子项目。Angular 2.0 引入了一些新概念和设计模式&#xff0c;但是 Angular 2.0 还有几个月才能在生产环境使用。为了能让 Angular 1.x 开发的应用使用 Angula…...

    2024/4/20 13:29:55
  3. angular2.0学习笔记3.了解angular2.0项目结构

    1.我们应用的代码都位于src文件中&#xff0c;包括所有的组件、模板、样式、图片以及我们的应用所需的任何东西都在这个文件来里。 2.src这个文件夹之外的文件都是为构建应用提供支持用的。 src文件夹及用途说明 1.app/app.component.{ts,html,css,spec.ts} 使用html模板&#…...

    2024/4/21 2:18:44
  4. Angular2.0视频教程

    https://zhuanlan.zhihu.com/p/25198059...

    2024/4/21 2:18:42
  5. Angular 2.0 文本拖拽

    基于Angular7.1和TypeScript实现 Html代码 <div style"padding-left: 0px;"><div idcontentTem classtemp-style contentEditable"true" (drop)"drop($event)" (dragover)"allowDrop($event)">1</div><div>效…...

    2024/4/21 2:18:41
  6. Linux上搭建angular2.0环境

    非root用户下&#xff1a; 1.下载node版本 下载地址&#xff1a;https://npm.taobao.org/mirrors/node 这里以 node-v8.12.0-linux-x64.tar.gz 为例 2.解压node版本 sudo mv node-v8.12.0-linux-x64.tar.gz /target(目标文件夹) cd /target tar -zxvf node-v8.12.0-linux-x6…...

    2024/4/21 2:18:41
  7. Angular2.0实现的搜索框(重新按UX封装了样式)()

    之前封成了个指令&#xff0c;本来想本模块自己用&#xff0c;后来别的同事也要用&#xff0c;干脆封装成一个模块&#xff0c;供外部调用 使用(加了一个属性) <ky-search [disabled]"true" (searchContent)"searchContentChange($event)"> </k…...

    2024/4/21 2:18:39
  8. angular2.0--my first angular2 app

    官网&#xff1a;https://angular.io 文档&#xff1a;https://angular.io/docs/ts/latest/ 让我们从零开始&#xff0c;建立在TypeScript 的基础上build angular2 app 目录结构&#xff1a; angular2-quickstart   |—app     |— app.component.ts     |—ma…...

    2024/4/20 20:27:28
  9. angular2.0最新版环境搭建与常见问题

    第一步&#xff1a;安装Node.js,npm(安装Node.js的时候自动就安装了npm)第二部&#xff1a;安装npm&#xff0c;由于npm官网镜像访问太慢&#xff0c;我们使用淘宝的npm镜像&#xff0c;在node命令窗口&#xff08;windows的cmd、linux的终端&#xff09;$ npm install -g cnpm…...

    2024/4/20 20:27:20
  10. 全面支持 Angular2 的 Web 后台 Bootstrap 模板 Sing App – Web Angular 2.0 Dashboard

    在线预览 Sing App v3.3.0 (包含 Angular 2.0 版本实现) 现在&#xff0c;本模板完全支持Angular2.0版本啦。 Sing Web App 是由专业前端工程师采用行业内流行的技术构建的一款全新的HTML后台管理模板。该模板拥有像素级完美的时尚设计和强大且通用的即用型编程功能。Sing Web …...

    2024/4/20 20:27:18
  11. angular 2.0 关于新版angular-cli的应用

    1.以前写过一个webstorm借助angular-cli搭建angular2.0项目的博客。 后来许久没有接触过angular&#xff0c;现在拾起来的时候发现已经更新&#xff0c;用法变了。所以来记录下&#xff0c;以免其他友看到照成误区。2.这也是说明一个道理&#xff0c;别人写下的东西你不一定适用…...

    2024/4/20 20:27:17
  12. angular预览PDF总结

    前言 单个页面可以同时预览多份PDF&#xff0c;这样就无法使用window.open(https:www.wxw.pdf,_self);的方式去利用自带浏览器去解析PDF。因为原因&#xff08;1&#xff09;&#xff0c;所以采用iframe去嵌入解析多个PDF链接。但是又发现&#xff0c;安卓手机端无法直接加载显…...

    2024/4/20 20:27:16
  13. 拖拽(可以封装成指令的形式 angular )

    //父元素的宽高&#xff0c;不让其脱离宽高//link:function (scope,ele,attr) {ele.parent (可以拿父元素的宽高)}$scope.widths $(".box").width();$scope. heights $(".box").height();function draggleBefore (_this,ev){var pos $scope.getPos(ev);…...

    2024/4/20 20:27:16
  14. angular 全局confirm确认框

    全局确认框是在弹出模态框的基础上修改的。 配置 模板 angular.module(custom-template, []) .run(["$templateCache", function($templateCache) {$templateCache.put("template/modal/confirmModelTemplate.html",<div class"m-c">\n…...

    2024/4/20 20:27:15
  15. angular primeng 弹出对话框修改

    功能目标&#xff1a; 点击列表项字符串弹出对话框&#xff0c;修改后关闭对话框&#xff0c;替换列表项原字符串。 点击“background"时弹出图2&#xff1a; 点击【apply】&#xff0c;列表框background变为background1 组件&#xff1a; TextareaDialog----提供图2的编辑…...

    2024/4/20 20:27:13
  16. Angular4 引用 material dialog时自定义对话框

    引用 material dialog 方法 官方文档自定义弹框内容后的结果 dialog html <div style"background-color: #4eaee1">我是内容 </div> 啊嘞&#xff0c;奇怪了&#xff0c;我并没哟设置 padding值&#xff0c;但是却有padding 查看material dialog …...

    2024/4/24 2:31:36
  17. angular双向绑定数据后,通过jquery修改input中的值后,angular绑定失效

    $(document).on(input propertychange, .peacetimescore, function(){if($(this).val()>20 || $(this).val()<0){layer.msg("请输入0-20之间的成绩");$(this).val("0").trigger(change);//这句话可以实现更新到model&#xff1b;} });...

    2024/4/20 6:56:06
  18. angular实现div盒子高度自适应

    <body ><div my-dre></div> </body><script>angular.module("myApp",[])//自定义一个指令.directive("myDre",function(){return{link:function($scope,Ele,Attrs){//首先获取打开浏览器窗口的高度↓$scope.heightwindow.in…...

    2024/4/21 2:18:36
  19. Angular与模态框的通讯

    Angular做项目的时候&#xff0c;难免会用到弹框&#xff08;即模态框&#xff09;&#xff0c;如果模态框里面有一张表格&#xff0c;表格里面的数据需要从父组件&#xff08;这里暂且先说成父组件吧&#xff01;&#xff09;里面获取&#xff0c;模态框的表格里面的数据经过修…...

    2024/4/21 2:18:35
  20. Angular两种模态框弹出方式

    在开始我们的blog之前&#xff0c;我们要先安装ngx-bootstrap-modal npm install ngx-bootstrap-modal --save 然后在index.html导入bootstrap样式表 <link href"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" rel"styleshe…...

    2024/4/23 13:01:14

最新文章

  1. 数据中台工具的选型要点_光点科技

    数据中台工具扮演着举足轻重的角色。想要全面理解数据中台工具的意义、作用以及应用方式&#xff0c;就必须深入探讨这一概念以及相关实践。 数据中台工具概述 数据中台&#xff0c;是一个支持数据集成、管理、分析和服务的平台&#xff0c;它能够帮助企业统一数据资源&#xf…...

    2024/4/24 16:06:14
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. 爬虫学习第一天

    爬虫-1 爬虫学习第一天1、什么是爬虫2、爬虫的工作原理3、爬虫核心4、爬虫的合法性5、爬虫框架6、爬虫的挑战7、难点8、反爬手段8.1、Robots协议8.2、检查 User-Agent8.3、ip限制8.4、SESSION访问限制8.5、验证码8.6、数据动态加载8.7、数据加密-使用加密算法 9、用python学习爬…...

    2024/4/23 6:25:49
  4. 人工智能产业应用--具身智能

    五、下一个浪潮 (一) 跳出缸中脑——虚实结合 在探索人工智能的边界时&#xff0c;“跳出缸中脑——虚实结合”这一概念提出了一个引人深思的视角&#xff0c;尤其是在具身智能的领域。具身智能是一种思想&#xff0c;强调智能体通过与其环境的直接物理互动来实现智能行为。然…...

    2024/4/22 16:29:21
  5. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/4/23 20:58:27
  6. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/4/23 13:30:22
  7. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/4/23 13:28:06
  8. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/4/20 23:26:47
  9. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/4/23 13:27:44
  10. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/4/19 11:57:53
  11. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/4/23 13:29:53
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/4/23 13:27:22
  13. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/4/23 13:28:42
  14. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/4/23 22:01:21
  15. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/4/23 13:29:23
  16. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/4/23 13:27:46
  17. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/4/23 13:47:22
  18. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/4/19 11:59:23
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/4/19 11:59:44
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/4/23 13:28:08
  21. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/4/23 13:29:47
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/4/23 13:28:14
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/4/23 13:27:51
  24. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/4/23 13:27:19
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57