天道酬勤,学无止境

如何观察 ng-content 中输入元素的变化(How to observe input element changes in ng-content)

问题

当子组件观察到输入变化时如何调用父组件的功能?

下面是 HTML 结构。

# app.comopnent.html
<form>
  <textbox>
    <input type="text">
  </textbox>
</form>

# textbox.component.html
<div class="textbox-wrapper">
  <ng-content>
</div>

限制如下。

  • TextboxComponent 有ng-content并且需要将input元素投影到它。
  • input元素被输入时,在 TextboxComponent 中发出一个事件。
  • 不想让input元素具有更多属性,例如<input type="text" (input)="event()">

我正在编写代码,但找不到解决方案...

# input.directive.ts
@Directive({ selector: 'input', ... })
export class InputDirective {
  ngOnChanges(): void {
    // ngOnChanges() can observe only properties defined from @Input Decorator...
  }
}

# textbox.component.ts
@Component({ selector: 'textbox', ... })
export class TextboxComponent {
  @ContentChildren(InputDirective) inputs: QueryList<InputDirective>;
  ngAfterContentInit(): void {
    this.inputs.changes.subscribe((): void => {
      // QueryList has a changes property, it can observe changes when the component add/remove.
      // But cannot observe input changes...
    });
  }
}
回答1

input事件冒泡,可以在父组件上监听

<div class="textbox-wrapper" (input)="inputChanged($event)">
  <ng-content></ng-content>
</div> 

Plunker 示例

回答2

ngAfterViewInit() ,找到感兴趣的元素,然后强制添加事件侦听器。 下面的代码只假设一个输入:

@Component({
    selector: 'textbox',
    template: `<h3>textbox value: {{inputValue}}</h3>
      <div class="textbox-wrapper">
        <ng-content></ng-content>
      </div>`,
})
export class TextboxComp {
  inputValue:string;
  removeListenerFunc: Function;
  constructor(private _elRef:ElementRef, private _renderer:Renderer) {}
  ngAfterContentInit() {
    let inputElement = this._elRef.nativeElement.querySelector('input');
    this.removeListenerFunc = this._renderer.listen(
      inputElement, 'input', 
      event => this.inputValue = event.target.value)
  }
  ngOnDestroy() {
    this.removeListenerFunc();
  }
}

普朗克

与 Günter 的声明式方法相反,这个答案本质上是一种命令式方法。 如果您有多个输入,这种方法可能更容易扩展。


似乎没有一种方法可以使用@ContentChild() (或@ContentChildren() )在用户提供的模板(即 ng-content 内容)中查找 DOM 元素......类似于@ContentChild(input)似乎不存在。 因此我使用querySelector()的原因。

在这篇博客文章中,http://angularjs.blogspot.co.at/2016/04/5-rookie-mistakes-to-avoid-with-angular.html,Kara 建议使用input选择器定义指令(比如 InputItem)然后使用@ContentChildren(InputItem) inputs: QueryList<InputItem>; . 然后我们不需要使用querySelector() 。 但是,我并不特别喜欢这种方法,因为 TextboxComponent 的用户必须以某种方式知道将 InputItem 也包含在directives数组中(我想一些组件文档可以解决这个问题,但我仍然不是粉丝)。 这是这种方法的一个plunker。

回答3

您可以使用以下场景,其中输入指令具有主机绑定属性

input.directive.ts

import {Directive, HostBinding} from 'angular2/core';
import {Observer} from 'rxjs/Observer';
import {Observable} from 'rxjs/Observable';

@Directive({
  selector: 'input',
  host: {'(input)': 'onInput($event)'}
})
export class InputDirective {
  inputChange$: Observable<string>;
  private _observer: Observer<any>;
  constructor() {
    this.inputChange$ = new Observable(observer => this._observer = observer);
  }
  onInput(event) {
    this._observer.next(event.target.value);
  }
}

然后您的 TextBoxComponent 将订阅上面在 InputDirective 类中定义的 Observable 对象。

textbox.component.ts

import {Component, ContentChildren,QueryList} from 'angular2/core';
import {InputDirective} from './input.directive';
@Component({
  selector: 'textbox',
  template: `
    <div class="textbox-wrapper">
      <ng-content></ng-content>
      <div *ngFor="#change of changes">
        {{change}}
      </div>
    </div>
  `
})
export class TextboxComponent {
  private changes: Array<string> = [];
  @ContentChildren(InputDirective) inputs: QueryList<InputDirective>;

