Aurelia父组件更新可观察集合时子视图不更新如何解决
问题原因
视图不更新的核心问题是代码里存在两个完全独立的TodoList实例:
- 你在
app.ts中手动通过new TodoList()创建了一个实例,调用addOne方法修改的是这个实例的todos数组 - 模板里的
<todo-list>是Aurelia的自定义组件,框架渲染时会自动为这个组件创建单独的TodoList视图模型实例,组件视图绑定的是这个独立实例的todos属性
两个实例数据完全不互通,你修改手动创建的实例数据时,组件根本感知不到变化,自然不会触发视图刷新。
可行修改方案
方案1:通过bindable做属性绑定(推荐,符合组件设计规范)
把数据源统一放在父组件持有,子组件只负责接收数据渲染:
- 修改
todo-list.ts,给组件添加可绑定的todos属性,移除组件内部的数据源初始化和新增方法:
import { bindable } from 'aurelia-framework'; export interface Todo { description: string; done: boolean; } export class TodoList { @bindable todos: Todo[] = []; }
- 修改
app.ts,把todos数组和新增逻辑移回App类,删除手动实例化TodoList的代码:
export interface Todo { description: string; done: boolean; } export class App { todos: Todo[] = [ { description: "Make bed", done: true }, { description: "Take out trash", done: false } ]; todoDescription = ''; addTodo() { if (this.todoDescription) { this.todos.push({ description: this.todoDescription, done: false }); this.todoDescription = ''; } } }
- 修改
app.html,将父组件的todos绑定到子组件对应属性上:
<template> <require from="./todo-list"></require> <h1>Todo list</h1> <form submit.trigger="addTodo()"> <input type="text" value.bind="todoDescription"> <button type="submit" disabled.bind="!todoDescription">Add Todo</button> </form> <todo-list todos.bind="todos"></todo-list> </template>
todo-list.html的渲染逻辑不需要调整,保持原有repeat.for="todo of todos"的写法即可正常工作。
方案2:通过ref获取组件真实实例
如果要把列表相关逻辑全部封装在TodoList类中,可以用ref属性拿到框架渲染生成的组件实例,直接操作实例上的数据:
- 修改
app.html,给todo-list标签添加ref引用:
<todo-list ref="todoList"></todo-list>
- 修改
app.ts,删除手动new TodoList()的代码,声明同名属性承接框架注入的组件实例:
import { TodoList } from "./todo-list"; export class App { todoList: TodoList; todoDescription = ''; addTodo() { if (this.todoDescription) { this.todoList.addOne(this.todoDescription); this.todoDescription = ''; } } }
这种方案不需要调整todo-list.ts和todo-list.html的原有代码,调用addOne时直接修改的是组件正在使用的实例数据,数组变更会被Aurelia的绑定系统感知,视图会同步更新。
内容的提问来源于stack exchange,提问作者Jacob Archambault
相关产品推荐
相关产品推荐

