angular 双向绑定
子组件定义
import {Component,forwardRef, EventEmitter, Input, Output } from '@angular/core';
import {ControlValueAccessor,NG_VALUE_ACCESSOR} from '@angular/forms'
@Component({
selector:'toggle-button',
template:`<div class="toggle-button-container" (click)="toggle()" style="background: red">
<a href="javascript:;" class="text-close" *ngIf="!model">关</a>
<a href="javascript:;" class="text-open" *ngIf="model">开</a>
</div>`,
providers:[{
provide:NG_VALUE_ACCESSOR,
useExisting:forwardRef(()=>RioToggleButton),
multi:true
}]
})
export class ToggleButton implements ControlValueAccessor{
@Input() model: any = ''
@Output() modelChange: EventEmitter<any> = new EventEmitter<any>()
toggle():void {
this.modelChange.emit(!this.model)
//this.modelChange.emit(123)
}
writeValue(value: any): void {
this.model = value
}
registerOnChange(fn: Function): void {
this.controlChange = fn
}
registerOnTouched(fn: Function): void {
this.controlTouch = fn
}
private controlChange: Function = () => {}
private controlTouch: Function = () => {}
}
父组件
<div>
{{deliverSwitch}}
<toggle-button [(model)]="deliverSwitch"></toggle-button>
</div>
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'app';
deliverSwitch = false;
}
如上
属性传递子组件:在子组件中@Input model属性是由父组件向子组件传递,model 值为父组件deliverSwitch提供,
属性值同步父组件:@Output modelChange 为EventEmitter实例,modelChange(这里需要刻意注意是model+Change),通过this.modelChange.emit(!this.model) 就可以将model 的值同步到父组件
更深入探讨父组件如何监听子组件model 的change (一般来讲只是使用双向绑定就可以完成大部分功能)
//(modelChange) 监听子组件this.modelChange.emit(modelVal)
<toggle-button [(model)]="deliverSwitch" (modelChange)="onModelChange($event)"></toggle-button>
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
deliverSwitch = false;
onModelChange(modelVal) {
console.log(modelVal);//modelVal为子组件emit发过来的值
}
}
vue 双向绑定
vue 分为2中形式
形式1:以v-model,子组件以$emit("input", modelValue)同步父组件
父组件
{{count}}
<count-plus v-model="count"></count-plus>
子组件 如下通过this.$emit("input", ++this.count); $emit "input"事件来同步父组件v-model
Vue.component("countPlus", {
props: {
value: {
required: true,
type: Number
}
},
data() {
//props 在子组件中不要直接使用
return {
count: this.value
}
},
template: `
<div @click="addCount">{{count}}</div>
`,
methods: {
addCount() {
this.$emit("input", ++this.count)
}
},
watch: {
value: function(newVal, oldVal) {
this.count = newVal;
}
}
})
形式2:以属性的形式 :xxx.sync="data" this.$emit("update:xxx", xxxValue);
父组件:
{{count}}
<count-plus :count.sync="count"></count-plus>
子组件
Vue.component("countPlus", {
props: {
count: {
required: true,
type: Number
}
},
data() {
//props 在子组件中不要直接使用
return {
countCopy: this.count
}
},
template: `
<div @click="addCount">{{countCopy}}</div>
`,
methods: {
addCount() {
this.$emit("update:count", ++this.countCopy)
}
},
watch: {
value: function(newVal, oldVal) {
this.countCopy = newVal;
}
}
})
看到这里基本上就可以了
贴一段vue.prototype.$emit
其实无论是v-model 还是:prop.sync ,最终执行的都是在父组件中的回调函数,vue 自己给包装了一下,你可以跟一下代码,看看vue 经典的实现。
谢谢您的浏览。