>  기사  >  웹 프론트엔드  >  타로와 리액트의 차이점은 무엇인가요?

타로와 리액트의 차이점은 무엇인가요?

青灯夜游
青灯夜游원래의
2020-11-13 10:41:083969검색

차이점: 1. Taro는 클래스 메서드에서 JSX 정의를 지원하지 않지만, React는 지원합니다. 2. Taro는 JSX 요소가 포함된 맵 루프에서 if 식을 사용할 수 없지만, React는 사용할 수 있습니다. 3. Taro는 Array.map을 사용할 수 없습니다. 외부 메서드는 JSX를 작동합니다. 배열이지만 반응할 수 있습니다.

타로와 리액트의 차이점은 무엇인가요?

Taro와 React의 차이점(브로슈어에서 재인쇄)

WeChat 애플릿의 한계로 인해 React의 일부 작성 방법과 기능은 아직 Taro에서 구현되지 않았으며 점차적으로 구현될 예정입니다. 앞으로는 개선될 것입니다. 본 책자가 발행된 시점에서 Taro의 최신 버전은 1.1이므로 다음 설명에서 기본 버전은 1.1입니다.

render() 이외의 메서드에서 JSX를 정의하는 것은 현재 지원되지 않습니다

WeChat 애플릿의 template은 값과 함수를 동적으로 전달할 수 없기 때문에 Taro는 현재 클래스 메서드에서 JSX 정의를 지원할 수 없습니다.

잘못된 사례

class App extends Component {
  _render() {
    return <view></view>
  }
}

class App extends Component {
  renderHeader(showHeader) {
    return showHeader && <header></header>
  }
}

class App extends Component {
  renderHeader = (showHeader) => {
    return showHeader& & <header></header>
  }
}

Solution
이 렌더 메소드에 정의되어 있습니다.

class App extends Component {

  render () {
    const { showHeader, showMain } = this.state
    const header = showHeader && <header></header>
    const main = showMain && <main></main>
    return (
      <view>
        {header}
        {main}
      </view>
    )
  }
}

JSX 요소가 포함된 맵 루프에서는 if 표현식을 사용할 수 없습니다.

잘못된 사례

numbers.map((number) => {
  let element = null
  const isOdd = number % 2
  if (isOdd) {
    element = <custom></custom>
  }
  return element
})

numbers.map((number) => {
  let isOdd = false
  if (number % 2) {
    isOdd = true
  }
  return isOdd && <custom></custom>
})

Solution
맵 루프에서 조건식이나 논리식을 사용해 보세요.

numbers.map((number) => {
  const isOdd = number % 2
  return isOdd ? <custom></custom> : null
})

numbers.map((number) => {
  const isOdd = number % 2
  return isOdd && <custom></custom>
})

JSX 배열을 조작하기 위해 Array.map 이외의 메소드를 사용할 수 없습니다.

Taro는 실제로 JSX를 애플릿의 문자열 템플릿으로 변환하고 기본 JSX 표현식은 실제로 요소(react)에 대한 React/Nerv 생성자입니다. - 요소), 기본 JSX의 모든 React 요소 세트에서 작업할 수 있습니다. 그러나 Taro에서는 map 메소드만 사용할 수 있으며 Taro는 이를 애플릿에서 wx:for로 변환합니다.

잘못된 상황

test.push(<view></view>)

numbers.forEach(numbers => {
  if (someCase) {
    a = <view></view>
  }
})

test.shift(<view></view>)

components.find(component => {
  return component === <view></view>
})

components.some(component => component.constructor.__proto__ === <view></view>.constructor)

numbers.filter(Boolean).map((number) => {
  const element = <view></view>
  return <view></view>
})

Solution
먼저 순회해야 할 배열을 처리한 후 처리된 배열로 맵 메서드를 호출합니다.

numbers.filter(isOdd).map((number) => <view></view>)

for (let index = 0; index  {
  return <view></view>
})

