无magic: true参数时,数组变化如何更新Ractive.js?
问题描述
我用Ractive结合PouchDB展示实时变化的数组数据,原本靠magic: true参数实现自动更新,但Ractive 0.9.x版本把这个参数移除了。官方建议每次数组变化时调用ractive.update(),但我遇到了作用域问题:
fetchInitialDocs().then(renderDocsSomehow).then(reactToChanges).catch(console.log.bind(console)); function renderDocsSomehow() { let myRactive = new Ractive({ el: '#myDiv', template: 'my Template', //magic: true, data:{ doc1: docs }, components: {myComponents}, computed: {computedValues} }); } function reactToChanges() { //here my changes appear onUpdatedOrInserted(change.doc); myRactive.update() // <- 这里没法用update,因为myRactive在这个作用域里找不到 }
我还试过在renderDocsSomehow()里加观察者,但没生效:
ractive.observe('doc1', function(newValue, oldValue, keypath) { ractive.update() });
请问怎么通知Ractive数据已经变更,触发更新呢?
解决方案
这个问题本质是两个核心点:一是解决Ractive实例的跨函数作用域访问,二是要遵循Ractive的响应式数据更新规则——直接修改原始数据是不会触发视图更新的。给你几个实用的解决办法:
1. 让Ractive实例在全局/外层作用域可访问
最简单的方式就是把myRactive声明在两个函数都能访问到的外层作用域,或者从renderDocsSomehow里返回实例,这样链式调用的后续函数也能拿到它:
let myRactive; // 外层作用域声明实例变量 fetchInitialDocs() .then(renderDocsSomehow) .then(reactToChanges) .catch(console.log.bind(console)); function renderDocsSomehow() { myRactive = new Ractive({ el: '#myDiv', template: 'my Template', data:{ doc1: docs }, components: {myComponents}, computed: {computedValues} }); return myRactive; // 返回实例,确保链式调用能拿到 } function reactToChanges() { // 关键:不要直接修改原始数组,要用Ractive的API更新数据 // 比如把新的文档添加到doc1数组里 myRactive.push('doc1', change.doc); // 用push/set这类方法后,Ractive会自动触发视图更新,不需要手动调用update() // 除非你有特殊的计算属性需要强制刷新,那再调用myRactive.update() }
2. 利用闭包绑定实例(避免全局变量)
如果不想用全局变量,推荐在renderDocsSomehow内部创建变更处理函数的闭包版本,这样它就能直接访问到内部的myRactive实例:
fetchInitialDocs() .then(renderDocsSomehow) .catch(console.log.bind(console)); function renderDocsSomehow() { const myRactive = new Ractive({ el: '#myDiv', template: 'my Template', data:{ doc1: docs }, components: {myComponents}, computed: {computedValues} }); // 在这里定义变更处理函数,通过闭包直接访问myRactive function handleDocChange(doc) { myRactive.push('doc1', doc); } // 把PouchDB的变更事件和这个闭包函数绑定 onUpdatedOrInserted(handleDocChange); }
3. 修复你的观察者方案(为什么之前没生效?)
你之前的观察者没起作用,是因为默认的observe只会监听doc1的引用变化(比如把整个数组替换成新数组),如果只是修改数组内部元素,需要开启深度观察:
myRactive.observe('doc1.*', function(newValue, oldValue, keypath) { // 这个回调会在数组新增、修改、删除元素时触发 // 但其实如果是用Ractive的API修改数据,这里甚至不需要手动调用update() // myRactive.update(); }, { depth: Infinity });
不过还是更推荐使用Ractive提供的push、splice、set等方法来修改数据,这样Ractive会自动处理响应式更新,不需要额外手动调用update()。
内容的提问来源于stack exchange,提问作者Torf
相关产品推荐
相关产品推荐

