gpt4 book ai didi

aurelia - jquery 更改事件和 aurelia 的技术

转载 作者:行者123 更新时间:2023-12-01 09:17:39 25 4
gpt4 key购买 nike

我需要找到一个可靠的解决方案来让这两个框架很好地发挥作用。

使用 materialize-css,他们的 select 元素使用 jquery 来应用值更改。然而,这并不会触发 aurelia 看到变化。使用...的技术
$("选择")
.change((eventObject: JQueryEventObject) => {
fireEvent(eventObject.target, "变化");
});
我可以触发 aurelia 看到的事件,但是,aurelia 然后在更新它的绑定(bind)时导致事件再次被触发,我最终陷入无限循环......堆栈溢出:D

在这方面让两者一起玩最可靠的方法是什么?

最佳答案

我已经使用 materialize-css + aurelia 工作了一段时间,我可以确认来自 materialize 的 select 元素是相当有问题的。

我只是想在这里分享我的一个解决方案,以防有人需要更多示例。在这种情况下,Ashley's 可能更清洁。我的选项使用可绑定(bind)而不是插槽。

除了基本思想是相同的(使用保护变量和微任务)。

我在处理 3rd 方插件和双向数据绑定(bind)方面学到的一个教训是,它有助于在处理源自绑定(bind)目标(DOM 上的选择元素)的更改和更改之间进行更清晰、更明显的分离源自绑定(bind)源(例如,包含该元素的页面的 ViewModel)。

我倾向于使用名称如 onValueChangedByBindingSourceonValueChangedByBindingTarget 的更改处理程序来处理将 ViewModel 与 DOM 同步的不同方式,从而减少混淆代码。

示例:https://gist.run?id=6ee17e333cd89dc17ac62355a4b31ea9

src/material-select.html

<template>
<div class="input-field">
<select value.two-way="value" id="material-select">
<option repeat.for="option of options" model.bind="option">
${option.displayName}
</option>
</select>
</div>
</template>

src/material-select.ts

import {
customElement,
bindable,
bindingMode,
TaskQueue,
Disposable,
BindingEngine,
inject,
DOM
} from "aurelia-framework";

@customElement("material-select")
@inject(DOM.Element, TaskQueue, BindingEngine)
export class MaterialSelect {
public element: HTMLElement;
public selectElement: HTMLSelectElement;

@bindable({ defaultBindingMode: bindingMode.twoWay })
public value: { name: string, value: number };

@bindable({ defaultBindingMode: bindingMode.oneWay })
public options: { displayName: string }[];

constructor(
element: Element,
private tq: TaskQueue,
private bindingEngine: BindingEngine
) {
this.element = element;
}

private subscription: Disposable;
public isAttached: boolean = false;
public attached(): void {
this.selectElement = <HTMLSelectElement>this.element.querySelector("select");
this.isAttached = true;

$(this.selectElement).material_select();
$(this.selectElement).on("change", this.handleChangeFromNativeSelect);

this.subscription = this.bindingEngine.collectionObserver(this.options).subscribe(() => {
$(this.selectElement).material_select();
});
}

public detached(): void {
this.isAttached = false;
$(this.selectElement).off("change", this.handleChangeFromNativeSelect);
$(this.selectElement).material_select("destroy");
this.subscription.dispose();
}

private valueChanged(newValue, oldValue): void {
this.tq.queueMicroTask(() => {
this.handleChangeFromViewModel(newValue);
});
}


private _suspendUpdate = false;

private handleChangeFromNativeSelect = () => {
if (!this._suspendUpdate) {
this._suspendUpdate = true;
let event = new CustomEvent("change", {
bubbles: true
});
this.selectElement.dispatchEvent(event)

this._suspendUpdate = false;
}
}

private handleChangeFromViewModel = (newValue) => {
if (!this._suspendUpdate) {
$(this.selectElement).material_select();
}
}
}

编辑

自定义属性怎么样?

要点:https://gist.run?id=b895966489502cc4927570c0beed3123

src/app.html

<template>
<div class="container">
<div class="row"></div>
<div class="row">
<div class="col s12">
<div class="input-element" style="position: relative;">
<select md-select value.two-way="currentOption">
<option repeat.for="option of options" model.bind="option">${option.displayName}</option>
</select>
<label>Selected: ${currentOption.displayName}</label>
</div>
</div>
</div>
</div>
</template>

src/app.ts

export class App {
public value: string;
public options: {displayName: string}[];

constructor() {
this.options = new Array<any>();
this.options.push({ displayName: "Option 1" });
this.options.push({ displayName: "Option 2" });
this.options.push({ displayName: "Option 3" });
this.options.push({ displayName: "Option 4" });
}

public attached(): void {

this.value = this.options[1];
}
}

src/md-select.ts

import {
customAttribute,
bindable,
bindingMode,
TaskQueue,
Disposable,
BindingEngine,
DOM,
inject
} from "aurelia-framework";

@inject(DOM.Element, TaskQueue, BindingEngine)
@customAttribute("md-select")
export class MdSelect {
public selectElement: HTMLSelectElement;

@bindable({ defaultBindingMode: bindingMode.twoWay })
public value;

constructor(element: Element, private tq: TaskQueue) {
this.selectElement = element;
}

public attached(): void {
$(this.selectElement).material_select();
$(this.selectElement).on("change", this.handleChangeFromNativeSelect);
}

public detached(): void {
$(this.selectElement).off("change", this.handleChangeFromNativeSelect);
$(this.selectElement).material_select("destroy");
}

private valueChanged(newValue, oldValue): void {
this.tq.queueMicroTask(() => {
this.handleChangeFromViewModel(newValue);
});
}


private _suspendUpdate = false;

private handleChangeFromNativeSelect = () => {
if (!this._suspendUpdate) {
this._suspendUpdate = true;
const event = new CustomEvent("change", { bubbles: true });
this.selectElement.dispatchEvent(event)
this.tq.queueMicroTask(() => this._suspendUpdate = false);
}
}

private handleChangeFromViewModel = (newValue) => {
if (!this._suspendUpdate) {
$(this.selectElement).material_select();
}
}
}

关于aurelia - jquery 更改事件和 aurelia 的技术,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40042667/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com