  onChange(value, index) {
    this.changes.push(`input${index}: ${value}`);
  }

  ngAfterContentInit(): void {
    this.inputs.toArray().forEach((input, index) => {
      input.inputChange$.subscribe(value => this.onChange(value, index + 1));
    });
  }
}

这是 plunker 示例

回答4

您可以使用 Angular CDK 观察者 https://material.angular.io/cdk/observers/api

在你的模块中导入这个模块

import { ObserversModule } from '@angular/cdk/observers';

然后在ng-content's父元素中使用

<div class="projected-content-wrapper (cdkObserveContent)="contentChanged()">
 <ng-content></ng-content>
</div>
回答5

您可以在输入元素上添加一个 ngControl。

<form>
  <textbox>
    <input ngControl="test"/>
  </textbox>
</form>

这样你就可以在 ContentChild 中使用 NgControl。 它限制了对 valueChanges 属性的访问,您可以在其上注册以接收更新通知。

@Component({ selector: 'textbox', ... })
export class TextboxComponent {
  @ContentChild(NgControl) input: NgControl;
  ngAfterContentInit(): void {
    this.input.control.valueChanges.subscribe((): void => {
      (...)
    });
  }
}
标签

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • Angular2+ 面试题集锦
    1. 生命周期钩子 生命周期的顺序,见下图: ngOnChanges:当组件数据绑定的输入属性发生变化是触发,该方法接收一个SimpleChanges对象,包括当前值和上一个属性值。首次调用一定发生在ngOnInit前,值得注意的是该方法仅限于对象的引用发生变化时才会触发。ngOninit:初始化指令或组件,在angular第一次显示展示组件的绑定属性后调用,该方法只会调用一次ngDocheck:检测 ngAfterContentInit:当把内容投影进组件之后调用,第一次调用ngDocheck()之后调用,只调用一次,只适用于组件 ngAfterContentChecked:每次完成被投影组件内容的变更检测之后调用,只适用于组件 ngAfterViewInit:在angular初始化组件及其子组件的视图之后调用,只调用一次,只适用于组件 ngAfterViewChecked:每次做完组件视图和子视图的变更检测之后调用,只适用于组件 ngOnDestroy:在angular每次销毁组件或指令之前调用,通常用于移除事件监听,退订可观察对象。 详细案例分析见:https://blog.csdn.net/it_rod/article/details/79433887 2. 指令分类 组件:用于构建UI组件,继承于Directive类 属性指令:用于改变组件的外观或行为
  • Angualr入门第一部分
    Angualr 一、目录结构 “assets”: [ 存放静态资源目录 “src/favicon.ico”,“src/assets”] “index”: “src/index.html”, 单页面,打包编译结果出口 “main”: “src/main.ts”, 整个模块化系统启动的入口,其作用为:加载根模块,启动执行模块系统,为整个系统的程序入口。 package.json:项目包说明文件,文件中有scripts字段,左边是简易命令,右边是等效的执行程序,即在终端输入 npm run start 和 ng serve均会执行编译程序: "scripts": { "ng": "ng", 运行查看Angular CLI脚手架工具使用帮助 "start": "ng serve", 运行开发模式 "build": "ng build", 运行项目打包构建(用于发布到生成环境) "test": "ng test", 运行karma单元测试 "lint": "ng lint", 运行TypeScripts代码校验 "e2e": "ng e2e", 运行protractor端到端测试 "npm run pc:start": 启动pc-fe项目 } 二、组件 Component(组件)是整个框架的核心 ,“组件化”的可以用来解耦、复用。 app.component.ts就是一个组件
  • How to Implement DOM Data Binding in JavaScript(How to Implement DOM Data Binding in JavaScript)
    问题 请将此问题视为严格的教育意义。 我仍然有兴趣听到新的答案和想法来实现这一目标 tl; dr 如何使用JavaScript实现双向数据绑定? 数据绑定到DOM 通过将数据绑定到DOM,我的意思是例如拥有a具有属性b的JavaScript对象。 然后具有<input> DOM元素(例如),当DOM元素的变化, a变化,反之亦然(即,我的意思是双向数据绑定)。 这是AngularJS的示意图: 所以基本上我的JavaScript类似于: var a = {b:3}; 然后是一个输入(或其他形式)元素,例如: <input type='text' value=''> 我希望输入的值是ab的值(例如),并且当输入文本更改时,我也希望ab也更改。 当JavaScript中的ab更改时,输入也会更改。 问题 用普通的JavaScript可以完成这些工作的一些基本技术是什么? 具体来说,我想提供一个很好的答案: 绑定如何作用于对象? 如何聆听表格中的更改可能会起作用? 是否可以通过简单的方式仅在模板级别修改HTML? 我不想在HTML文档本身中跟踪绑定,而仅在JavaScript中跟踪(带有DOM事件,而JavaScript始终引用所使用的DOM元素)。 我尝试了什么? 我是Mustache的忠实粉丝,所以我尝试使用它进行模板制作。 但是,由于Mustache将HTML作为字符串处理
  • 如何让 MutationObserver 工作不止一次?(How do I make a MutationObserver work more then once?)
    问题 我使用 MutationObserver,所以我可以让 div 对变化做出反应。 当它将更改更改为显示在 div 正下方时,它只运行一次。 如果我键入一些内容来划分输入 div,则只显示第一个字符。 我在 MDN 上找到了这个 “向元素添加观察者就像 addEventListener,如果您多次观察该元素,则没有任何区别。这意味着如果您观察一个元素两次,则观察回调不会触发两次,您也不必运行 disconnect( ) 两次。换句话说,一旦观察到一个元素,用同一个观察者实例再次观察它就什么都不做。但是如果回调对象不同,它当然会向它添加另一个观察者。” 但是我不确定如何解决这个问题。 我尝试在第一个观察者的回调中创建一个新的观察者,希望它能创建一个观察者链,但这不起作用。 其他人是如何解决这个问题的? <div contenteditable="true" class="input"></div> <div class="display"></div> <script> let input= document.getElementsByClassName("input")[0]; let display= document.getElementsByClassName("display")[0]; let config={attributes:true, childList
  • 如何观察DOM的变化AngularJS(How to watch the DOM for changes AngularJS)
    问题 这似乎是一个愚蠢的问题,但是我需要知道如何观察页面的整个DOM并在页面发生任何变化时重新对其进行编译。 本质上,这是AngularJS在默认情况下通过使用数据绑定来执行的操作,但是我需要在DOM中的任何内容发生更改时(不仅是绑定)进行更改。 之所以这样,是因为我有一个完全用HTML,Javascript和PHP构建的应用程序。 它是一个单页应用程序,具有一个主页,并将PHP注入该页面中的DIV包装器中。 我想对其进行一些修改,但要使我的代码与原始代码完全分开。 为此,我需要能够在每次注入具有自己的DOM结构的新PHP文件时重新编译DOM。 到目前为止,我似乎没有用。 app.directive("watch", function () { return function (scope, element, attr) { scope.$watch("watch", function(oldValue, newValue) { if(newValue) { console.log("there is a new value"); console.log("the new value is " + newValue); } }); } }); 我在<body>标签中添加了watch属性,但它似乎不起作用,当dom更改时,没有任何记录。 最终,我想用$
  • 如何在javascript中实现观察者模式?(how to implement observer pattern in javascript?)
    问题 嗨,我很想在 JavaScript 中实现观察者模式: 我的 index.js : $(document).ready(function () { var ironMan = new Movie(); ironMan.setTitle('IronMan'); ironMan.setRating('R'); ironMan.setId(1); // ironMan.setCast(['Robert Downey Jr.', 'Jeff Bridges', 'Gwyneth Paltrow']); var terminator = new Movie(); terminator.setTitle('Terminator'); terminator.setRating('P'); terminator.setId(2); console.log(ironMan.toString()); console.log(terminator.toString()); ironMan.play(); ironMan.stop(); ironMan.download(); ironMan.share('V. Rivas'); console.log(ironMan.getCast()[0]); }); 我的电影: var title; var rating; var id; var
  • 如何观察“searchTerm”输入字段的值变化?(How to have the `searchTerm` input field being observed for its value change?)
    问题 我有两个可以正常工作的观察: @ViewChild(MatPaginator) paginator: MatPaginator; @ViewChild(MatSort) sort: MatSort; ngOnInit() { ... merge(this.sort.sortChange, this.paginator.page) .pipe( startWith({}), switchMap(() => { return this.getUsers(this.sort.active, this.sort.direction, this.paginator.pageIndex); }), map(userApi => { 这允许在更新排序或分页时调用getUsers服务方法。 现在,我还想在输入搜索词时调用此服务方法: @ViewChild(String) searchTerm: string; @ViewChild(MatPaginator) paginator: MatPaginator; @ViewChild(MatSort) sort: MatSort; ngOnInit() { ... merge(this.searchTerm.length, this.sort.sortChange, this.paginator.page) .pipe( startWith({}
  • Angular 开发
    Angular 企业实战开发 1. 概述 Angular 是一个使用 HTML、CSS、TypeScript 构建客户端应用的框架,用来构建单页应用程序。 Angular 是一个重量级的框架,内部集成了大量开箱即用的功能模块。 Angular 为大型应用开发而设计,提供了干净且松耦合的代码组织方式,使应用程序整洁更易于维护。 Angular Angular 中文 Angular CLI 2. 架构预览 2.1 模块 Angular 应用是由一个个模块组成的,此模块指的不是ESModule,而是 NgModule 即 Angular 模块。 NgModule 是一组相关功能的集合,专注于某个应用领域,可以将组件和一组相关代码关联起来,是应用组织代码结构的一种方式。 在 Angular 应用中至少要有一个根模块,用于启动应用程序。 NgModule 可以从其它 NgModule 中导入功能,前提是目标 NgModule 导出了该功能。 NgModule 是由 NgModule 装饰器函数装饰的类。 import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; @NgModule({ imports: [ BrowserModule ] })
  • 如何检测DIV的尺寸变化?(How to detect DIV's dimension changed?)
    问题 我有以下示例html,有一个DIV,其宽度为100%。 它包含一些元素。 在执行窗口调整大小时,内部元素可能会重新放置,并且div的尺寸可能会更改。 我问是否有可能挂钩div的尺寸更改事件? 以及如何做到这一点? 我目前将回调函数绑定到目标DIV上的jQuery resize事件,但是,没有控制台日志输出,请参见以下内容: <html> <head> <script type="text/javascript" language="javascript" src="http://code.jquery.com/jquery-1.6.1.min.js"></script> <script type="text/javascript" language="javascript"> $('#test_div').bind('resize', function(){ console.log('resized'); }); </script> </head> <body> <div id="test_div" style="width: 100%; min-height: 30px; border: 1px dashed pink;"> <input type="button" value="button 1" /> <input type="button" value="button
  • 聚合物:如何观察变化特性(Polymer: How to watch for change in <content> properties)
    问题 我刚刚开始学习聚合物。 这是我的聚合物元素的通用版本: <polymer-element name="my-element"> <template> <style> :host { position:absolute; width: 200px; height: 100px; background-color: green; } </style> <p>my element</p> <content id="first-in"></content> <content id="second-in"></content> </template> <script> Polymer('my-element', { domReady: function() { alert(this.children[0].getAttribute('title')); //this returns the value I want to observe } }); </script> <polymer-element> 内容标签都填充了另一个自定义元素(再次稍微简化): <polymer-element name="in-element" attributes="title"> <template> <style> ... </style> <p>{{title}}</p> </template>
  • 从DOM中删除并再次插入后如何更新聚合物元素绑定(How to update polymer element bindings after it was removed from DOM and inserted again)
    问题 假设我们有容器聚合物元素和另一个虚拟聚合物元素。 容器聚合物元素具有用于插入另一种聚合物的 div 块。 container_polymer.html <polymer-element name='container-polymer'> <template> <div id="container"> </div> <button on-click="{{first}}">show first</button> <button on-click="{{firstPrepared}}">show first prepared</button> <button on-click="{{second}}">show second</button> </template> <script type="application/dart" src="container_polymer.dart"> </script> </polymer-element> 插入虚拟聚合物有三个按钮: 第一个按钮将第一个虚拟聚合物插入容器。 第二个按钮也插入第一个虚拟聚合物,并在该聚合物上调用prepareElement() 。 第三个按钮将第二个虚拟聚合物插入容器 container_polymer.dart import 'package:polymer/polymer.dart'; import
  • Vue原理深度剖析
    一、Vue基础语法 Vue.js基础结构 使用el方式: 使用render函数方式: Vue生命周期 Vue.js语法和概念 插值表达式 插值表达式相当于一个占位符,只会替换掉其中的占位置的内容。 v-text只能显示Vue对象传递过来的数据,会替换掉节点里已有的内容。 插值表达式和v-text不能够解析html标签,v-html能够解析html标签。 结论: 如果只是单独展示Vue对象里的数据,建议使用“v-text”指令。如果要同时展示用户前台数据,那么就需要用插值表达式,但是不要忘记和“v-cloak”属性一起使用(同时需要设置样式[v-cloak]{display:none;})。如果Vue对象传递过来的数据含有HTML标签,则使用v-html 指令 VUE提供的14个指令: v-model :双向数据绑定,表单元素常用 input select radio checkbox textarea 等,v-model有三个修饰符,例如input元素 v-model.trim去掉输入值的前后空格和v-model.number,将输入的字符串转换为number,v-model.lazy 输入的数据不再实时更新,而是数据失去焦点的时候再更新输入的数据v-show: 元素的显示和隐藏,频繁操作元素的显示和隐藏,就用v-show ,原理是操作的dom 的css样式
  • Polymer 1.0 'array-style' 路径访问器,替代表达式中的括号表示法(Polymer 1.0 'array-style' path accessors, alternative to bracket notation in expressions)
    问题 Polymer 1.0 文档指出: 路径语法不支持数组样式的访问器(例如 users[0].name)。 但是,您可以直接在路径 (users.0.name) 中包含索引。 如何在动态设置路径时解决这个问题,并使用 Polymer 0.5 获得与以下示例相同的行为? 这特别是在为对象定义的模型生成表单的上下文中。 <template repeat="{{row in fieldset.rows}}"> <div layout horizontal flex> <template repeat="{{field in row}}" flex> <paper-field field="{{model.fields[field]}}" value="{{obj[field]}}"> </paper-field> </template> </div> </template> 编辑: 根据 https://github.com/Polymer/polymer/issues/1504: 没有近期计划来支持这一点。 Polymer 0.5 有一个用于绑定的复杂表达式解析器,为了简单和性能,我们将其删除。 您今天可以使用替代模式来实现类似的结果,只是需要您更加明确。 实现双向数据绑定的替代模式仍不清楚。 回答1 是的,Polymer 1.0 确实不再支持绑定表达式中的myObject[key
  • Angular快速上手指南
    angular快速上手指南 angular脚手架下载以及angular项目的新建angular脚手架安装命令angular创建项目命令启动angular项目 angular中的目录结构以及核心文件目录结构核心文件如何在angular中创建组件如何使用组件 Angular基本操作angular中定义属性angular中的数据绑定angular中的属性绑定将文本解析成htmlangular中的数据循环angular中的条件渲染ngswitch的使用动态绑定Class及Styleangular中的管道angular中的事件绑定双向数据绑定 angular中的服务angular中的dom操作通过原生JavaScript直接操作dom通过ViewChild angular组件之间的通信父组件向子组件传递数据父组件向子组件传递方法父组件把自己传递给子组件子组件向父组件传递参数子组件通过output+eventEmit的方法向父组件广播数据。非父子组件之间传递参数 angular组件生命周期及执行顺序组件类的构造函数(constructor)ngOnInitngOnChangesngOnDestoryngDoCheckngAfterContentInitngAfterContentCheckedngAfterViewInitngAfterViewChecked angular中的rx
  • 更新扩展程序中可观察到的淘汰赛js时如何保留光标位置(How To Retain Cursor Position When Updating A Knockout js Observable In An Extender)
    问题 目标是在输入时将用户输入转换为大写。 我正在使用以下扩展程序: ko.extenders.uppercase = function (target, option) { target.subscribe(function (newValue) { target(newValue.toUpperCase()); }); return target; }; 可以将此扩展程序添加到绑定到HTML文本框的Observable: self.userField = ko.observable(product.userField || "").extend({ uppercase: true }); 这很好用。 将绑定到可观察对象的文本转换为大写。 当用户在一个空白字段中键入文本或将其添加到现有文本的末尾时,该文本将转换为大写字母。 到现在为止还挺好! 现在,当用户要插入文本时,可以使用光标键或鼠标将光标置于插入点,然后输入新文本,字符以大写形式插入,但是光标位置现在跳至文本的末尾,因为底层可观察对象已更新。 在仍将用户输入转换为大写的同时,如何保留光标位置? 更新1: 我创建了一个自定义绑定,以便可以访问该元素并获取并设置光标位置。 我试图利用现有的value约束优势。 我正在使用内置的ko.selectExtensions.writeValue函数。 这对于我的应用程序可能已经足够好了
  • 如何使用 Swift 和 KVO 观察单个数组元素的变化(更新)?(How to observe individual array element changes (update) with Swift and KVO?)
    问题 我需要订阅/取消订阅数组的单个元素吗? 我想单独更新每个表视图单元格以反映后备数组中的更改。 我所说的更改不是追加/删除操作,而是更新数组对象的属性。 我希望我能够解释我想要实现的目标。 谢谢 回答1 要使用 KVO,请使用dynamic属性声明模型对象: class Foo: NSObject { @objc dynamic var bar: String // in Swift 3, `@objc` is not necessary; in Swift 4 we must make this explicit init(bar: String) { self.bar = bar super.init() } } 然后,让单元处理 KVO。 首先,我有一个协议,单元格可以通过该协议通知表格视图它需要重新加载: protocol CustomCellDelegate: class { func didUpdateObject(for cell: UITableViewCell) } 并且表视图控制器可以符合这个CustomCellDelegate协议并在通知它需要时重新加载单元格: func didUpdateObject(for cell: UITableViewCell) { if let indexPath = tableView.indexPath(for: cell
  • 用于更新/更改元素/innerText 的 Javascript 事件侦听器(Javascript Eventlistener for Update / Change on Element / innerText)
    问题 是否有一个 eventListener 只是检查innerText的变化? 例子: 12345 我只想检查“12345”是否正在更改为“23415”之类的其他内容。 不会出现“点击”事件或其他任何事情。 我没有机会通过跨度更新即将到来的代码。 所以我真的只能从 span 元素的变化中获取事件,但我不知道如何。 对不起,我的英语不好,谢谢! 回答1 查看 MutationObserver。 使用它你可以监听被观察元素的characterData 。 例子: HTML <span class="observable" contenteditable="true">12345</span> JS var observables = document.querySelector('.observable'); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { console.log(mutation); }); }); var config = {characterData: true, subtree: true}; observer.observe(observables, config); 小提琴 请注意,
  • 使用香草javascript和MutationObserver检测输入标签中的值变化(detect value change in input tag with vanilla javascript and MutationObserver)
    问题 我想检测何时输入字段中的文本/值发生变化。 即使我用js更改了值,我也想检测到该更改。 到目前为止,这是我在小提琴演示中尝试过的方法。 HTML : <input type="text" id="exNumber"/> JavaScript : var observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { // console.log('Mutation type: ' + mutation.type); if ( mutation.type == 'childList' ) { if (mutation.addedNodes.length >= 1) { if (mutation.addedNodes[0].nodeName != '#text') { // console.log('Added ' + mutation.addedNodes[0].tagName + ' tag.'); } } else if (mutation.removedNodes.length >= 1) { // console.log('Removed ' + mutation.removedNodes[0].tagName + ' tag.') } } if
  • 如何观察数组的变化并查看添加了哪个新元素?(How can I observe array changes and see which new element is added?)
    问题 onArrayChanged: function(obj, keyName, value) { // What is value here, exactly? }.property('array.@each') 将元素添加到数组时,如何知道添加了哪个值? 同样,当从数组中删除一个值时,如何访问它呢? 回答1 看看addArrayObserver,请参阅http://jsfiddle.net/pangratz666/EE65Z/: var a = Ember.A('a b c d e f g'.w()); var o = Ember.Object.create({ arrayWillChange: Ember.K, arrayDidChange: function(array, start, removeCount, addCount) { console.log(arguments); } }); a.addArrayObserver(o);
  • 理解VUE双向数据绑定原理和实现
    一、原理:1.vue 双向数据绑定是通过 数据劫持 结合 发布订阅模式的方式来实现的, 也就是说数据和视图同步,数据发生变化,视图跟着变化,视图变化,数据也随之发生改变;2.核心:关于VUE双向数据绑定,其核心是 Object.defineProperty()方法;3.介绍一下Object.defineProperty()方法 (1)Object.defineProperty(obj, prop, descriptor) ,这个语法内有三个参数,分别为 obj (要定义其上属性的对象) prop (要定义或修改的属性) descriptor (具体的改变方法) (2)简单地说,就是用这个方法来定义一个值。当调用时我们使用了它里面的get方法,当我们给这个属性赋值时,又用到了它里面的set方法;set,get方法初步了解二、先简单的实现一个js的双向数据绑定来熟悉一下这个方法: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document<