在这段使用JSX的React代码中,...
是做什么的?它叫什么名字?
<Modal {...this.props} title='Modal heading' animation={false}>
在这段使用JSX的React代码中,...
是做什么的?它叫什么名字?
<Modal {...this.props} title='Modal heading' animation={false}>
{...this.props}
展开了props
中的“自有”可枚举属性,作为你正在创建的Modal
元素上的离散属性。例如,如果this.props
包含a: 1
和b: 2
,那么<Modal {...this.props} title='Modal heading' animation={false}>
将会与
<Modal a={this.props.a} b={this.props.b} title='Modal heading' animation={false}>
class Example extends React.Component {
render() {
const { className, children } = this.props;
return (
<div className={className}>
{children}
</div>
);
}
}
ReactDOM.render(
[
<Example className="first">
<span>Child in first</span>
</Example>,
<Example className="second" children={<span>Child in second</span>} />
],
document.getElementById("root")
);
.first {
color: green;
}
.second {
color: blue;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
this.setState(prevState => {
return {foo: {...prevState.foo, a: "updated"}};
});
将this.state.foo
替换为一个新对象,该对象具有与foo
相同的所有属性,除了a
属性变为"updated"
:
const obj = {
foo: {
a: 1,
b: 2,
c: 3
}
};
console.log("original", obj.foo);
// Creates a NEW object and assigns it to `obj.foo`
obj.foo = {...obj.foo, a: "updated"};
console.log("updated", obj.foo);
.as-console-wrapper {
max-height: 100% !important;
}
children
属性,还是它们会被合并? - Snackoverflowchildren
的属性提供的子元素将被放弃,而你在开始标记和结束标记之间指定的子元素将会生效,但如果这是未定义行为,我肯定不会依赖它。 - T.J. Crowder...
被称为 扩展属性,正如名称所表示的那样,它允许一个表达式被展开。
var parts = ['two', 'three'];
var numbers = ['one', ...parts, 'four', 'five']; // ["one", "two", "three", "four", "five"]
在这种情况下(我将简化它)。
// Just assume we have an object like this:
var person= {
name: 'Alex',
age: 35
}
这个:
<Modal {...person} title='Modal heading' animation={false} />
等于
<Modal name={person.name} age={person.age} title='Modal heading' animation={false} />
简而言之,这是一种巧妙的捷径,我们可以这样说。
**my_dict
。 - aquirdturtle这三个点在ES6中代表了展开运算符,它允许我们在JavaScript中做很多事情:
连接数组
var shooterGames = ['Call of Duty', 'Far Cry', 'Resident Evil'];
var racingGames = ['Need For Speed', 'Gran Turismo', 'Burnout'];
var games = [...shooterGames, ...racingGames];
console.log(games) // ['Call of Duty', 'Far Cry', 'Resident Evil', 'Need For Speed', 'Gran Turismo', 'Burnout']
解构数组
var shooterGames = ['Call of Duty', 'Far Cry', 'Resident Evil'];
var [first, ...remaining] = shooterGames;
console.log(first); //Call of Duty
console.log(remaining); //['Far Cry', 'Resident Evil']
合并两个对象
var myCrush = {
firstname: 'Selena',
middlename: 'Marie'
};
var lastname = 'my last name';
var myWife = {
...myCrush,
lastname
}
console.log(myWife); // {firstname: 'Selena',
// middlename: 'Marie',
// lastname: 'my last name'}
另一个使用三个点的方法是被称为剩余参数(Rest Parameters),它使得将函数的所有参数作为一个数组传入成为可能。
将函数的参数作为数组
function fun1(...params) {
}
...
(JavaScript中的三个点)被称为Spread Syntax或Spread Operator。它允许可迭代对象(例如数组表达式或字符串)扩展,也可以在任何位置扩展对象表达式。这不仅适用于React,它是JavaScript运算符。
这里所有的答案都很有帮助,但我想列出最常用的实际使用场景Spread Syntax(扩展语法)的用例。
1. 合并数组(连接数组)
有各种各样的方法来组合数组,但扩展运算符允许您在数组的任何位置放置它。如果您想要合并两个数组并在数组中的任何位置放置元素,可以按如下方式执行:
var arr1 = ['two', 'three'];
var arr2 = ['one', ...arr1, 'four', 'five'];
// arr2 = ["one", "two", "three", "four", "five"]
2. 复制数组
过去我们想要复制一个数组时,通常使用 Array.prototype.slice()
方法。但是,你也可以使用扩展运算符来达到同样的效果。
var arr = [1,2,3];
var arr2 = [...arr];
// arr2 = [1,2,3]
3. 调用函数不使用Apply方法
在ES5中,要将一个由两个数字组成的数组传递给doStuff()
函数,通常会使用Function.prototype.apply()
方法,如下所示:
function doStuff (x, y, z) {}
var args = [0, 1, 2];
// Call the function, passing args
doStuff.apply(null, args);
然而,通过使用展开运算符,您可以将一个数组传递到函数中。
doStuff(...args);
4. 解构数组
您可以将解构和剩余运算符一起使用,将信息提取到变量中:
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
console.log(x); // 1
console.log(y); // 2
console.log(z); // { a: 3, b: 4 }
5. 函数参数作为 Rest 参数
ES6中也有三个点(...
),它表示一个 Rest 参数,将函数的所有剩余参数收集到一个数组中。
function f(a, b, ...args) {
console.log(args);
}
f(1, 2, 3, 4, 5); // [3, 4, 5]
6. 使用数学函数
任何使用拓展语法作为参数的函数,都可以被那些能够接受任意数量参数的函数所使用。
let numbers = [9, 4, 7, 1];
Math.min(...numbers); // 1
7. 合并两个对象
您可以使用扩展运算符来合并两个对象。这是一种更简单和更清晰的方法。
var carType = {
model: 'Toyota',
yom: '1995'
};
var carFuel = 'Petrol';
var carData = {
...carType,
carFuel
}
console.log(carData);
// {
// model: 'Toyota',
// yom: '1995',
// carFuel = 'Petrol'
// }
8. 将字符串拆分为单独字符
您可以使用展开操作符将字符串拆分为单独的字符。
let chars = ['A', ...'BC', 'D'];
console.log(chars); // ["A", "B", "C", "D"]
你可以考虑更多使用 Spread 运算符的方式。我在这里列出的是其流行用例。这是ES6的一个特性,在React中也使用。请看下面的例子:
function Sum(x, y, z) {
return x + y + z;
}
console.log(Sum(1, 2, 3)); // 6
如果我们最多只有三个参数,那么这种方法是可以的。但是,如果我们需要添加例如110个参数,应该怎么做呢?我们应该定义所有这些参数并逐个添加吗?
当然,有一种更简单的方法,称为展开运算符(spread)。 你不需要传递所有这些参数,而是写成:
function (...numbers){}
我们不知道有多少参数,但我们知道这些参数非常多。
基于ES6,我们可以将上述函数重写为下面的形式,并使用展开和映射使它变得异常简单:
let Sum = (...numbers) => {
return numbers.reduce((prev, current) => prev + current);
}
console.log(Sum(1, 2, 3, 4, 5, 6, 7, 8, 9)); // 45
向Brandon Morelli致敬。他在这里完美地解释了,但链接可能会失效,所以我只是粘贴下面的内容:
扩展语法就是三个点:...
它允许可迭代对象在期望0个或更多参数的地方进行扩展。
没有上下文的定义很难理解。让我们探索一些不同的用例来帮助理解这意味着什么。
看一下下面的代码。在此代码中,我们不使用扩展语法:
var mid = [3, 4];
var arr = [1, 2, mid, 5, 6];
console.log(arr);
在上面,我们创建了一个名为mid
的数组。 然后我们创建了第二个包含mid
数组的数组。 最后,我们记录输出结果。 你期望arr
会打印什么?点击上面的运行按钮查看发生了什么。这是输出:
[1, 2, [3, 4], 5, 6]
这是您预期的结果吗?
通过将 mid
数组插入到 arr
数组中,我们得到了一个数组内部的数组。如果这是目标,那就没问题了。但是如果您只想要一个包含1到6值的单个数组呢?为了实现这一点,我们可以使用拓展语法!请记住,拓展语法允许我们的数组元素扩展。
让我们看下面的代码。除了我们现在使用拓展语法将 mid
数组插入到 arr
数组中之外,其他都一样:
var mid = [3, 4];
var arr = [1, 2, ...mid, 5, 6];
console.log(arr);
当你点击运行按钮时,这是结果:
[1, 2, 3, 4, 5, 6]
太棒了!
还记得你刚才读到的扩展语法定义吗?这就是它发挥作用的地方。正如你所看到的,当我们创建arr
数组并在mid
数组上使用扩展运算符时,mid
数组不仅被插入,而且被展开。这个展开意味着mid
数组中的每个元素都会被插入到arr
数组中。结果是一个从1到6的数字单一数组,而不是嵌套的数组。
JavaScript具有内置的数学对象,可以让我们进行一些有趣的数学计算。在此示例中,我们将查看Math.max()
。如果您不熟悉,Math.max()
返回零或多个数字中最大的数字。以下是几个示例:
Math.max();
// -Infinity
Math.max(1, 2, 3);
// 3
Math.max(100, 3, 4);
// 100
若你想找到多个数字中的最大值,Math.max()
方法需要使用多个参数。不幸的是,你不能直接使用单个数组作为输入。在引入扩展语法之前,使用 .apply()
是在数组上使用 Math.max()
的最简单方式。
var arr = [2, 4, 8, 6, 0];
function max(arr) {
return Math.max.apply(null, arr);
}
console.log(max(arr));
它可以正常工作,但非常令人不爽。
现在看看我们如何使用扩展语法完全相同的功能:
var arr = [2, 4, 8, 6, 0];
var max = Math.max(...arr);
console.log(max);
不需要创建一个函数并使用apply方法返回Math.max()的结果,我们只需要两行代码! 展开语法扩展了数组元素,并将每个元素分别输入到
Math.max()方法中!
示例3-复制数组
在JavaScript中,您不能通过将新变量设置为已经存在的数组来仅仅复制一个数组。请考虑以下代码示例:
var arr = ['a', 'b', 'c'];
var arr2 = arr;
console.log(arr2);
当你按下运行按钮时,你将会得到如下输出:
['a', 'b', 'c']
乍一看,似乎它起作用了——似乎我们已经将arr的值复制到了arr2中。但事实并非如此。你知道,在JavaScript中处理对象(数组是一种对象类型)时,我们是按引用分配而不是按值分配的。这意味着arr2被赋予与arr相同的引用。换句话说,我们对arr2所做的任何操作也会影响原始的arr数组(反之亦然)。请看下面的例子:
var arr = ['a', 'b', 'c'];
var arr2 = arr;
arr2.push('d');
console.log(arr);
在上面的代码中,我们向arr2中添加了一个新元素d。然而,当我们输出arr的值时,你会发现d的值也被添加到了这个数组中:
['a', 'b', 'c', 'd']
不需要担心!我们可以使用展开运算符!考虑下面的代码。它几乎与上面的代码相同。不过这里我们在一对方括号中使用了展开运算符:
var arr = ['a', 'b', 'c'];
var arr2 = [...arr];
console.log(arr2);
点击“运行”,您将看到预期输出:
['a', 'b', 'c']
以上,arr中的数组值扩展为单个元素,然后分配给arr2。我们现在可以随意更改arr2数组而不会影响原始的arr数组:
var arr = ['a', 'b', 'c'];
var arr2 = [...arr];
arr2.push('d');
console.log(arr);
再说一遍,这个方法可行是因为数组arr的值被扩展来填充我们arr2数组定义的括号。因此,我们将arr2设置为等于arr的各个值,而不是像第一个示例中那样设置arr的引用。
额外示例-字符串转换成数组
作为最后一个有趣的示例,您可以使用展开语法将字符串转换为数组。只需在一对方括号内使用展开语法:
var str = "hello";
var chars = [...str];
console.log(chars);
对于想要简单快速理解的人:
首先,这不仅仅是React的语法。这是ES6中称为展开语法的语法,它可以迭代(合并、添加等)数组和对象。在这里阅读更多相关内容。
因此,回答这个问题:
假设你有这个标签:
<UserTag name="Supun" age="66" gender="male" />
而你需要做的是:
const user = {
"name": "Joe",
"age": "50"
"test": "test-val"
};
<UserTag name="Supun" gender="male" {...user} age="66" />
那么标签将等于这个:
<UserTag name="Joe" gender="male" test="test-val" age="66" />
因此,当您在React标签中使用扩展语法时,它会将标签的属性作为对象属性进行合并(如果存在则替换)给定的对象user
。此外,您可能已经注意到一件事情,即它只替换前面的属性,而不是后面的属性。因此,在这个例子中,age保持不变。
这只是在JSX中以一种不同的方式定义props!
它使用ES6中的...
数组和对象运算符(对象运算符尚不完全支持),因此基本上,如果您已经定义了您的props,您可以通过这种方式将其传递给您的元素。
所以在您的情况下,代码应该是这样的:
function yourA() {
const props = {name='Alireza', age='35'};
<Modal {...props} title='Modal heading' animation={false} />
}
所以您定义的道具现在已被分离并可以在需要时重用。
它等同于:
function yourA() {
<Modal name='Alireza' age='35' title='Modal heading' animation={false} />
}
以下是React团队对JSX中展开运算符的引用:
JSX展开属性 如果您预先知道要放在组件上的所有属性,那么使用JSX就很容易:
var component = <Component foo={x} bar={y} />;
修改 Props 是不好的
如果您不知道要设置哪些属性,可能会想在稍后将它们添加到对象中:
var component = <Component />;
component.props.foo = x; // bad
component.props.bar = y; // also bad
这是一个反模式,因为这意味着我们无法在更早的时候帮助您检查正确的propTypes。这意味着您的propTypes错误最终会出现具有神秘堆栈跟踪的情况。
props应该被视为不可变的。在其他地方突变props对象可能会导致意料之外的后果,所以在这一点上理想情况下它应该是一个被冻结的对象。var props = {};
props.foo = x;
props.bar = y;
var component = <Component {...props} />;
你传入的对象属性被复制到组件的props中。
你可以多次使用它或与其他属性组合使用。规范顺序很重要。后面的属性会覆盖之前的。
var props = { foo: 'default' };
var component = <Component {...props} foo={'override'} />;
console.log(component.props.foo); // 'override'
奇怪的 ... 符号是什么意思?对于来自Python世界的人,JSX Spread Attributes相当于解包参数列表(Python的**
操作符)。
我知道这是一个JSX问题,但有时候通过类比可以更快地理解它。
...
运算符在不同的语境中表现不同。在这个语境中,它是由 @T.J. Crowder 描述的“扩展”运算符。在另一个语境中,它也可能是由 @Tomas Nikodym 描述的“剩余”运算符。 - doub1ejackconst {a,b, ...rest} = obj
。现在,你有了一个新的obj/arr,其中包含除a、b之外的其余元素。 - Hayyaun