我们在上一期中讲 $rootscope时,看到$rootscope是依赖$prase,其实不止是$rootscope,翻看angular的源码随便翻翻就可以发现很多地方是依赖于$parse的。而$parse的源码打开一看,它的代码量有接近两千行。翻开angular的api文档,官方只给出了简短的解释"Converts Angular expression into a function(将一个angular的表达式转化为一个函数)",心中神兽奔腾————就这么点功能为什么要“两千行代码”呢。

一、分享一下源码作者的第一段注释


/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * **     Any commits to this file should be reviewed with security in mind.  **   Changes to this file can potentially create security vulnerabilities. **          An approval from 2 Core members with history of modifying      **                         this file is required.                          **                                                                         **  Does the change somehow allow for arbitrary javascript to be executed? **    Or allows for someone to change the prototype of built-in objects?   **     Or gives undesired access to variables likes document or window?    ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
这段声明,我只在angular源码中的三个文件中看到:$parse,$sce,$compile。

这段声明的大体意思是:所有提交到这个文件的修改都会因为出于安全性的考虑被检视。修改这个文件可能会带来安全漏洞。至少需要两位angular的核心成员审批,这个文件才能修改。所做的修改是否会导致任意的js代码的执行,或者允许某人修改绑定在对象上的原型(prototype),或者给予不被希望的访问变量(比如document,window)的权限。

敢情,作者实现了一个编译器,正在学习编译原理的同学有福了
通过阅读后面的注释以及https://docs.angularjs.org/guide/security,可以知道:这里实现$parse使用了2000行代码是出于安全性的考虑,而使用了编译器的方式来编译需要解析的表达式。在词法解析的过程中,本来可以使用正则表达式的,但是作者使用了自己构建一个词法解析器(Lexer),我的猜测是出于性能的考虑。通过编译原理的学习,我们知道词法的解析只需要3型文法,而3型文法等价于正则表示,所以用正则表示能够识别所有的需要的词法。利用通行的正则表达式,固然可以很快的写出一个词法分析器,但是效率却是很低的,正则表达式的执行,需要反复多次的遍历字符串,对于被频繁调用的$parse服务(我们说它干的是脏活累活)用正则表达式来实现词法分析器显然是不合适的。

二、编译原理(这一部分对于angular的源码分析,没有太大卵用,可以跳过)

对于编译原理,其实就是计算机科学家在编写编译器过程中总结出来的一套理论。而编译器,是一个程序,它的输入是一种编程语言,输出结果是另外一种编程语言,相当于是一个翻译官,比如可以将英语翻译成中文。抽象出来,就是将A语言翻译成B语言的程序,称之为编译器。这会带来一个问题,A语言和B语言的描述能力是否相同,就是A语言和B语言是否等价,是否能否翻译。

说点题外话
读者有没有想过这个问题:为什么人类的语言能够相互翻译呢?反正,这个问题我是一直在思索,最近在读《乔姆斯基的思想与理想》算是找到了一种解释:人类有一种共同内在语言,乔姆斯基称之为I语言,这是源自于人类的固有属性的东西,而我们使用的汉语、英语神马的都不过是一种表观的语言,它们是I语言的编码,其描述能力自然等价于I语言,那么这些语言的表述能力也就相等了。(乔姆斯基是现在还健在的大师,我个人觉得可以将他与牛顿、达尔文、爱因斯坦等人齐名)

1.编译器的一般构成:

一个编译器一般包含这几个子程序:代码预处理程序,词法分析器,语法分析器,语义分析器,目标代码生成器,目标代码优化器等。
代码预处理程序:作用在于干掉代码中的不相关的部分,包括注释、多余的空格,以及将预编译指令翻译成代码。

词法分析器:根据语言规定的词汇表规则识别出合法的词汇,如果有非法词汇停止编译,抛出错误信息。比如,在写C语言中,对标识符的定义是,以字母或下划线开头可以包含字母、数字、下划线的字符串,词法分析器就是根据这个定义来识别标识符。
算了,限于篇幅,后面省略。。。。

2.文法分类

1956年,Chomsky建立形式语言的描述。通过对产生式的施加不同的限制,Chomsky把文法分为4种类型
首先定义一个产生式α→β

0型文法(PSG):

α∈(VN∪VT)* ,且至少含一个VN

β∈(VN∪VT)*
对产生式没有任何限制
例如:A0→A0,A1→B
0型文法说明:
0型文法也称为短语文法。