JSX 매개변수에 익명 함수를 사용할 수 없습니다.

잘못된 사례

<view> this.handleClick()} />

<view> this.handleClick(e)} />

<view> ({})} />

<view></view>

<view></view></view></view></view>

해결책
함수를 바인딩하려면 바인드 또는 클래스 매개변수를 사용하세요.

<view></view>

JSX 매개변수에서는 개체 확장기를 사용할 수 없습니다

WeChat 애플릿 구성 요소에서는 구성 요소에 전달된 각 매개 변수를 미리 설정해야 하지만 개체 확장기는 고정되지 않은 숫자 매개 변수로 동적으로 전달됩니다. 따라서 Taro가 이 기능을 지원할 방법은 없습니다.

잘못된 상황

<view></view>

<view></view>

해결책
개발자가 자신의 값을 할당합니다.

render () {
    const { id, title } = obj
    return <view></view>
}

JSX 매개변수(props)에 JSX 요소를 전달할 수 없습니다.

내장된 구성 요소화로 인해 WeChat 애플릿의 시스템은 속성(props)을 통해 기능을 전달할 수 없으며, props 전달 기능은 React 시스템의 기반 중 하나라고 할 수 있습니다. 자체 제작한 컴포넌트화 시스템은 내장된 컴포넌트화 슬롯 기능을 사용할 수 없습니다. 두 가지 힘 중 작은 힘일수록 당분간은 이 기능을 지원할 수 없습니다.

잘못된 상황

} />

 <view></view>} />

 }} />

 <view></view>)} />

해결책
props를 전달하거나 props.children을 통해 하위 구성 요소를 중첩하여 JSX 템플릿의 표시 콘텐츠를 미리 결정하세요.

상태 비저장 구성 요소를 지원하지 않습니다

WeChat의 제한된 템플릿 기능으로 인해 동적 값 전송 및 기능을 지원하지 않으므로 Taro는 현재 하나의 파일에서 하나의 구성 요소 정의만 지원합니다. 개발자 간의 혼란을 피하기 위해 Stateless Component 정의는 당분간 지원되지 않습니다.

잘못된 사례

function Test () {
  return <view></view>}function Test (ary) {
  return ary.map(() => <view></view>)}const Test = () => {
  return <view></view>}const Test = function () {
  return <view></view>}

해결 방법
클래스를 사용하여 구성 요소를 정의하세요.

class App extends Component {
  render () {
    return (
      <view></view>
    )
  }}

이름 지정 규칙
Taro 함수 이름 지정은 onClick과 같은 카멜식 이름 지정 방법을 사용합니다. WeChat 애플릿의 WXML은 전달 함수를 지원하지 않으므로 함수 이름은 컴파일 후 문자열 형식으로 WXML에 바인딩됩니다. WXML 제한 사항에 따라 함수 이름에는 세 가지 제한 사항이 있습니다.

메서드 이름에는 숫자가 포함될 수 없습니다.
메서드 이름은 밑줄로 시작하거나 끝날 수 없습니다.
메서드 이름의 길이는 20자를 초과할 수 없습니다.
그렇지 않으면 컴파일된 코드가 WeChat 애플릿에 다음 오류를 보고합니다.

타로와 리액트의 차이점은 무엇인가요?
ESLint 편집기 플러그인을 설치하는 것이 좋습니다
Taro에는 React와 약간 다른 몇 가지 작성 방법이 있습니다. ESLint 관련 편집기 플러그인을 설치하여 사용자 친화적인 프롬프트를 얻으세요. 다양한 편집자에 의해 설치되는 플러그인이 다르기 때문에 구체적인 설치 방법을 직접 검색해 보시기 바랍니다. 여기서는 자세한 내용을 다루지 않습니다. 아래와 같이 플러그인을 설치한 후 표시되는 메시지는 다음과 같습니다.

