与我使用的其他框架相比,我最喜欢 React 的原因之一就是它对 JavaScript 的暴露程度。没有模板DSL( JSX 编译为合理的 JavaScript),组件 API 只是通过添加 React Hooks 变得更简单,并且该框架为解决的核心 UI 问题提供非常少的抽象概念。

因此,学习 JavaScript 对于使用 React 有效构建应用程序是非常可取的。所以这里有一些 JavaScript 功能,我建议你花一些时间学习,这样你就可以尽可能有效地使用 React。

模板文字

模板文字就像具有超能力的字符串:

 1const greeting = 'Hello' 2const subject = 'World' 3console.log(`${greeting} ${subject}!`) // Hello World! 4 5// this is the same as: 6console.log(greeting + ' ' + subject + '!') 7 8// in React: 9function Box({className, ...props}) {10  return <div className={`box ${className}`} {...props} />11}12

MDN:模板文字(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals)

简写属性名

很常见并且有用,我直到现在都没有想到可以这样做。

 1const a = 'hello' 2const b = 42 3const c = {d: [true, false]} 4console.log({a, b, c}) 5 6// this is the same as: 7console.log({a: a, b: b, c: c}) 8 9// in React:10function Counter({initialCount, step}) {11  const [count, setCount] = useCounter({initialCount, step})12  return <button onClick={setCount}>{count}</button>13}