一个非常重要的理论结果是,0型文法的能力相当于图灵机(Turing),关于图灵机,我的另一篇博文《第一章,计算机的发明》有讲到。或者说,任何0型语言都是递归可枚举的;反之,递归可枚举集必定是一个0型语言。对0型文法产生式的形式作某些限制,以给出1,2和3型文法的定义。
注意
文法G 定义为四元组(VN ,VT ,P,S)
VN :非终结符集
VT :终结符集
P :产生式集合(规则集合)
S :开始符号(识别符号)

1型文法(上下文有关文法context-sensitive):

对任一产生式α→β,都有|β|>=|α|, 仅仅S→ε除外
  产生式的形式描述:α1Aα2→α1βα2
  (其中,α1、α2、β∈(VN∪VT)*,β≠ε,A∈VN)
  即:A只有出现在α1α2的上下文中,才允许用β替换。
  产生的语言称“上下文有关语言”
  例如:0A0→011000,1A1→101011

2型文法(CFG):

对任一产生式α→β,都有α∈VNβ∈(VN∪VT)*
  产生式的形式描述:A→β(A∈VN)
  即β取代A时,与A所处的上下文无关。
  产生的语言称“上下文无关语言”
  例如:G[S]:S→01 S→0S1

3型文法(RG):也称正规文法

每个产生式均为A→aBA→a —— 右线性
  A→BaA→a —— 左线性
  其中,A、B∈VN,a∈VT*
  产生的语言称“正规语言”
  例如:G[S]: S→0A | 0,A→1B | B,B→1 | 0

三、$parse的词法解析器

1.在讲源代码前,先讲字符串搜索的预搜索技术.

在匹配运算符号的时候会出现一个问题:比如,在匹配x += y中的运算符时,如果逐个字符扫描,将得到连接x和y中的中间运算符是+=,而我们知道这里其实是一个运算符号+=,那么怎么办呢?
很简单:遇到+时,我们先不要断言它是一个"加预算符",继续读入一个字符,看这两个字符是否能够组成一个新的符号,如果能组成则一个识别,索引标签步进两个单位,如果不能则判断+号是"加运算符",提前读入的字符不算数。
我们将这种预先处理的技术,称为"预搜索技术"。
推广下去,你会得到KMP算法

2.词法解析器的源代码:

