当前位置 : 主页 > 网页制作 > JQuery >

jquery改变事件和aurelia的技巧

来源:互联网 收集:自由互联 发布时间:2021-06-15
我需要找到一个可靠的解决方案来使这两个框架发挥得很好. 使用materialize-css,他们的select元素使用jquery来应用值更改.然而,这不会触发aurelia看到变化.使用…的技术 $( “选择”) .change(
我需要找到一个可靠的解决方案来使这两个框架发挥得很好.

使用materialize-css,他们的select元素使用jquery来应用值更改.然而,这不会触发aurelia看到变化.使用…的技术

    $( “选择”)
        .change((eventObject:JQueryEventObject)=> {
            fireEvent(eventObject.target,“change”);
    });

我可以触发aurelia看到的事件,然而,aurelia然后导致事件再次被触发,而它正在更新它的绑定并且我最终进入无限循环…. Stack Overflow:D

什么是最可靠的方式让这两个人在这方面一起玩?

我已经与materialize-css aurelia合作了一段时间,我可以确认来自物化的选择元素是非常有问题的.

我只想在这里分享我的一个解决方案,以防有人想要一些额外的例子.在这种情况下,阿什利可能更干净.我使用可绑定的选项而不是插槽.

除此之外,基本思想是相同的(使用保护变量和微任务).

我在处理第三方插件和双向数据绑定时学到的一个教训是,它有助于在处理源自绑定目标(DOM上的select元素)的更改和源自的绑定更改之间做出更明确,明确的分离.绑定源(例如包含该元素的页面的ViewModel).

我倾向于使用名称为onValueChangedByBindingSource和onValueChangedByBindingTarget的更改处理程序来处理将ViewModel与DOM同步的不同方式,从而减少代码混乱.

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

SRC /材料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 /材料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();
        }
    }
}
网友评论