2017-05-20 24 views
2

我正在从这个tutorial学习Redux,我不明白下面的spread运算符如何在对象和数组中都起作用。如果...state返回相同的东西,它如何在两种情况下工作?我认为它只会返回一个数组,因此它将在SHUTTER_VIDEO_SUCCESS内工作,因为除了action.videos之外,它会将状态内的任何内容传播到新数组中,但如何在SELECTED_VIDEO案例中工作?没有放置它的钥匙。扩展运算符抓取的数组不是来自默认initialState的键值对吗?传播运算符如何在数组与obj中工作?

initialState.js

export default { 
    images: [], 
    videos: [] 
}; 

someComponent.js

import initialState from './initialState'; 
import * as types from 'constants/actionTypes'; 

export default function (state = initialState.videos, action) { 
    switch (action.type) { 
    case types.SELECTED_VIDEO: 
     return { ...state, selectedVideo: action.video } 
    case types.SHUTTER_VIDEO_SUCCESS: 
     return [...state, action.videos]; 
    default: 
     return state; 
    } 
} 
+2

['...'不是操作符!](https://stackoverflow.com/questions/37151966/what-is-spreadelement- in-ecmascript-documentation-it-the-same-as-spread-oper/37152508#37152508) –

回答

0

阵列也是一个键/值对的,但关键是一个索引。它使用ES6 destructuringspread syntax

Redux docs on the subject

您可能还需要在ES6属性值速记读了(或任何它被称为):

ES6 Object Literal in Depth

当你发现自己分配一个匹配属性值属性名称,您可以省略属性值,它隐含在ES6中。

+0

['...'不是操作符!](https://stackoverflow.com/questions/37151966/什么是spreadelement-in-ecmascript-documentation-it-the-same-as-spread-oper/37152508#37152508) –

+0

@FelixKling你说得对,把它改为“传播语法”,谢谢!实际上没有想到我为什么称它为操作员,只是因为其他许多人才这么做。 – rymdmaskin

+0

那么'SELECTED_VIDEO'返回什么?状态最初是一个数组如何传播到一个对象?它会然后是'{0:[...],selectedVideo:action.video}'? – stackjlei

0

按照教程:

创建反应的应用程序内预装了巴贝尔,插件变换对象,其余的扩展,让您使用传播(...)运算符来复制枚举的属性从一个对象到另一个以简洁的方式。对于上下文,{... state,videos:action.videos}计算为Object.assign({},state,action.videos)。

所以,这不是ES6的功能。它使用一个插件让你使用该功能。

链接:https://babeljs.io/docs/plugins/transform-object-rest-spread/

+0

你解决了如何传播语法如何处理对象中的对象,但我的问题是它如何处理对象中的数组 – stackjlei

+0

@stackjlei在SELECTED_VIDEO的情况下,返回一个对象。 –

4

UPDATE

传播语法允许你传播的数组对象(数组是技术上对象,主要是在JS一切)。将数组分散到对象中时,它将为每个数组项添加一个key: value对,其中键是索引,值是存储在数组中索引中的值。例如:

const arr = [1,2,3,4,5] 
const obj = { ...arr } // { 0: 1, 1: 2, 2: 3, 3: 4, 4: 5 } 

const arr2 = [{ name: 'x' }, { name: 'y' }] 
const obj2 = { ...arr2 } // { 0: { name: 'x' }, 1: { name: 'y' } } 

您还可以将字符串分散到数组和对象中。对于数组,它的行为类似于String.prototype.split

const txt = 'abcdefg' 
const arr = [...txt] // ['a','b','c','d','e','f', 'g'] 

对于对象,它会通过字符分割字符串,并通过索引键分配:

const obj = { ...txt } // { 0:'a',1:'b',2:'c',3:'d',4:'e',5:'f',6:'g' } 

所以,你可能会得到的数据排序作品当你将一个数组扩展到一个对象时。但是,如果您提供的示例是您实际使用的示例,那么您将遇到问题。见下文。

=============

在终极版减速的情况下,当您使用传播语法使用数组它传播从阵列中的每个项目进入一个新的数组。它基本上与使用concat

const arr = [1,2,3] 
const arr2 = [4,5,6] 
const arr3 = [...arr, ...arr2] // [1,2,3,4,5,6] 
// same as arr.concat(arr2) 

与对象,传播语法蔓延从一个对象key: value对到另一个:

const obj = { a: 1, b: 2, c: 3 } 
const newObj = { ...obj, x: 4, y: 5, z: 6 } 
// { a: 1, b: 2, c: 3, x: 4, y: 5, z: 6 } 

这两种方式来帮助保护您的数据不变的你减速。扩展语法复制数组项或对象键/值而不是引用它们。如果在数组中嵌套对象或对象进行任何更改,则必须考虑到这一点,以确保获得新副本而不是突变数据。

如果您有数组作为对象键,那么您可以将整个对象分散到一个新对象中,然后根据需要覆盖各个键,包括需要使用扩展语法更新的数组。例如,对示例代码的更新:

const initialState = { 
    images: [], 
    videos: [], 
    selectedVideo: '' 
} 

// you need all of your initialState here, not just one of the keys 
export default function (state = initialState, action) { 
    switch (action.type) { 
    case types.SELECTED_VIDEO: 
     // spread all the existing data into your new state, replacing only the selectedVideo key 
     return { 
     ...state, 
     selectedVideo: action.video 
     } 
    case types.SHUTTER_VIDEO_SUCCESS: 
     // spread current state into new state, replacing videos with the current state videos and the action videos 
     return { 
     ...state, 
     videos: [...state.videos, ...action.videos] 
     } 
    default: 
     return state; 
    } 
} 

这显示更新状态对象以及作为数组的对象的特定键。

在你给的例子中,你正在改变你的状态结构。它以一个数组开始,然后有时返回一个数组(当SHUTTER_VIDEO_SUCCESS时)并且有时返回一个对象(当SELECTED_VIDEO时)。如果你想拥有一个reducer功能,你不会将你的initialState隔离到视频阵列。您需要手动管理所有状态树,如上所示。但是您的reducer可能不应该根据操作切换回送的数据类型。那将是一个不可预知的混乱。

如果您想将每个按键分解为单独的缩减器,您可以使用3个(图像,视频和selectedVideo)并使用combineReducers来创建状态对象。

import { combineReducers } from 'redux' 
// import your separate reducer functions 

export default combineReucers({ 
    images, 
    videos, 
    selectedVideos 
}) 

在这种情况下,每当您调度一个动作来生成完整的状态对象时,每个reducer都会运行。但是每个reducer只会处理它的特定键,而不是整个状态对象。所以你只需要数组更新逻辑的键是

+0

['...'不是操作符!](https://stackoverflow.com/questions/37151966/what-is-spreadelement-in-ecmascript-documentation-is-it-the-same-as-spread- oper/37152508#37152508) –

+0

当然。编辑为更新到语法 – shadymoses

+0

您解决了传播语法如何处理数组中的数组和对象中的对象,但是我的问题是它如何与对象中的数组一起工作 – stackjlei