타로와 리액트의 차이점은 무엇인가요?
타로와 리액트의 차이점은 무엇인가요?
最佳编码方式
经过较长时间的探索与验证,目前 Taro 在微信小程序端是采用依托于小程序原生自定义组件系统来设计实现 Taro 组件化的,所以目前小程序端的组件化会受到小程序原生组件系统的限制,而同时为了实现以 React 方式编写代码的目标,Taro 本身做了一些编译时以及运行时的处理,这样也带来了一些值得注意的约束,所以有必要阐述一下 Taro 编码上的最佳实践。

组件样式说明
微信小程序的自定义组件样式默认是不能受外部样式影响的,例如在页面中引用了一个自定义组件,在页面样式中直接写自定义组件元素的样式是无法生效的。这一点,在 Taro 中也是一样,而这也是与大家认知的传统 Web 开发不太一样。

给组件设置 defaultProps
在微信小程序端的自定义组件中,只有在 properties 中指定的属性,才能从父组件传入并接收

Component({
  properties: {
    myProperty: { // 属性名
      type: String, // 类型(必填),目前接受的类型包括:String, Number, Boolean, Object, Array, null(表示任意类型)
      value: '', // 属性初始值(可选),如果未指定则会根据类型选择一个
      observer: function (newVal, oldVal, changedPath) {
         // 属性被改变时执行的函数(可选),也可以写成在 methods 段中定义的方法名字符串, 如:'_propertyChange'
         // 通常 newVal 就是新设置的数据, oldVal 是旧数据
      }
    },
    myProperty2: String // 简化的定义方式
  }
  ...
})

而在 Taro 中,对于在组件代码中使用到的来自 props 的属性,会在编译时被识别并加入到编译后的 properties 中,暂时支持到了以下写法

this.props.property

const { property } = this.props

const property = this.props.property

但是一千个人心中有一千个哈姆雷特,不同人的代码写法肯定也不尽相同,所以 Taro 的编译肯定不能覆盖到所有的写法,而同时可能会有某一属性没有使用而是直接传递给子组件的情况,这种情况是编译时无论如何也处理不到的,这时候就需要大家在编码时给组件设置 defaultProps 来解决了。

组件设置的 defaultProps 会在运行时用来弥补编译时处理不到的情况,里面所有的属性都会被设置到 properties 中初始化组件,正确设置 defaultProps 可以避免很多异常的情况的出现。

组件传递函数属性名以 on 开头
在 Taro 中,父组件要往子组件传递函数,属性名必须以 on 开头

// 调用 Custom 组件,传入 handleEvent 函数,属性名为 `onTrigger`
class Parent extends Component {

  handleEvent () {

  }

  render () {
    return (
      <custom></custom>
    )
  }
}

这是因为,微信小程序端组件化是不能直接传递函数类型给子组件的,在 Taro 中是借助组件的事件机制来实现这一特性,而小程序中传入事件的时候属性名写法为 bindmyevent 或者 bind:myevent

<!-- 当自定义组件触发“myevent”事件时,调用“onMyEvent”方法 -->
<component-tag-name></component-tag-name>
<!-- 或者可以写成 -->
<component-tag-name></component-tag-name>

所以 Taro 中约定组件传递函数属性名以 on 开头,同时这也和内置组件的事件绑定写法保持一致了。

小程序端不要在组件中打印传入的函数
前面已经提到小程序端的组件传入函数的原理,所以在小程序端不要在组件中打印传入的函数,因为拿不到结果,但是 this.props.onXxx && this.props.onXxx() 这种判断函数是否传入来进行调用的写法是完全支持的。

小程序端不要将在模板中用到的数据设置为 undefined
由于小程序不支持将 data 中任何一项的 value 设为 undefined ,在 setState 的时候也请避免这么用。你可以使用 null 来替代。

小程序端不要在组件中打印 this.props.children
在微信小程序端是通过 来实现往自定义组件中传入元素的,而 Taro 利用 this.props.children 在编译时实现了这一功能, this.props.children 会直接被编译成 标签,所以它在小程序端属于语法糖的存在,请不要在组件中打印它。

