这篇文章主要围绕什么是AngularJS中的parentValueWatch?和angular$parent展开,旨在为您提供一份详细的参考资料。我们将全面介绍什么是AngularJS中的parent
这篇文章主要围绕什么是AngularJS中的parentValueWatch?和angular $parent展开,旨在为您提供一份详细的参考资料。我们将全面介绍什么是AngularJS中的parentValueWatch?的优缺点,解答angular $parent的相关问题,同时也会为您带来Angular 4.x Forms patchValue and setValue、AngularJs $parse、$eval和$observe、$watch详解、AngularJS $watch 的 Angular 等价物是什么?、AngularJs watch监听input value并请求数据的方法的实用方法。
本文目录一览:- 什么是AngularJS中的parentValueWatch?(angular $parent)
- Angular 4.x Forms patchValue and setValue
- AngularJs $parse、$eval和$observe、$watch详解
- AngularJS $watch 的 Angular 等价物是什么?
- AngularJs watch监听input value并请求数据的方法
什么是AngularJS中的parentValueWatch?(angular $parent)
(AngularJS v1.2.24)
解决方法
考虑简单的指令,
{ restrict:"AE",scope:{ foo:'=' } }
现在让我们说在父作用域中,foo是一个对象.
$parent.$scope.foo = { bar:"zim" }
每个$digest循环,子$scope将需要检查父范围的foo值及其每个属性.
如果foo是一个非常庞大且深度嵌套的对象,这将需要很长时间,因此它需要花费很长时间.
在HTML中,这可能如下所示:
<div parent-directive> <div foo-directive foo=bar></div></div>
一个快速的解决方法是使用ng-init“冻结”值.
<div parent-directive> <div foo-directive ng-init='zug={bar:$parent.foo.bar}' foo=zug></div></div>
现在绑定到新对象的值.你失去了轻松绑定,但获得了性能.
它始终是一种权衡.
Angular 4.x Forms patchValue and setValue
在 Angular 4.x 中有多种方式可以更新表单的值,对于使用响应式表单的场景,我们可以通过框架内部提供的 API ,(如 patchValue 和 setValue )方便地更新表单的值。这篇文章我们将介绍如何使用 patchValue 和 setValue 方法更新表单的值,此外还会进一步介绍它们之间的差异。
Reactive Form Setup
app.module.ts
import { NgModule,CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; import { browserModule } from '@angular/platform-browser'; import { ReactiveFormsModule } from '@angular/forms'; import { AppComponent } from './app.component'; import { EventFormComponent } from './event-form.component'; @NgModule({ imports: [browserModule,ReactiveFormsModule],declarations: [AppComponent,EventFormComponent],bootstrap: [AppComponent],schemas: [CUSTOM_ELEMENTS_SCHEMA] }) export class AppModule { }
app.component.ts
import { Component,OnInit } from '@angular/core'; @Component({ selector: 'exe-app',template: ` <event-form></event-form> `,}) export class AppComponent {}
event-form.component.ts
import { Component,OnInit } from '@angular/core'; import { FormBuilder,FormGroup } from '@angular/forms'; @Component({ selector: 'event-form',template: ` <form novalidate (ngSubmit)="onSubmit(form)" [formGroup]="form"> <div> <label> <span>Full name</span> <input type="text"formControlName="name"> </label> <div formGroupName="event"> <label> <span>Event title</span> <input type="text"formControlName="title"> </label> <label> <span>Event location</span> <input type="text"formControlName="location"> </label> </div> </div> <div> <button type="submit" [disabled]="form.invalid"> Submit </button> </div> </form> `,}) export class EventFormComponent implements OnInit { form: FormGroup; constructor(public fb: FormBuilder) { } ngOnInit() { this.form = this.fb.group({ name: ['',Validators.required],event: this.fb.group({ title: ['',location: ['',Validators.required] }) }); } onSubmit({ value,valid }: { value: any,valid: boolean }) { } }
patchValue
我们先来介绍 patchValue() 方法,然后在介绍 setValue() 方法。使用 patchValue() 方法会比使用 setValue() 方法更好,为什么这么说呢?我们来看一下源码就知道答案了。
// angular2/packages/forms/src/model.ts export class FormGroup extends AbstractControl { ... patchValue( value: {[key: string]: any},{onlySelf,emitEvent}: {onlySelf?: boolean,emitEvent?: boolean} = {}): void { Object.keys(value).forEach(name => { if (this.controls[name]) { this.controls[name].patchValue(value[name],{onlySelf: true,emitEvent}); } }); this.updateValueAndValidity({onlySelf,emitEvent}); } } // 使用示例 const form = new FormGroup({ first: new FormControl(),last: new FormControl() }); console.log(form.value); // {first: null,last: null} form.patchValue({first: 'Nancy'}); console.log(form.value); // {first: 'Nancy',last: null}
从源码中我们可以看出,patchValue() 方法会获取输入参数对象的所有 key 值,然后循环调用内部控件的 patchValue()
方法,具体代码如下:
Object.keys(value).forEach(name => { if (this.controls[name]) { this.controls[name].patchValue(value[name],emitEvent}); } });
首先,Object.keys()
会返回对象 key 值的数组,例如:
const man = {name : 'Semlinker',age: 30}; Object.keys(man); // ['name','age']
此外 this.controls
包含了 FormGroup 对象中的所有 FormControl 控件,我们可以通过 this.controls[name]
方式,访问到 name 对应的控件对象。
现在让我们来回顾一下上面的示例中创建 FormGroup 对象的相关代码:
this.form = this.fb.group({ name: ['',event: this.fb.group({ title: ['',Validators.required] }) });
与之相对应的对象模型如下:
{ name: '',event: { title: '',location: '' } }
因此要更新该模型的值,我们可以利用 FormGroup
对象的 patchValue()
方法:
this.form.patchValue({ name: 'Semlinker',event: { title: 'Angular 4.x\'s Road',location: 'Xiamen' } });
以上代码将会通过循环的方式,更新每个 FormControl
控件。接下来我们看一下 FormControl
中 patchValue() 方法的具体实现:
patchValue(value: any,options: { onlySelf?: boolean,emitEvent?: boolean,emitModelToViewChange?: boolean,emitViewToModelChange?: boolean } = {}): void { this.setValue(value,options); }
忽略所有的函数参数和类型,它所做的就是调用 setValue() 方法,设置控件的值。另外使用 patchValue()
方法有什么好处呢?假设我们使用 firebase
,那么当我们从 API 接口获取数据对象时,对象内部可能会包含 $exists
和 $key
属性。而当我们直接使用返回的数据对象作为参数,直接调用 patchValue() 方法时,不会抛出任何异常:
this.form.patchValue({ $exists: function () {},$key: '-KWihhw-f1kw-ULPG1ei',name: 'Semlinker',location: 'Xiamen' } });
其实没有抛出异常的原因,是因为在 patchValue() 内部循环时,我们有使用 if
语句进行条件判断。那好,现在我们开始来介绍 setValue() 方法。
setValue
首先,我们来看一下 FormGroup 类中的 setValue() 方法的具体实现:
setValue( value: {[key: string]: any},emitEvent}: {onlySelf?: boolean,emitEvent?: boolean} = {}): void { this._checkAllValuesPresent(value); Object.keys(value).forEach(name => { this._throwIfControlMissing(name); this.controls[name].setValue(value[name],emitEvent}); }); this.updateValueAndValidity({onlySelf,emitEvent}); } // 使用示例 const form = new FormGroup({ first: new FormControl(),last: new FormControl() }); console.log(form.value); // {first: null,last: null} form.setValue({first: 'Nancy',last: 'Drew'}); console.log(form.value); // {first: 'Nancy',last: 'Drew'}
跟 patchValue() 方法一样,我们内部也是包含一个 Object.keys()
的循环,但在循环开始之前,我们会先调用 _checkAllValuesPresent()
方法,对输入值进行校验。 另外 _checkAllValuesPresent()
方法的具体实现如下:
_checkAllValuesPresent(value: any): void { this._forEachChild((control: AbstractControl,name: string) => { if (value[name] === undefined) { throw new Error(`Must supply a value for form control with name: '${name}'.`); } }); }
该方法内部通过 _forEachChild()
遍历内部的 FormControl 控件,来确保我们在调用 setValue()
方法时,设置的参数对象中,会包含所有控件的配置信息。如果 name
对应的配置信息不存在,则会抛出异常。
在 _checkAllValuesPresent()
验证通过后,Angular 会进入 Object.keys()
循环,此外在调用 setValue()
方法前,还会优先调用 _throwIfControlMissing()
判断控件是否存在,该方法的实现如下:
_throwIfControlMissing(name: string): void { if (!Object.keys(this.controls).length) { throw new Error(` There are no form controls registered with this group yet. If you're using ngModel,you may want to check next tick (e.g. use setTimeout). `); } if (!this.controls[name]) { throw new Error(`Cannot find form control with name: ${name}.`); } }
上面代码首先判断 this.controls
是否存在,如果存在进一步判断 name
对应的 FormControl
控件是否存在。当 _throwIfControlMissing()
验证通过后,才会最终调用 FormControl
控件的 setValue() 方法:
this.controls[name].setValue(value[name],emitEvent});
我们来看一下 FormControl
类中,setValue() 方法的具体实现:
setValue(value: any,emitEvent,emitModelToViewChange,emitViewToModelChange}: { onlySelf?: boolean,emitViewToModelChange?: boolean } = {}): void { this._value = value; if (this._onChange.length && emitModelToViewChange !== false) { this._onChange.forEach((changeFn) => changeFn(this._value,emitViewToModelChange !== false)); } this.updateValueAndValidity({onlySelf,emitEvent}); }
该方法的第一个参数,就是我们要设置的值,第二个参数是一个对象:
onlySelf:若该值为 true,当控件的值发生变化后,只会影响当前控件的验证状态,而不会影响到它的父组件。默认值是 false。
emitEvent:若该值为 true,当控件的值发生变化后,将会触发
valueChanges
事件。默认值是 trueemitModelToViewChange:若该值为 true,当控件的值发生变化时,将会把新值通过
onChange
事件通知视图层。若未指定emitModelToViewChange
的值,这是默认的行为。emitViewToModelChange:若该值为 true,
ngModelChange
事件将会被触发,用于更新模型。若未指定emitViewToModelChange
的值,这是默认的行为。
其实仅仅通过上面的代码,我们还是没完全搞清楚 setValue()
方法内部真正执行流程。如我们不知道如何注册 changeFn 函数和 updateValueAndValidity()
方法的内部处理逻辑,接下来我们先来看一下如何注册 changeFn 函数:
export class FormControl extends AbstractControl { /** @internal */ _onChange: Function[] = []; ... /** * Register a listener for change events. */ registerOnChange(fn: Function): void { this._onChange.push(fn); } }
现在我们来回顾一下 setValue() 的相关知识点。对于 FormGroup
对象,我们可以通过 setValue()
方法更新表单的值,具体使用示例如下:
this.form.setValue({ name: 'Semlinker',location: 'Xiamen' } });
以上代码成功运行后,我们就能成功更新表单的值。但如果我们使用下面的方式,就会抛出异常:
this.form.setValue({ $exists: function () {},location: 'Xiamen' } });
最后我们来总结一下 FormGroup
和 FormControl
类中 patchValue() 与 setValue() 的区别。
patchValue vs setValue
FormControl
patchValue
patchValue(value: any,options); }
setValue
setValue(value: any,emitViewToModelChange}: { onlySelf?: boolean,emitViewToModelChange?: boolean } = {}): void { this._value = value; if (this._onChange.length && emitModelToViewChange !== false) { this._onChange.forEach((changeFn) => changeFn(this._value,emitEvent}); }
通过源码我们发现对于 FormControl
对象来说,patchValue() 和 setValue() 这两个方法是等价的。此外 setValue() 方法中做了三件事:
更新控件当前值
判断是否注册
onChange
事件,若有则循环调用已注册的changeFn
函数。重新计算控件的值和验证状态
FormGroup
patchValue
patchValue( value: {[key: string]: any},emitEvent?: boolean} = {}): void { Object.keys(value).forEach(name => { if (this.controls[name]) { this.controls[name].patchValue(value[name],emitEvent}); } }); this.updateValueAndValidity({onlySelf,emitEvent}); }
setValue
setValue( value: {[key: string]: any},emitEvent?: boolean} = {}): void { this._checkAllValuesPresent(value); // 判断的是否为所有控件都设置更新值 Object.keys(value).forEach(name => { this._throwIfControlMissing(name); // 判断控件是否存在 this.controls[name].setValue(value[name],emitEvent}); }); this.updateValueAndValidity({onlySelf,emitEvent}); // 重新计算控件的值和验证状态 }
通过查看源码,我们发现 setValue() 方法相比 patchValue() 会更严格,会执行多个判断:
判断的是否为所有控件都设置更新值
判断控件是否存在
而 patchValue() 方法,会先使用 this.controls[name]
进行过滤,只更新参数 value
中设定控件的值。
我有话说
为什么 FormControl 中 patchValue() 和 setValue() 是等价的,还需要两个方法?
因为 FormControl 继承于 AbstractControl 抽象类:
export class FormControl extends AbstractControl { }
AbstractControl 抽象类中定义了 patchValue() 和 setValue() 两个抽象方法,需要由子类实现:
/** * Sets the value of the control. Abstract method (implemented in sub-classes). */ abstract setValue(value: any,options?: Object): void; /** * Patches the value of the control. Abstract method (implemented in sub-classes). */ abstract patchValue(value: any,options?: Object): void;
创建 FormControl 控件有哪些常见的方式?
方式一
const ctrl = new FormControl('some value'); console.log(ctrl.value); // 'some value'
方式二
const ctrl = new FormControl({ value: 'n/a',disabled: true }); console.log(ctrl.value); // 'n/a' console.log(ctrl.status); // disABLED
若没有设置 disabled 属性,即:
const ctrl = new FormControl({ value: 'n/a'}); console.log(ctrl.value); // Object {value: "n/a"} console.log(ctrl.status); // VALID
为什么呢?因为内部在初始设置控件状态时,会对传入的 formState
参数进行判断:
FormControl 构造函数
constructor( formState: any = null,validator: ValidatorFn|ValidatorFn[] = null,asyncValidator: AsyncValidatorFn|AsyncValidatorFn[] = null) { ... this._applyFormState(formState); ... }
_applyFormState() 方法
private _applyFormState(formState: any) { if (this._isBoxedValue(formState)) { this._value = formState.value; formState.disabled ? this.disable({onlySelf: true,emitEvent: false}) : this.enable({onlySelf: true,emitEvent: false}); } else { this._value = formState; } }
_isBoxedValue() 方法
_isBoxedValue(formState: any): boolean { return typeof formState === 'object' && formState !== null && Object.keys(formState).length === 2 && 'value' in formState && 'disabled' in formState; }
方式三
const ctrl = new FormControl('',Validators.required); console.log(ctrl.value); // '' console.log(ctrl.status); //INVALID
创建 FormGroup 对象有哪些常见的方式?
方式一
const form = new FormGroup({ first: new FormControl('Nancy',Validators.minLength(2)),last: new FormControl('Drew'),}); console.log(form.value); // Object {first: "Nancy",last: "Drew"} console.log(form.status); // 'VALID'
方式二
const form = new FormGroup({ password: new FormControl('',passwordConfirm: new FormControl('',},passwordMatchValidator); function passwordMatchValidator(g: FormGroup) { return g.get('password').value === g.get('passwordConfirm').value ? null : { 'mismatch': true }; }
上面代码中,我们在创建 FormGroup 对象时,同时设置了同步验证器 (validator),用于校验 password (密码) 和 passwordConfirm (确认密码) 的值是否匹配。
参考资源
https://toddmotto.com/angular...
AngularJs $parse、$eval和$observe、$watch详解
$parse和$eval
$parse和$eval这两个函数都可以解析表达式的值.
它们的区别在于$parse是一个服务,可以注入使用. $eval是scope对象上的一个方法,我们只能在能访问scope的场景下使用它.
getter(context); //John Doe
setter(context,'new name');
getter(context); //new name
getter(context,locals); //Doe John
$parse服务接收一个表达式作为参数并返回一个函数. 这个函数可以被调用,其中的参数是一个context对象,通常来说是作用域. 另外,这个函数有一个assign属性. 它也是一个函数,可以用来在给定的上下文中改变这个表达式的值. 最后一行代码演示了如何使用locals来覆盖context对象.
$eval用起来要简单很多,因为它的上下文已经被指定为scope对象.
关于$parse和$eval之间的关系,我们能从Angular源码中看出来,可以说$eval是为了让$parse在scope中使用更方便的语法糖.
$eval还有个同胞兄弟,$evalAsync,它并不会立刻计算表达式的值,而是将表达式缓存起来,等到下一次$digest ( 脏检查 ) 的时候执行. 以获取更好的性能.
$observe和$watch
$observe和$watch都可以监听表达式值的变化. 但有显著的不同. $observe是angular指令中link函数第三个参数 ( attrs ) 的一个方法. 只能在指令的link函数中使用它. 它是通过$evalAsync函数实现监控的.
$watch是scope对象上的一个方法,watch表达式很灵活,可以是一个函数,可以是scope上的属性,也可以是一个字符串形式的表达式. 监听scope上的属性名或表达式的时候,会利用$parse服务将表达式转换成一个函数,这个函数会在$digest中被调用. $watch的第三个参数"objectEquality",指定比较对象的方式,如果为true,则用angular.equals,否则直接比较引用. 默认为false.
当你需要监听一个包含"{{}}"的DOM属性时,使用$observe,如果用$watch,只能得到undefined. 反之,就用$watch. 如果用$observe,只能得到一个固定的字符串.
有一个特殊的情况,当你的指令使用了独立的作用域 ( scope:{} ),那些应用了"@"语法的DOM属性,即使包含"{{ }}",也可以被$watch.
因为@前缀标识符,它的实现是通过$observe去监听DOM属性的变化,这就是为什么@attr的值只能是字符串或是"{{}}",而不能是scope上的属性,所以最终$watch看到的表达式是没有"{{ }}"的. 而"="和"&"则是基于$watch实现. 所以=attr,&attr的值不能包含"{{ }}",但可以直接使用scope上的属性.
$watchGroup和$watchCollection
$watchGroup是用来监听一组表达式. 数组中任意表达式的变化都会触发监听函数.
$watchCollection
用来监听一个对象(包括数组),当这个对象的任意属性发生变化时,触发监听函数. 和$watch一样,第一次参数可以是一个返回一个对象的函数.$scope.$watchCollection('names',function (newVal,oldVal) {
$scope.dataCount = newVal.length;
});
$timeout(function(){
$scope.names.pop();
},2000);
$observe,$watch,$watchGroup,$watchCollection都返回一个移除监听的函数. 当需要取消监听的时候,直接调用.
以上就是对AngularJs $parse、$eval和$observe、$watch的知识详解,谢谢大家对本站的支持!
总结
以上是小编为你收集整理的AngularJs $parse、$eval和$observe、$watch详解全部内容。
如果觉得小编网站内容还不错,欢迎将小编网站推荐给好友。
AngularJS $watch 的 Angular 等价物是什么?
在 AngularJS 中,您可以$watch
使用$scope
. 在 Angular 中观察变量变化(例如,在组件变量中)的等价物是什么?
AngularJs watch监听input value并请求数据的方法
本文主要和大家分享AngularJs watch监听input value并请求数据的方法,希望能帮助到大家。
1、html input菜单和隐藏的控件
<p></p> <p> <p><span>*</span> 投放产品</p> <input name="app" ng-model="chance.appName" type="text"placeholder="请填写产品名称"> </p> <p ng-if="ishaveName==true"> 该应用已被商务"{{haveName}}"录入国,可保持沟通 </p>
2、watch开始使用
1、JS 必须初始化$watch控件 ,ng-model="chance.appName"
$scope.chance={ appName:null};
2、开始watch代码
1、一定注意是$watch,前面有美元符。里面是变量,变量前面没有$scope
2、在没有获取到值的情况下,提示控件,应该不显示。所以设置了变量$scope.ishaveName= false,注意JS头部初始化为false,只有当true的时候才会显示提示控件
3、在进入$watch的时候,就将上面2中的$scope.ishaveName设置为false
$scope.chance={ appName:null};$scope.ishaveName= false;
$scope.$watch('chance.appName',function () { $scope.ishaveName= false; if($scope.chance.appName!=null&&$scope.chance.appName!=undefined&&$scope.chance.appName!=''){ $http.get(ctx+'/chance/findAdminByAppName?appName='+$scope.chance.appName) .success(function (data,status) { if(data.result!=null){ $scope.haveName= data.result.name; $scope.ishaveName= true; } }) } });
3、后端代码
1、controller
@Controller@RequestMapping("chance")@ResourceFolder(folder = "module/chance/")public class ChanceController { @GetMapping("findAdminByAppName") @ResponseBody public ResponseBean findAdminByAppName(String appName){ try { return ResponseBean.buildSuccess(customerChanceService.findAdminByAppName(appName)); }catch (AppException e){ return ResponseBean.buildFailure(e.getMessage()); } } }
2、service,当如果为登录人员自己设置的产品的时候,不需要提示自己,尽可能的提示其他人(傻子知道)。
//根据产品名字 ,查看是否有商务经理已经添加了该产品,选则一个不是自己的产品经理@Overridepublic SysAdminUser findAdminByAppName(String appName) { if("".equals(appName)||appName==null){ return null; } Long adminId = CasConfig.RemoteUserUtil.getRemoteUserId(); List<SysAdminUser> sysAdminUsers = customerMapper.findAdminByAppName(appName); //有可能会出现多个人,那么首先如果是自己创建的话,就排除掉 if(sysAdminUsers.size()>0){ if(adminId.compareTo(sysAdminUsers.get(0).getId())==0){ sysAdminUsers.remove(0); } if(sysAdminUsers.size()>0){ return sysAdminUsers.get(0); } } return null; }
3、mapper
1、首先应该明确,我们这里获取的是管理人,所以要以管理人为核心。
<!--根据产品,名字,看出是否已经有商务经理在维护了,根据产品名字 ,查看是否有商务经理已经添加了该产品,如果前台传入的参数我空,则通过java判断,不能进入本sql,`否则会出错`--> <select id="findAdminByAppName" resultType="com.duodian.admore.entity.db.admin.SysAdminUser"> SELECT s.* FROM `sys_admin_user` s left JOIN crm_customer_chance c on c.adminId = s.id where c.isVisible = 1 and c.adminId is not NULL <if test="_parameter != null and _parameter!= ''"> and c.appName = #{_parameter} </if> GROUP by id </select> </mapper>
相关推荐:
.vue文件中监听input输入事件oninput详解
以上就是AngularJs watch监听input value并请求数据的方法的详细内容,更多请关注php中文网其它相关文章!
我们今天的关于什么是AngularJS中的parentValueWatch?和angular $parent的分享就到这里,谢谢您的阅读,如果想了解更多关于Angular 4.x Forms patchValue and setValue、AngularJs $parse、$eval和$observe、$watch详解、AngularJS $watch 的 Angular 等价物是什么?、AngularJs watch监听input value并请求数据的方法的相关信息,可以在本站进行搜索。
本文标签: