我正在学习Svelte从文档中读到的内容,需要重新分配数组才能更新组件或页面。为此,他们提供了一个更惯用的解决方案。不用写:
messages.push('hello');
messages = messages;
您可以改为:
messages = [...messages, 'hello'];
好的,很有道理。但随后文档说:
您可以使用类似的样式来替换弹出,移位,取消移位和拼接。
但是如何?我看不到如何从数组中删除项目。更重要的是,我该如何惯用地写以下内容?
messages.splice(messages.indexOf('hello'), 1);
messages = messages;
答案 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
}
您可以使用扩展语法来替换pop
,shift
,unshift
和splice
,尽管在某些情况下可能会增加操作时间和复杂性:>
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
这里发生的是:
messages.splice(messages.indexOf('hello'), 1);
messages = messages;
在数组中 first 的出现这里的假设是"hello"
需要存在,否则可能会从数组中删除 last 项(因为"hello"
返回indexOf
。
因此,原始数组是可变的:取决于上下文,有时可能更可取,而不是将整个数组复制到一个新数组中;否则,通常最好避免这种突变。
所以。如果您想完全具有这种行为,可能这是最好的代码。例如,以filter为例:
-1
这里发生的是:
messages = messages.filter(message => message !== "hello")
因此它与原始代码有很大不同:首先,它总是循环整个数组。如果您有成千上万个元素,即使第二个索引只有一个"hello"
,它也会始终迭代所有元素。也许这就是您想要的,也许不是。如果该元素是唯一的(例如id),则可能希望在找到它后停止。
其次,它返回一个新数组。再说一次,通常比改变数组更好,但是在某些情况下,最好改变它而不是创建一个新的数组。
因此,如果您想对原始数组进行变异,最好坚持使用原始代码。
相反,如果您不在乎(例如"hello"
的示例),我相信出于svelte开发人员的意图,您的代码将大致翻译为:
push
(仍然假设有一条let i = messages.indexOf("hello");
messages = [...messages.slice(0, i), ...messages.slice(i + 1)];
消息,而您只对第一次出现的消息感兴趣。)
不幸的是,JS没有更好的语法来处理切片。
答案 3 :(得分:1)
您可以在阵列上执行常规的push
和pop
或`拼接操作
但是由于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存储区中的变量)已更改。这就是为什么必须使用messages
或let
关键字而不是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']