组件属性传递注意
不要以 id、class、style 作为自定义组件的属性与内部 state 的名称,因为这些属性名在微信小程序中会丢失。

组件 state 与 props 里字段重名的问题
不要在 state 与 props 上用同名的字段,因为这些被字段在微信小程序中都会挂在 data 上。

小程序中页面生命周期 componentWillMount 不一致问题
由于微信小程序里页面在 onLoad 时才能拿到页面的路由参数,而页面 onLoad 前组件都已经 attached 了。因此页面的 componentWillMount 可能会与预期不太一致。例如:

// 错误写法
render () {
  // 在 willMount 之前无法拿到路由参数
  const abc = this.$router.params.abc
  return <custom></custom>
}

// 正确写法
componentWillMount () {
  const abc = this.$router.params.abc
  this.setState({
    abc
  })
}
render () {
  // 增加一个兼容判断
  return this.state.abc && <custom></custom>
}

对于不需要等到页面 willMount 之后取路由参数的页面则没有任何影响。

组件的 constructor 与 render 提前调用
很多细心的开发者应该已经注意到了,在 Taro 编译到小程序端后,组件的 constructor 与 render 默认会多调用一次,表现得与 React 不太一致。

这是因为,Taro 的组件编译后就是小程序的自定义组件,而小程序的自定义组件的初始化时是可以指定 data 来让组件拥有初始化数据的。开发者一般会在组件的 constructor 中设置一些初始化的 state,同时也可能会在 render 中处理 state 与 props 产生新的数据,在 Taro 中多出的这一次提前调用,就是为了收集组件的初始化数据,给自定义组件提前生成 data ,以保证组件初始化时能带有数据,让组件初次渲染正常。

所以,在编码时,需要在处理数据的时候做一些容错处理,这样可以避免在 constructor 与 render 提前调用时出现由于没有数据导致出错的情况。

JS 编码必须用单引号
在 Taro 中,JS 代码里必须书写单引号,特别是 JSX 中,如果出现双引号,可能会导致编译错误。

环境变量 process.env 的使用
不要以解构的方式来获取通过 env 配置的 process.env 环境变量,请直接以完整书写的方式 process.env.NODE_ENV 来进行使用

// 错误写法,不支持
const { NODE_ENV = 'development' } = process.env
if (NODE_ENV === 'development') {
  ...
}

// 正确写法
if (process.env.NODE_ENV === 'development') {

}

预加载
在微信小程序中,从调用 Taro.navigateTo、Taro.redirectTo 或 Taro.switchTab 后,到页面触发 componentWillMount 会有一定延时。因此一些网络请求可以提前到发起跳转前一刻去请求。

Taro 提供了 componentWillPreload 钩子,它接收页面跳转的参数作为参数。可以把需要预加载的内容通过 return 返回,然后在页面触发 componentWillMount 后即可通过 this.$preloadData 获取到预加载的内容。

class Index extends Component {
  componentWillMount () {
    console.log('isFetching: ', this.isFetching)
    this.$preloadData
      .then(res => {
        console.log('res: ', res)
        this.isFetching = false
      })
  }

  componentWillPreload (params) {
    return this.fetchData(params.url)
  }

  fetchData () {
    this.isFetching = true
    ...
  }
}

小结
由于 JSX 中的写法千变万化,我们不能支持到所有的 JSX 写法,同时由于微信小程序端的限制,也有部分 JSX 的优秀用法暂时不能得到很好地支持。这些不支持的写法都可以通过其他写法来规避,同时 ESLint 相关插件都能很好地提醒用户避免踩坑。了解 Taro 这些注意事项后,接下来我们就来动手实现一个简单的 Todo 项目。

更多编程相关知识,请访问:编程学习网站!!

위 내용은 타로와 리액트의 차이점은 무엇인가요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.