var Lexer = function(options) {this.options = options;
};Lexer.prototype = {constructor: Lexer,lex: function(text) { //将一个字符串转换成一个词汇表this.text = text;this.index = 0;this.tokens = [];while (this.index < this.text.length) {var ch = this.text.charAt(this.index);if (ch === '"' || ch === "'") { //识别字符串this.readString(ch);} else if (this.isNumber(ch) || ch === '.' && this.isNumber(this.peek())) {//识别number(包括,整数、浮点数和科学计数法this.readNumber();} else if (this.isIdent(ch)) {//识别标识符this.readIdent();} else if (this.is(ch, '(){}[].,;:?')) { //识别边界符号this.tokens.push({index: this.index, text: ch});this.index++;} else if (this.isWhitespace(ch)) { //识别空格this.index++;} else { //运算符的识别,一个运算符由1到3个字符组成,需要预搜索var ch2 = ch + this.peek();//预搜索1个字符var ch3 = ch2 + this.peek(2);//预搜索2个字符var op1 = OPERATORS[ch];var op2 = OPERATORS[ch2];var op3 = OPERATORS[ch3];if (op1 || op2 || op3) {var token = op3 ? ch3 : (op2 ? ch2 : ch);this.tokens.push({index: this.index, text: token, operator: true});this.index += token.length;} else {this.throwError('Unexpected next character ', this.index, this.index + 1); //发生异常,抛出}}}return this.tokens;//返回存储下来的词汇表},is: function(ch, chars) { //判断ch是否是chars字符串中一个字符return chars.indexOf(ch) !== -1;},peek: function(i) { //返回,预读i个字符var num = i || 1;return (this.index + num < this.text.length) ? this.text.charAt(this.index + num) : false;},isNumber: function(ch) { //判断字符是否是数字return ('0' <= ch && ch <= '9') && typeof ch === "string";},isWhitespace: function(ch) { //判断字符是否是非打印字符// IE treats non-breaking space as \u00A0return (ch === ' ' || ch === '\r' || ch === '\t' ||ch === '\n' || ch === '\v' || ch === '\u00A0');},isIdent: function(ch) { //判断ch是否是属于标识符的字符集return ('a' <= ch && ch <= 'z' ||'A' <= ch && ch <= 'Z' ||'_' === ch || ch === '$');},isExpOperator: function(ch) { //是否科学技术法中的符号(+或者-)return (ch === '-' || ch === '+' || this.isNumber(ch));},throwError: function(error, start, end) { //错误抛出end = end || this.index;var colStr = (isDefined(start)? 's ' + start +  '-' + this.index + ' [' + this.text.substring(start, end) + ']': ' ' + end);throw $parseMinErr('lexerr', 'Lexer Error: {0} at column{1} in expression [{2}].',error, colStr, this.text);},readNumber: function() { //读入一个数var number = '';var start = this.index;while (this.index < this.text.length) {var ch = lowercase(this.text.charAt(this.index));if (ch == '.' || this.isNumber(ch)) {number += ch;} else {var peekCh = this.peek();if (ch == 'e' && this.isExpOperator(peekCh)) {number += ch;} else if (this.isExpOperator(ch) &&peekCh && this.isNumber(peekCh) &&number.charAt(number.length - 1) == 'e') {number += ch;} else if (this.isExpOperator(ch) &&(!peekCh || !this.isNumber(peekCh)) &&number.charAt(number.length - 1) == 'e') {this.throwError('Invalid exponent');} else {break;}}this.index++;}this.tokens.push({index: start,text: number,constant: true,value: Number(number)});},readIdent: function() { //读入一个标识符var start = this.index;while (this.index < this.text.length) {var ch = this.text.charAt(this.index);if (!(this.isIdent(ch) || this.isNumber(ch))) {break;}this.index++;}this.tokens.push({index: start,text: this.text.slice(start, this.index),identifier: true});},readString: function(quote) { //读入一个字符串var start = this.index;this.index++;var string = '';var rawString = quote;var escape = false;while (this.index < this.text.length) {var ch = this.text.charAt(this.index);rawString += ch;if (escape) {if (ch === 'u') {var hex = this.text.substring(this.index + 1, this.index + 5);if (!hex.match(/[\da-f]{4}/i)) {this.throwError('Invalid unicode escape [\\u' + hex + ']');}this.index += 4;string += String.fromCharCode(parseInt(hex, 16));} else {var rep = ESCAPE[ch];string = string + (rep || ch);}escape = false;} else if (ch === '\\') {escape = true;} else if (ch === quote) {this.index++;this.tokens.push({index: start,text: rawString,constant: true,value: string});return;} else {string += ch;}this.index++;}this.throwError('Unterminated quote', start);}
};

3.上面代码对应的有限状态机

有限状态机

4.如果用正则表达式来实现

1.字符串:/(["'])\S+\1/
2.number:/([0-9]*.)?[0-9]+(e[\+-][0-9]+)?/
3.标识符:/[a-zA-Z_\$][a-zA-Z0-9_\$]*/
4.运算符:/\+|-|\*|\/|%|===|\!==|==|\!=|<|>|<=|>=|&&|\|\||\!|=|\|/

四、$parse的语法解析器

1.概念

AST:Abstract Syntax Tree,抽象语法树
抽象语法树(Abstract Syntax Tree ,AST)作为程序的一种中间表示形式,在程序分析等诸多领域有广泛的应用。利用抽象语法树可以方便地实现多种源程序处理工具,比如源程序浏览器、智能编辑器、语言翻译器等。

2.$parse的AST实现:

var AST = function(lexer, options) {this.lexer = lexer;this.options = options;
};//下面定义了语法树节点的类型
AST.Program = 'Program';//代表程序的根节点
AST.ExpressionStatement = 'ExpressionStatement'; //表达式节点
AST.AssignmentExpression = 'AssignmentExpression';//赋值表达式
AST.ConditionalExpression = 'ConditionalExpression';//判断表达式
AST.LogicalExpression = 'LogicalExpression';//逻辑运算表达式
AST.BinaryExpression = 'BinaryExpression';//二进制预算处理表达式(按位与、按位或)? 看了后面,才知道这种理解是不对的.这表示的大小关系.但是为什么要取这个名字呢?
AST.UnaryExpression = 'UnaryExpression';  //非数据表达式
AST.CallExpression = 'CallExpression'; //调用表达式
AST.MemberExpression = 'MemberExpression'; //成员变量表达式
AST.Identifier = 'Identifier'; //标识符
AST.Literal = 'Literal'; //文字,额,这里是指ture,false,null,undefined等
AST.ArrayExpression = 'ArrayExpression';//数据表达式
AST.Property = 'Property'; //对象属性表达式
AST.ObjectExpression = 'ObjectExpression';//对象表达式
AST.ThisExpression = 'ThisExpression';//this表达式// Internal use only
AST.NGValueParameter = 'NGValueParameter';AST.prototype = {ast: function(text) {//语法树的入口this.text = text;this.tokens = this.lexer.lex(text);//调用词法分析器,得到合法的词汇表var value = this.program();//调用"program"子程序,开始生成语法树if (this.tokens.length !== 0) {this.throwError('is an unexpected token', this.tokens[0]);}return value;},program: function() {var body = [];while (true) {//循环,调用expressionStatement读取语句if (this.tokens.length > 0 && !this.peek('}', ')', ';', ']'))body.push(this.expressionStatement());if (!this.expect(';')) {return { type: AST.Program, body: body};//返回一个语法树}}},expressionStatement: function() { //表达式节点,代表的是js的一个语句return { type: AST.ExpressionStatement, expression: this.filterChain() };//其中调用过滤器链filterChain.这是是为识别过滤器的语法如:timestamp|date:'yyyy-mm-dd'},filterChain: function() { var left = this.expression();//调用expression,获取语法树的节点var token;while ((token = this.expect('|'))) { //过滤器可能是以链状存在的,比如:xxx|filter1|filter2...,所以需要循环处理left = this.filter(left); //调用filter}return left;},expression: function() {return this.assignment();},assignment: function() {//识别赋值语句var result = this.ternary();if (this.expect('=')) {result = { type: AST.AssignmentExpression, left: result, right: this.assignment(), operator: '='};}return result;},ternary: function() {//识别三元运算:xxx?Axxx:Bxxx;var test = this.logicalOR();var alternate;var consequent;if (this.expect('?')) {alternate = this.expression();if (this.consume(':')) {consequent = this.expression();return { type: AST.ConditionalExpression, test: test, alternate: alternate, consequent: consequent};}}return test;},logicalOR: function() { //识别逻辑运算 "或"(||)var left = this.logicalAND();while (this.expect('||')) {left = { type: AST.LogicalExpression, operator: '||', left: left, right: this.logicalAND() };}return left;},logicalAND: function() { //识别逻辑运算 "与"(&&)var left = this.equality();while (this.expect('&&')) {left = { type: AST.LogicalExpression, operator: '&&', left: left, right: this.equality()};}return left;},equality: function() { //识别逻辑运算 "等"(==)var left = this.relational();var token;while ((token = this.expect('==','!=','===','!=='))) {left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.relational() };}return left;},relational: function() { //识别大小比较的表达式var left = this.additive();var token;while ((token = this.expect('<', '>', '<=', '>='))) {left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.additive() };//没搞懂为什么要取这个名字Binary,一开始还以为是二进制运算相关}return left;},additive: function() { //识别加减表达式var left = this.multiplicative();var token;while ((token = this.expect('+','-'))) {left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.multiplicative() };}return left;},multiplicative: function() {//识别乘除法var left = this.unary();var token;while ((token = this.expect('*','/','%'))) {left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.unary() };}return left;},unary: function() { //处理非数组的表达式var token;if ((token = this.expect('+', '-', '!'))) {return { type: AST.UnaryExpression, operator: token.text, prefix: true, argument: this.unary() };} else {return this.primary();}},primary: function() {//处理js的远程语法写的内容var primary;if (this.expect('(')) {primary = this.filterChain();this.consume(')');} else if (this.expect('[')) {primary = this.arrayDeclaration();} else if (this.expect('{')) {primary = this.object();} else if (this.constants.hasOwnProperty(this.peek().text)) {primary = copy(this.constants[this.consume().text]);} else if (this.peek().identifier) {primary = this.identifier();} else if (this.peek().constant) {primary = this.constant();} else {this.throwError('not a primary expression', this.peek());}var next;while ((next = this.expect('(', '[', '.'))) {if (next.text === '(') {primary = {type: AST.CallExpression, callee: primary, arguments: this.parseArguments() };this.consume(')');} else if (next.text === '[') {primary = { type: AST.MemberExpression, object: primary, property: this.expression(), computed: true };this.consume(']');} else if (next.text === '.') {primary = { type: AST.MemberExpression, object: primary, property: this.identifier(), computed: false };} else {this.throwError('IMPOSSIBLE');}}return primary;},filter: function(baseExpression) {//处理过滤器语法var args = [baseExpression];//将传入参数放入args ,做第一个参数节点var result = {type: AST.CallExpression, callee: this.identifier(), arguments: args, filter: true};//使用过滤器,其实质是调用一个函数,所以语法树节点是一个"CallExpression"while (this.expect(':')) {args.push(this.expression());//压缩其他参数节点}return result;},parseArguments: function() { //处理参数var args = [];if (this.peekToken().text !== ')') {do {args.push(this.expression());} while (this.expect(','));}return args;},identifier: function() { //处理标识符var token = this.consume();if (!token.identifier) {this.throwError('is not a valid identifier', token);}return { type: AST.Identifier, name: token.text };},constant: function() { //处理常量// TODO check that it is a constantreturn { type: AST.Literal, value: this.consume().value };},arrayDeclaration: function() { //处理数组var elements = [];if (this.peekToken().text !== ']') {do {if (this.peek(']')) {// Support trailing commas per ES5.1.break;}elements.push(this.expression());} while (this.expect(','));}this.consume(']');return { type: AST.ArrayExpression, elements: elements };},object: function() {//处理Objectvar properties = [], property;if (this.peekToken().text !== '}') {do {if (this.peek('}')) {// Support trailing commas per ES5.1.break;}property = {type: AST.Property, kind: 'init'};if (this.peek().constant) {property.key = this.constant();} else if (this.peek().identifier) {property.key = this.identifier();} else {this.throwError("invalid key", this.peek());}this.consume(':');property.value = this.expression();properties.push(property);} while (this.expect(','));}this.consume('}');return {type: AST.ObjectExpression, properties: properties };},throwError: function(msg, token) {throw $parseMinErr('syntax','Syntax Error: Token \'{0}\' {1} at column {2} of the expression [{3}] starting at [{4}].',token.text, msg, (token.index + 1), this.text, this.text.substring(token.index));},consume: function(e1) {if (this.tokens.length === 0) {throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);}var token = this.expect(e1);if (!token) {this.throwError('is unexpected, expecting [' + e1 + ']', this.peek());}return token;},peekToken: function() {if (this.tokens.length === 0) {throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);}return this.tokens[0];},peek: function(e1, e2, e3, e4) {return this.peekAhead(0, e1, e2, e3, e4);},peekAhead: function(i, e1, e2, e3, e4) {if (this.tokens.length > i) {var token = this.tokens[i];var t = token.text;if (t === e1 || t === e2 || t === e3 || t === e4 ||(!e1 && !e2 && !e3 && !e4)) {return token;}}return false;},expect: function(e1, e2, e3, e4) {//期望子程序,如果满足期望,将this.tokens队列头部弹出一个元素返回,否则返回falsevar token = this.peek(e1, e2, e3, e4);if (token) {this.tokens.shift();return token;}return false;},/* `undefined` is not a constant, it is an identifier,* but using it as an identifier is not supported*/constants: {'true': { type: AST.Literal, value: true },'false': { type: AST.Literal, value: false },'null': { type: AST.Literal, value: null },'undefined': {type: AST.Literal, value: undefined },'this': {type: AST.ThisExpression }}
};

3.语法树的数据结构:

从上面的代码中可以得知,语法树的一个节点的数据结构

{ type: AST.xxxStatement, //节点类型xxx:xxx, //每种节点类型的所含的元素不同   
}//1.语法树根节点
{   type: AST.Program,    body: body
}
//2.语法数表达式节点
{   type: AST.ExpressionStatement,    expression: this.filterChain() 
}
//3.赋值语句节点
{   type: AST.AssignmentExpression,   left: result,     right: this.assignment(),   operator: '='
}
//4.条件表达式节点(三目预算)
{   type: AST.ConditionalExpression,  test: test,  alternate: alternate,    consequent: consequent
}
//5.逻辑预算节点
{   type: AST.LogicalExpression,  operator: '||',  left: left,  right: this.logicalAND() 
}
//6.比较运算节点
{   type: AST.BinaryExpression,   operator: token.text,     left: left,     right: this.relational() 
}
//7.非数据节点
{   type: AST.UnaryExpression,    operator: token.text,  prefix: true,    argument: this.unary() 
}
//8.成员变量节点
{   type: AST.MemberExpression,   object: primary,  property: this.expression(),     computed: true 
}
//9.标识符节点
{   type: AST.Identifier,     name: token.text 
}
//10.常量节点
{   type: AST.Literal,    value: this.consume().value 
}
//11.数据节点
{   type: AST.ArrayExpression,    elements: elements 
}

4.举例

假设angular表达式是str = ok.str;str.length>2?'abc':123|test:look;
那么通过上面的程序,得到的语法树将是:

语法树

五、$parse编译器

在$parse中定义了两个编译器:ASTCompiler 和 ASTInterpreter,他们的作用都是调用AST生成语法树,然后将语法树组装成js函数。
两者之间的差别是
1.ASTCompiler 会将句法树按语义组装成函数,ASTInterpreter是按语义组装成语句,然后调用循环,主句执行;
2.ASTInterpreter的语句执行过程中,会被附加ensureSafeXXX的函数,进行安全性检查。
3.看看,他们都是怎么被调用的:

/*** @constructor*/
var Parser = function(lexer, $filter, options) {this.lexer = lexer;this.$filter = $filter;this.options = options;this.ast = new AST(this.lexer);this.astCompiler = options.csp ? new ASTInterpreter(this.ast, $filter) : //什么是csp??new ASTCompiler(this.ast, $filter);
};Parser.prototype = {constructor: Parser,parse: function(text) {return this.astCompiler.compile(text, this.options.expensiveChecks);}
};

什么是csp,请看CSP 1.1 specification;
还有一篇:浏览器安全策略说之内容安全策略CSP;
另外推荐angular-ngcsp和angular-Security
写得太多了,其他代码就不再分析了。如果有机会,后面再补一篇博文。

六、$parse服务

这里,将$parse代码函数代码贴出来,如果上面的代码明白了,下面的也就很简单了,不再赘述了.

function $parse(exp, interceptorFn, expensiveChecks) {var parsedExpression, oneTime, cacheKey;switch (typeof exp) {case 'string':exp = exp.trim();cacheKey = exp;var cache = (expensiveChecks ? cacheExpensive : cacheDefault);parsedExpression = cache[cacheKey];if (!parsedExpression) {if (exp.charAt(0) === ':' && exp.charAt(1) === ':') {oneTime = true;exp = exp.substring(2);}var parseOptions = expensiveChecks ? $parseOptionsExpensive : $parseOptions;var lexer = new Lexer(parseOptions);var parser = new Parser(lexer, $filter, parseOptions);parsedExpression = parser.parse(exp);if (parsedExpression.constant) {parsedExpression.$$watchDelegate = constantWatchDelegate;} else if (oneTime) {parsedExpression.$$watchDelegate = parsedExpression.literal ?oneTimeLiteralWatchDelegate : oneTimeWatchDelegate;} else if (parsedExpression.inputs) {parsedExpression.$$watchDelegate = inputsWatchDelegate;}cache[cacheKey] = parsedExpression;}return addInterceptor(parsedExpression, interceptorFn);case 'function':return addInterceptor(exp, interceptorFn);default:return noop;}};

这篇博文,我从昨天写到今天,终于勉强写完了。
你说$parse是不是专干脏活和累活呢?
上一期:angular源码分析:angular中$rootscope的实现——scope的一生
下一期:angular源码分析:angular源码分析:angular中入境检察官$sce
ps:sec,是Strict Contextual Escaping的缩写。这个可以被我们用的较少,这里给api的链接:$sec

转载于:https://www.cnblogs.com/web2-developer/p/angular-10.html

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

相关文章

  1. angular 中的$parse ,$eval

    AngularJS的初学者常常会对$parse和$eval两个内建服务感到有些困惑&#xff0c;今天我们就来说说AngularJS中的$parse和$eval。 总的来说&#xff0c;$parse和$eval都是作用于AngularJS的表达式。 什么是表达式&#xff1f;AngularJS中的表达式就是一些类似于JavaScript代码的代…...

    2024/4/28 3:24:09
  2. 浅谈AngularJS中的$parse和$eval

    $parse和$eval都是用来将表达式转为一个函数 $eval是scope的一个方法&#xff0c;$parse是一种全局可以使用的服务。 从api可以看出来$eval是一种使用当前上下文的特殊$parse // $parse$parse(expr)(context, locals);// $eval: // expr:要解析的表达式 // locals:…...

    2024/4/21 3:53:57
  3. $broadcast、$on、$emit,angular不同级控制器之间的传值

    工作中经常用到的是$broadcast、$on&#xff0c;$emit自己用的很少。 一.关于$broadcast事件&#xff1a;该服务发布一个向下的事件从父作用域开始传给下面所有的子作用域&#xff08;包括自己&#xff09;&#xff0c;并通知$on接收&#xff0c;该事件的生命周期也是从broadca…...

    2024/4/21 3:53:56
  4. $on、$emit和$broadcast的使用

    $emit只能向parent controller传递event与data( $emit(name, args) )$broadcast只能向child controller传递event与data( $broadcast(name, args) )$on用于接收event与data( $on(name, listener) ) <div ng-controller"ParentCtrl"> <!--父级-…...

    2024/4/21 3:53:55
  5. angularjs中控制器之间的通信----$on、$emit和$broadcast解析

    $on、$emit和$broadcast使得event、data在controller之间的传递变的简单。 $emit只能向parent controller传递event与data$broadcast只能向child controller传递event与data$on用于接收event与data例如&#xff1a; <div ng-controller"ParentCtrl"> …...

    2024/4/21 3:53:54
  6. AngularJS的学习--$on、$emit和$broadcast

    $on、$emit和$broadcast使得event、data在controller之间的传递变的简单。 $emit只能向parent controller传递event与data$broadcast只能向child controller传递event与data$on用于接收event与data 例子如下 html代码 <div ng-controller"ParentCtrl"> …...

    2024/4/21 3:53:53
  7. Angular中 broadcast和 emit的使用方法

    分享一下我老师大神的人工智能教程&#xff01;零基础&#xff0c;通俗易懂&#xff01;http://blog.csdn.net/jiangjunshow也欢迎大家转载本篇文章。分享知识&#xff0c;造福人民&#xff0c;实现我们中华民族伟大复兴&#xff01;要在控制器之间传递变量变化需要使用angular…...

    2024/4/26 14:12:37
  8. AngularJS的学习--$on、$emit和$broadcast的使用

    AngularJS中的作用域有一个非常有层次和嵌套分明的结构。其中它们都有一个主要的$rootScope(也就说对应的Angular应用或者ng-app)&#xff0c;然后其他所有的作用域部分都是继承自这个$rootScope的&#xff0c;或者说都是嵌套在主作用域下面的。很多时候&#xff0c;你会发现这…...

    2024/4/21 3:53:52
  9. [AngularJS面面观] 10. scope事件机制 - $emit,$broadcast以及事件对象

    在上一篇文章中&#xff0c;介绍了事件机制背后的订阅-发布模式以及angular事件的生命周期。 本文继续介绍和事件机制相关的几个重要组成部分&#xff1a; 1. 事件对象的组成 2. 事件与scope继承树-$emit以及$broadcast 3. 事件的停止传播以及阻止默认行为 事件对象的组成…...

    2024/4/21 3:53:51
  10. angular8.x父子组件传值和方法【不定时更新,实际用到再补充】

    一、父组件向子组件的传入数据 [selected]”tCbCbglpws” 左侧是名称---右侧是数据 <app-child [selected]"tCbCbglpws"></app-child> <!--父组件中子组件引用-->// 父组件ts export class FatherComponent implements OnInit {public tCbCbglpws …...

    2024/4/21 3:53:49
  11. angular4之父子组件之间的传值

    了解Input和Output Input : 将父作用域中的值“输入”到子作用域中&#xff0c;之后子作用域进行相关处理Output &#xff1a; 子作用域触发事件执行响应函数&#xff0c;而响应函数方法体则位于父作用域中&#xff0c;相当于将事件“输出”到父作用域中&#xff0c;在父作用…...

    2024/4/20 16:14:46
  12. angular父子组件的传值,兄弟之间传值

    1.父级向子级传值&#xff0c;不管是属性&#xff0c;方法&#xff0c;还是整个父级对象this,都可以通过类似变量的形式传入&#xff0c;具体如下 <app-detail #detail msg"123"></app-detail> //传入的值不是变量<app-detail #detail [msg]"pa…...

    2024/4/21 3:53:47
  13. angular2 里父子组件传值的坑

    1.如果传的是基本类型的值&#xff0c;子组件里改变该值&#xff0c;父组件无变化 2.如果传的是对象&#xff0c;子组件里改变对象里的变量&#xff0c;父组件会变化 3.如果传的是函数&#xff0c;this不会继续指向父组件对象了&#xff0c;如果需要this指向父组件&#xff0c;…...

    2024/4/21 3:53:46
  14. 记录angular父子组件传值

    Input,Output,eventEmitter 子组件 <app-header > <div (click)"sendPerent"> </div> Output() private outer new eventEmitter();sendPerent(){ this.outer.emit(key,value) }父组件 <app-header (outer)"run"> run(e){cons…...

    2024/4/21 3:53:45
  15. Angular4-父子组件传值@input@output

    父组件传值给子组件 在页面引入input import { Input } from angular/core; 父组件传值给子组件 <app-index [title]"title" [run]"run"></app-index> 子组件使用 Input() title; Input() run;这样就可以直接使用{{title}},和this.run()…...

    2024/4/21 3:53:44
  16. Angular2父子组件之间数据传递:父子组件共享服务通信

    ​父子组件共享同一个服务&#xff0c;利用该服务实现双向通信 首先定义服务&#xff1a; parentService.ts&#xff08;服务&#xff09; import {Injectable} from "angular/core"Injectable()export class ParentService { name: string "小明"; ge…...

    2024/4/21 3:53:43
  17. Angular8--父子组件之间的传值

    目录 一、通过输入型绑定把数据从父组件传到子组件。 二、父组件监听子组件的事件 三、通过 setter 截听输入属性值的变化 四、通过ngOnChanges()来截听输入属性值的变化 五、父组件调用ViewChild() https://angular.cn/guide/component-interaction官方文档 https://blo…...

    2024/4/20 19:59:01
  18. Angular中父子组件双向绑定传值

    下面为大家展示一个较为简单的ng父子组件双向绑定传值&#xff0c;下面是父组件页面 这个页面的大概功能就是父组件(红色)通过输入框输入内容反映到子组件上进行展示,并且进行了投影, 子组件(橙黄色)通过Input输入框输入内容反映到父组件上&#xff0c;并且使用了Output传值给父…...

    2024/4/20 19:58:59
  19. Angular JS 文件上传按钮覆盖问题

    在文件上传中&#xff0c;如果使用<input type"file"> 会出现如图的效果&#xff1a;&#xff0c;按钮上的“选取文件” 字是无法改变的&#xff0c;这样会比较丑&#xff0c;可以选择如下的效果&#xff1a; <div ng-controller"form-ctrl">&…...

    2024/4/20 19:58:58
  20. angularJs 获取上传文件进度

    angular在1.5.5以上的版本中,在$http中也加入了eventHandler和uploadEventHandlers等方法。 发送请求&#xff1a; $http({method:"POST",url:basePath"/roadShow/saveOrUpdate",eventHandlers: {progress: function(c) {console.log(Progress -> c…...

    2024/4/28 17:41:20

最新文章

  1. 二极管钳位型三电平SVPWM(羊角波)闭环系统simulink建模与仿真

    整理了二极管钳位型三电平SVPWM&#xff08;羊角波&#xff09;闭环系统simulink建模与仿真模型&#xff0c;附赠参考资料。 在二极管钳位型三电平SVPWM中&#xff0c;通过控制逆变器的开关器件&#xff08;IGBT&#xff09;的导通和关断&#xff0c;将输入的直流电压转换为三…...

    2024/4/28 21:54:07
  2. 梯度消失和梯度爆炸的一些处理方法

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

    2024/3/20 10:50:27
  3. 自定义OPPO-r9s的kernel内核,并开启安卓支持docker

    0. 版本说明 本文提供了OPPO手机r9s的内核编译方法&#xff0c;并开机支持docker。用的是开源lineage14.1的rom。 我这边基于开源lineage14.1&#xff0c;打了一个docker内核编译镜像(17380582683/r9s)&#xff0c;大家可以在容器里&#xff0c;手动打出完整的rom包zip文件。…...

    2024/4/23 2:13:16
  4. 6.9物联网RK3399项目开发实录-驱动开发之PWM的使用(wulianjishu666)

    嵌入式实战开发例程&#xff0c;珍贵资料&#xff0c;开发必备&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1149x7q_Yg6Zb3HN6gBBAVA?pwdhs8b PWM 使用 前言 AIO-3399J 开发板上有 4 路 PWM 输出&#xff0c;分别为 PWM0 ~ PWM3&#xff0c;4 路 PWM 分别使用在…...

    2024/4/28 2:14:12
  5. 【外汇早评】美通胀数据走低,美元调整

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

    2024/4/28 13:52:11
  6. 【原油贵金属周评】原油多头拥挤,价格调整

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

    2024/4/28 3:28:32
  7. 【外汇周评】靓丽非农不及疲软通胀影响

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

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

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

    2024/4/28 13:51:37
  9. 【外汇早评】日本央行会议纪要不改日元强势

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

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

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

    2024/4/27 14:22:49
  11. 【外汇早评】美欲与伊朗重谈协议

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

    2024/4/28 1:28:33
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

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

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

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

    2024/4/27 17:59:30
  14. 【原油贵金属早评】市场情绪继续恶化,黄金上破

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

    2024/4/25 18:39:16
  15. 【外汇早评】美伊僵持,风险情绪继续升温

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

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

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

    2024/4/26 19:03:37
  17. 氧生福地 玩美北湖(上)——为时光守候两千年

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

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

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

    2024/4/25 18:39:14
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

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

    2024/4/26 23:04:58
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

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

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

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

    2024/4/28 5:48:52
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

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

    2024/4/26 19:46:12
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

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

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

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

    2024/4/27 8:32:30
  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