【问题标题】:Aurelia binding to a function with parameter and forcing updateAurelia 绑定到带参数的函数并强制更新
【发布时间】:2020-02-23 14:45:39
【问题描述】:

我已将 isSelected(item) 函数绑定到我的按钮,该函数将切换类以显示它是否被选中,但是此函数不会在更改时更新。

我不能使用计算属性,因为它需要一个参数。

有没有什么方法可以使用绑定函数并使用@computedFrom 装饰器等进行理想更新?

这里的例子:

https://codesandbox.io/s/aurelia-typescript-sandbox-8oksr?fontsize=14

您会注意到通过该功能正确绑定了人2,但单击其他​​项目不会更新UI。

-

这样做的原因

我想这样做的原因是源数组有点复杂。而不是我在这里作为示例给出的 people 数组。我的真实域更接近于包含项目的框列表,这些框可以包含其他框(可能无限),可以在任何级别选择项目。

【问题讨论】:

  • 再一次,虽然我不认为这是一个很好的选择,但我在下面发布的内容实际上应该适用于您的“盒子”。 IOW,每个“盒子”都有自己的 isSelected 标志。也许这在您的场景中仍然不起作用?
  • 我已经做了一些接近你建议的事情,但正如你所说,手动管理状态不是一个好的选择,而且很容易出错。我希望发现有某种方法可以将函数连接到更改通知,这样我就可以把它全部撕掉。 KnockoutJs 允许您绑定到参数化函数(尽管我相信它会在轮询更改时对性能造成影响)
  • 在更新 2 中查看我的答案。我认为这解决了您正在尝试做的事情。

标签: function binding aurelia


【解决方案1】:

更新 2

所以我遇到了this issue on github。其中一个答案表明,将观察到的项目传递给方法会自动使方法可观察。目前,您只是将person 传递给isSelected()。但是,人并没有被改变。我认为您可以通过像这样更改您的 isSelected() 方法来完成您正在寻找的内容(注意在按钮的类绑定中对 isSelected 的调用发生了变化):

vm.ts

public isSelected(person, length){
   return this.selections.find(item => item.name === person.name);
}

view.html

<button
    class="btn-gradient mini ${isSelected(person, selections.length) ? 'green': 'red'}"
    click.delegate="selectPerson(person)"
    repeat.for="person of people">
    ${person.name}
  </button>

示例:https://codesandbox.io/s/aurelia-typescript-sandbox-oelt7?fontsize=14

原帖

我在尝试实现isSelected() 方法来控制选定的指标类时遇到了同样的问题。我已经查看了@computedFrom

我可能错了,但从我所见@computedFrom 只能与未参数化的 getter 一起使用。

@computedFrom('firstName', 'lastName')
get fullName() { return `${firstName} ${lastName}`}

所以我们想要做的问题是我们需要将索引或项目传递给我们的方法——这破坏了我们使用@computedFrom的能力。

另一种我不太喜欢...但它确实有效的替代方法是为您的每个 person 对象添加一个 isSelected 属性。然后您的代码将如下所示:

vm.ts

selectPerson(person){
    person.isSelected = !person.isSelected;  //De-selects if already selected
}

view.html

<button
class="btn-gradient mini ${person.isSelected ? 'green': 'red'}"
click.delegate="selectPerson(person)"
repeat.for="person of people">${person.name}</button>

(或者,正如我最近向我建议的那样,将您的 person 对象包装在一个包装类中)

public class SelectableWrapper {
   constructor(public person : Person, public isSelected : boolean){}
}

更新 1

要解决显示所选项目列表的问题(以及“着色”所选项目),您可以执行以下操作(除了我已经显示的内容):

vm.ts

//Remove selections property and add it as a getter
get selections(){
   return this.people.filter(p => p.isSelected);
}

view.html

<div repeat.for = "person of selections">
   ${person.name}
</div>

此处示例:https://codesandbox.io/s/aurelia-typescript-sandbox-u92nk?fontsize=14

【讨论】:

  • 这确实有效,传入一个您并不真正关心计算的附加参数有点奇怪,但它确实更新了 UI。我想知道我是否可以在新的装饰器中隐藏这种怪异,比如 computedFrom
  • 该问题的最终评论实际上链接到对此处选项的很好解释。不是这样的,我现在最不喜欢。 sobell.net/aurelia-dirty-checking-a-function
【解决方案2】:

利用信号器进行多选

import "./app.css";
import {BindingSignaler} from 'aurelia-templating-resources';
import { inject } from "aurelia-framework";

@inject(BindingSignaler)
export class App {
  message = "Hello World!";
  message2 = "Hello World2!";
  people = [{ name: "Person 1" }, { name: "Person 2" }, { name: "Person 3" }];
  selections = [];

  constructor(private signaler: BindingSignaler) {
    this.selections.push(this.people[1]);
  }

  selectPerson(person) {
    this.selections.push(person);
    this.signaler.signal('select-signal')
  }

  color(person) {
    return this.selections.includes(person) ? 'green' : 'red';
  }
}
<template>
  <h1>People</h1>

  <div repeat.for="person of selections">
    ${person.name}
  </div>

  <button
    class="btn-gradient mini ${color(person) & signal:'select-signal' }"
    click.delegate="selectPerson(person)"
    repeat.for="person of people"
  >
    ${person.name}
  </button>
</template>

单选

selected 添加到类中, 在更改时分配person 然后使用selected === person 作为条件

import "./app.css";

export class App {
  message = "Hello World!";
  message2 = "Hello World2!";
  people = [{ name: "Person 1" }, { name: "Person 2" }, { name: "Person 3" }];
  selections = [];

  // add selected
  selected = null;

  constructor() {

    // use selectPerson
    this.selectPerson(this.people[1]);
  }

  selectPerson(person) {
    this.selections.push(person);

    // assign person to selected
    this.selected = person;
  }
}

<template>
  <h1>People</h1>

  <div repeat.for="person of selections">
    ${person.name}
  </div>

  <!-- use `selected === person` as condition -->
  <button
    class="btn-gradient mini ${selected === person ? 'green': 'red'}"
    click.delegate="selectPerson(person)"
    repeat.for="person of people"
  >
    ${person.name}
  </button>
</template>

【讨论】:

  • 我已经通过 selections 数组跟踪选定的人(可以是多人)。我想强调所有选择,而不仅仅是我相信您的代码将实现的最新选择。
猜你喜欢
  • 1970-01-01
  • 2011-07-20
  • 2011-02-09
  • 1970-01-01
  • 2018-12-30
  • 2010-09-20
  • 2011-04-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多