在Svelte中拼接后如何更新数组?

时间:2019-11-20 22:04:55

标签: svelte

我正在学习Svelte从文档中读到的内容,需要重新分配数组才能更新组件或页面。为此,他们提供了一个更惯用的解决方案。不用写:

messages.push('hello');
messages = messages;

您可以改为:

messages = [...messages, 'hello'];

好的,很有道理。但随后文档说:

  

您可以使用类似的样式来替换弹出,移位,取消移位和拼接。

但是如何?我看不到如何从数组中删除项目。更重要的是,我该如何惯用地写以下内容?

messages.splice(messages.indexOf('hello'), 1);
messages = messages;

7 个答案:

答案 0 :(得分:3)

您可以例如使用filter数组方法创建一个没有元素'hello'的新数组:

messages = messages.filter(m => m !== 'hello');

答案 1 :(得分:3)

如前所述,斯维尔特的反应性是由作业触发的。 current Svelte tutorial使用JavaScript的(ES6)spread syntax(三个点)将下一个较高的数字添加到数组中,与使用push的冗余分配相比,它提供了更多的惯用解决方案:

function pushNumber() {     
    numbers = [...numbers, lastnumber]; // 1, 2, 3, 4, 5
}

您可以使用扩展语法来替换popshiftunshiftsplice,尽管在某些情况下可能会增加操作时间和复杂性:

function unshiftNumber() {  
    numbers = [firstnumber, ...numbers]; // 0, 1, 2, 3, 4
}

function popNumber() {
    numbers = [...numbers.slice(0,numbers.length - 1)]; // 1, 2, 3
}

function shiftNumber() {
    numbers = [...numbers.slice(1,numbers.length)]; // 2, 3, 4
}

function spliceNumber() {
    numbers = [firstnumber, ...numbers.slice(0,numbers.length-1)];// 0, 1, 2, 3
}   

不过,传播只是做到这一点的一种方法。不使用pop / push等的目的是鼓励不变性。因此,例如,任何删除都只能是过滤器。

答案 2 :(得分:2)

这里有几件事情要考虑。 给出以下代码:

CFLAGS

这里发生的是:

  1. 寻找字符串messages.splice(messages.indexOf('hello'), 1); messages = messages; 在数组中 first 的出现
  2. 根据找到的索引从数组中删除此类元素。

这里的假设是"hello" 需要存在,否则可能会从数组中删除 last 项(因为"hello"返回indexOf

因此,原始数组是可变的:取决于上下文,有时可能更可取,而不是将整个数组复制到一个新数组中;否则,通常最好避免这种突变。

所以。如果您想完全具有这种行为,可能这是最好的代码。例如,以filter为例:

-1

这里发生的是:

  1. 过滤掉 any 元素等于messages = messages.filter(message => message !== "hello")
  2. 返回不包含此类元素的 new 数组

因此它与原始代码有很大不同:首先,它总是循环整个数组。如果您有成千上万个元素,即使第二个索引只有一个"hello",它也会始终迭代所有元素。也许这就是您想要的,也许不是。如果该元素是唯一的(例如id),则可能希望在找到它后停止。 其次,它返回一个新数组。再说一次,通常比改变数组更好,但是在某些情况下,最好改变它而不是创建一个新的数组。

因此,如果您想对原始数组进行变异,最好坚持使用原始代码。

相反,如果您不在乎(例如"hello"的示例),我相信出于svelte开发人员的意图,您的代码将大致翻译为:

push

(仍然假设有一条let i = messages.indexOf("hello"); messages = [...messages.slice(0, i), ...messages.slice(i + 1)]; 消息,而您只对第一次出现的消息感兴趣。)

不幸的是,JS没有更好的语法来处理切片。

答案 3 :(得分:1)

您可以在阵列上执行常规的pushpop或`拼接操作

但是由于Svelte的反应性是由分配触发的,因此使用诸如push和splice的数组方法不会自动导致更新。

根据All about Immutable Arrays and Objects in JavaScript,您可以这样操作...

let messages = ['something', 'another', 'hello', 'word', 'another', 'again'];

const indexOfHello = messages.indexOf('hello');

messages = [...messages.slice(0, indexOfHello), ...messages.slice(indexOfHello + 1)];

请注意接头切片

splice()方法向数组中添加/删除项目,并返回 删除的项目。 注意:此方法更改了原始数组。 语法array.splice(start, deleteCount, itemstoAdd, addThisToo);

但是

slice()方法将数组中选定的元素作为新的数组对象返回。 slice()方法选择从给定start参数开始的元素,并以给定end参数结束但不包括给定end参数的元素。 注意:原始阵列不会更改。

顺序排列

它将数组的一部分的浅表副本返回到新数组中 从开始到结束选择的对象(不包括结束)。原本的 数组将不会被修改。 语法: array.slice(start, end);

答案 4 :(得分:0)

展开拼接数组,将其重新分配给它自己;)

messages = [...messages.splice(messages.indexOf('hello'), 1)];

目标是使Svelte检测到数组messages(您的组件的属性或Svelte存储区中的变量)已更改。这就是为什么必须使用messageslet关键字而不是var声明数组const的原因。这样,您就可以重新分配它。重新分配操作本身足以使Svelte检测到阵列已更改。

甚至,只要这样做也可以:

messages = messages.splice(messages.indexOf('hello'), 1);

答案 5 :(得分:0)

一个衬套将无法与更改数组位置的数组功能一起使用,例如弹出,拼接,移位或不移位,所有这些都将更改实际数组,并且不返回修改后的数组

例如,在拼接的情况下(强调我的意思):

  

splice()方法通过删除或替换现有元素和/或添加新元素就位来更改数组的内容。

一个衬纸不会分配正确的值,请不要这样做:

let bob = [23, 46];
bob = bob.splice(0,1); // bob is now [23], instead of [46], after removing the first element

这意味着您具有正确的直觉,拼接必须在重新分配之前进行,通常这将在两个语句中进行。这将按照您期望的那样进行反应,从而导致数组没有问候:

let foo = ['hello', 'world'];
foo.splice(foo.indexOf('hello'), 1);
foo = foo; // foo is now ['world'], after removing 'hello'

答案 6 :(得分:0)

如果您四处游荡,filter 也可用于使用给定的 index 删除元素:

let elements = ['a','b', 'c'];
let idx = 1;
elements = elements.filter( (e,i) => i !== idx );
// => ['a', 'c']