MDN:ECMAScript 2015中对象初始化的新表示法(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer#New_notations_in_ECMAScript_2015)

箭头函数

箭头函数是在 JavaScript 中另一种编写函数的方法,但它们确实存在一些语义差异。幸运的是我们在 React 的土地上,如果在项目中使用hook(而不是类)就不必担心 this,但是箭头函数允许更复杂的匿名函数和隐式返回,所以你会看到并想要充分利用箭头的功能。

 1const getFive = () => 5 2const addFive = a => a + 5 3const divide = (a, b) => a / b 4 5// this is the same as: 6function getFive() { 7  return 5 8} 9function addFive(a) {10  return a + 511}12function divide(a, b) {13  return a / b14}1516// in React:17function TeddyBearList({teddyBears}) {18  return (19    <ul>20      {teddyBears.map(teddyBear => (21        <li key={teddyBear.id}>22          <span>{teddyBear.name}</span>23        </li>24      ))}25    </ul>26  )27}

MDN:箭头函数(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions)

解构

解构可能是我最喜欢的 JavaScript 功能。我一直在构造对象和数组(如果你使用 useState,可能也是如此,就像这样【https://kentcdodds.com/blog/react-hooks-array-destructuring-fundamentals】)。我喜欢它的陈述性。

 1// const obj = {x: 3.6, y: 7.8} 2// makeCalculation(obj) 3 4function makeCalculation({x, y: d, z = 4}) { 5  return Math.floor((x + d + z) / 3) 6} 7 8/ this is the same as 9function makeCalculation(obj) {10  const {x, y: d, z = 4} = obj11  return Math.floor((x + d + z) / 3)12}1314// which is the same as15function makeCalculation(obj) {16  const x = obj.x17  const d = obj.y18  const z = obj.z === undefined ? 4 : obj.z19  return Math.floor((x + d + z) / 3)20}2122// in React:23function UserGitHubImg({username = 'ghost', ...props}) {24  return <img src={`https://github.com/${username}.png`} {...props} />25}26

MDN:解构分配(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)

 一等要去阅读 MDN 文章,你肯定能够学到新东西。当你完成后,尝试用单行解构:
1function nestedArrayAndObject() { 2  // refactor this to a single line of destructuring... 3  const info = { 4    title: 'Once Upon a Time', 5    protagonist: { 6      name: 'Emma Swan', 7      enemies: [ 8        {name: 'Regina Mills', title: 'Evil Queen'}, 9        {name: 'Cora Mills', title: 'Queen of Hearts'},10        {name: 'Peter Pan', title: `The boy who wouldn't grow up`},11        {name: 'Zelena', title: 'The Wicked Witch'},12      ],13    },14  }15  // const {} = info // <-- replace the next few `const` lines with this16  const title = info.title17  const protagonistName = info.protagonist.name18  const enemy = info.protagonist.enemies[3]19  const enemyTitle = enemy.title20  const enemyName = enemy.name21  return `${enemyName} (${enemyTitle}) is an enemy to ${protagonistName} in "${title}"`22}

参数默认值

这是另一个我一直在用的功能:一种以声明方式表达函数默认值的非常强大的方法。

 1// add(1) 2// add(1, 2) 3function add(a, b = 0) { 4  return a + b 5} 6 7// is the same as 8const add = (a, b = 0) => a + b 910// is the same as11function add(a, b) {12  b = b === undefined ? 0 : b13  return a + b14}1516// in React:17function useLocalStorageState({18  key,19  initialValue,20  serialize = v => v,21  deserialize = v => v,22}) {23  const [state, setState] = React.useState(24    () => deserialize(window.localStorage.getItem(key)) || initialValue,25  )2627  const serializedState = serialize(state)28  React.useEffect(() => {29    window.localStorage.setItem(key, serializedState)30  }, [key, serializedState])3132  return [state, setState]33}

MDN:默认参数(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters)

Rest/Spread

...语法可以被认为是一种“集合”语法,它在一组值上运行。我一直都在使用,强烈建议你也学习。它实际上在不同的环境中有不同的含义,因此学习那些细微差别会对你有所帮助。

1const arr = [5, 6, 8, 4, 9] 2Math.max(...arr) 3// is the same as 4Math.max.apply(null, arr) 5 6const obj1 = { 7  a: 'a from obj1', 8  b: 'b from obj1', 9  c: 'c from obj1',10  d: {11    e: 'e from obj1',12    f: 'f from obj1',13  },14}15const obj2 = {16  b: 'b from obj2',17  c: 'c from obj2',18  d: {19    g: 'g from obj2',20    h: 'g from obj2',21  },22}23console.log({...obj1, ...obj2})24// is the same as25console.log(Object.assign({}, obj1, obj2))2627function add(first, ...rest) {28  return rest.reduce((sum, next) => sum + next, first)29}30// is the same as31function add() {32  const first = arguments[0]33  const rest = Array.from(arguments).slice(1)34  return rest.reduce((sum, next) => sum + next, first)35}3637// in React:38function Box({className, ...restOfTheProps}) {39  const defaultProps = {40    className: `box ${className}`,41    children: 'Empty box',42  }43  return <div {...defaultProps} {...restOfTheProps} />44}45

MDN:Spread语法(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax)

MDN:Rest 参数(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters)

ESModules

如果你正在使用现代工具构建自己的程序,它应该能够支持模块,了解语法怎样工作是个好主意,因为所有的甚至微不足道的程序都可能需要使用模块来重用代码。

1export default function add(a, b) { 2  return a + b 3} 4 5/* 6 * import add from './add' 7 * console.assert(add(3, 2) === 5) 8 */ 910export const foo = 'bar'1112/*13 * import {foo} from './foo'14 * console.assert(foo === 'bar')15 */1617export function subtract(a, b) {18  return a - b19}2021export const now = new Date()2223/*24 * import {subtract, now} from './stuff'25 * console.assert(subtract(4, 2) === 2)26 * console.assert(now instanceof Date)27 */2829// in React:30import React, {Suspense, Fragment} from 'react'

MDN:import(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import)

MDN:export(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export)

三元表达式

我喜欢三元表达式。他们的声明很漂亮。特别是在 JSX 中。

1const message = bottle.fullOfSoda 2  ? 'The bottle has soda!' 3  : 'The bottle may not have soda :-(' 4 5// is the same as 6let message 7if (bottle.fullOfSoda) { 8  message = 'The bottle has soda!' 9} else {10  message = 'The bottle may not have soda :-('11}1213// in React:14function TeddyBearList({teddyBears}) {15  return (16    <React.Fragment>17      {teddyBears.length ? (18        <ul>19          {teddyBears.map(teddyBear => (20            <li key={teddyBear.id}>21              <span>{teddyBear.name}</span>22            </li>23          ))}24        </ul>25      ) : (26        <div>There are no teddy bears. The sadness.</div>27      )}28    </React.Fragment>29  )30}31
   我意识到,在 prettier 出现并清理我们的代码之前,一些人不得不花时间弄清楚三元运算符是怎么回事,这让三元表达式变得令人反感。如果你还没有使用 prettier,我强烈建议你这样做。prettier 将使你的三元表达式更容易阅读。

MDN:条件(三元)运算符(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator)

数组方法

数组很棒,我一直使用数组方法!以下是我常用的方法:

  • find

  • some

  • every

  • includes

  • map

  • filter

  • reduce

这里有些例子:

 1const dogs = [ 2  { 3    id: 'dog-1', 4    name: 'Poodle', 5    temperament: [ 6      'Intelligent', 7      'Active', 8      'Alert', 9      'Faithful',10      'Trainable',11      'Instinctual',12    ],13  },14  {15    id: 'dog-2',16    name: 'Bernese Mountain Dog',17    temperament: ['Affectionate', 'Intelligent', 'Loyal', 'Faithful'],18  },19  {20    id: 'dog-3',21    name: 'Labrador Retriever',22    temperament: [23      'Intelligent',24      'Even Tempered',25      'Kind',26      'Agile',27      'Outgoing',28      'Trusting',29      'Gentle',30    ],31  },32]3334dogs.find(dog => dog.name === 'Bernese Mountain Dog')35// {id: 'dog-2', name: 'Bernese Mountain Dog', ...etc}3637dogs.some(dog => dog.temperament.includes('Aggressive'))38// false3940dogs.some(dog => dog.temperament.includes('Trusting'))41// true4243dogs.every(dog => dog.temperament.includes('Trusting'))44// false4546dogs.every(dog => dog.temperament.includes('Intelligent'))47// true4849dogs.map(dog => dog.name)50// ['Poodle', 'Bernese Mountain Dog', 'Labrador Retriever']5152dogs.filter(dog => dog.temperament.includes('Faithful'))53// [{id: 'dog-1', ..etc}, {id: 'dog-2', ...etc}]5455dogs.reduce((allTemperaments, dog) => {56  return [...allTemperaments, ...dog.temperaments]57}, [])58// [ 'Intelligent', 'Active', 'Alert', ...etc ]5960// in React:61function RepositoryList({repositories, owner}) {62  return (63    <ul>64      {repositories65        .filter(repo => repo.owner === owner)66        .map(repo => (67          <li key={repo.id}>{repo.name}</li>68        ))}69    </ul>70  )71}

MDN:Array(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)

Promises 和 async/await

这是一个很大的主题,可以在它们身上多花一些时间。Promises 在 JavaScript 生态中无处不在,并且由于 React在该生态系统中的根深蒂固,它们几乎到处都是(事实上,React 本身在内部也在使用 promises)。

Promises 可帮助你管理异步代码。Async/await 语法是处理 promises 的特殊语法。这两者是相辅相成的。

1function promises() { 2  const successfulPromise = timeout(100).then(result => `success: ${result}`) 3 4  const failingPromise = timeout(200, true).then(null, error => 5    Promise.reject(`failure: ${error}`), 6  ) 7 8  const recoveredPromise = timeout(300, true).then(null, error => 9    Promise.resolve(`failed and recovered: ${error}`),10  )1112  successfulPromise.then(log, logError)13  failingPromise.then(log, logError)14  recoveredPromise.then(log, logError)15}1617function asyncAwaits() {18  async function successfulAsyncAwait() {19    const result = await timeout(100)20    return `success: ${result}`21  }2223  async function failedAsyncAwait() {24    const result = await timeout(200, true)25    return `failed: ${result}`26  }2728  async function recoveredAsyncAwait() {29    let result30    try {31      result = await timeout(300, true)32      return `failed: ${result}` // this would not be executed33    } catch (error) {34      return `failed and recovered: ${error}`35    }36  }3738  successfulAsyncAwait().then(log, logError)39  failedAsyncAwait().then(log, logError)40  recoveredAsyncAwait().then(log, logError)41}4243function log(...args) {44  console.log(...args)45}4647function logError(...args) {48  console.error(...args)49}5051// This is the mothership of all things asynchronous52function timeout(duration = 0, shouldReject = false) {53  return new Promise((resolve, reject) => {54    setTimeout(() => {55      if (shouldReject) {56        reject(`rejected after ${duration}ms`)57      } else {58        resolve(`resolved after ${duration}ms`)59      }60    }, duration)61  })62}6364// in React:65function GetGreetingForSubject({subject}) {66  const [isLoading, setIsLoading] = React.useState(false)67  const [error, setError] = React.useState(null)68  const [greeting, setGreeting] = React.useState(null)6970  React.useEffect(() => {71    async function fetchGreeting() {72      try {73        const response = await window.fetch('https://example.com/api/greeting')74        const data = await response.json()75        setGreeting(data.greeting)76      } catch (error) {77        setError(error)78      } finally {79        setIsLoading(false)80      }81    }82    setIsLoading(true)83    fetchGreeting()84  }, [])8586  return isLoading ? (87    'loading...'88  ) : error ? (89    'ERROR!'90  ) : greeting ? (91    <div>92      {greeting} {subject}93    </div>94  ) : null95}

MDN:Promise(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)

MDN:async function(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function)

MDN:await(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await)

结论

当然有许多语言功能在构建 React 应用时很有用,这些是我最喜欢的,我发现自己一次又一次地使用它们。希望对你有帮助。

原文:https://kentcdodds.com/blog/javascript-to-know-for-react

©著作权归作者所有:来自51CTO博客作者mb5ff980b461ced的原创作品,如需转载,请注明出处,否则将追究法律责任

更多相关文章

  1. 用 await/async 正确链接 Javascript 中的多个函数[每日前端夜话
  2. 用原生 JavaScript 实现十大 jQuery 函数[每日前端夜话0x94]
  3. shell脚本之灵活调用函数技巧
  4. 函数式编程思维在三行代码情书中的应用
  5. 关于 Hive开窗函数
  6. string.h中部分函数的实现
  7. 学习C的第三天-函数
  8. SQL今日一题(11):窗口函数
  9. 为什么说 Python 内置函数并不是万能的?

随机推荐

  1. Unity3d和iOS、Android的混合开发介绍
  2. android 安卓事件处理示例
  3. 第3.2.1节 android基本视图
  4. android 自定义图片剪裁
  5. TextView跑马灯
  6. (Android) Download Images by AsyncTask
  7. android customactivityoncrashchau 程序
  8. android   CheckBox 用法
  9. android照相及照片上传
  10. Android第五期 - 更新自己的apk本地与网