React 电商项目

Flying
2019-02-18 / 0 评论 / 224 阅读 / 正在检测是否收录...

本项目需求功能Vue shop 相同,后端 API 也是一样的,使用的是 React 三件套:React、React Router 和 Redux。先对比一下最终效果吧,b本文主要就这两个项目说一说 React 与 Vue 的区别。

一、渲染不同

React 推荐通过 JSX 渲染模板。而 Vue 是更多时候和对 HTML 模板进行渲染。本质上,React 是在组件 JavaScript 代码中,通过原生 JavaScript 语法比如插值、条件,循环等、来实现模板,更加纯粹。React 通过 JavaScript 来操作一切:通过 JavaScript 来生成 html,所以设计了 JSX,甚至使用 JavaScript 来操作 CSS。它自身的 API 很小,得自己实现,幸好 React 的社区很活跃,不用什么都造轮子。所以说,React 的半门槛更高,更适合 JavaScript 基础更好的开发工程师。

看下面 CartControl 组件中 JSX 模板代码:

render() {
    return (
      <div className="cart-control">
        <div className="cart-decrease" title="减"
          onClick={this.decrement}>
          <span className="iconfont icon-remove-circle"></span>
        </div>
        <input className="cart-count" value={this.state.count}
          onChange={this.handleChange} />
        <div className="cart-add" title="加" onClick={this.increment}>
          <span className="iconfont icon-add-circle"></span>
        </div>
      </div>
    )
  }
}

可以看到 JSX 模板其实就是 ReactNode,作为 render 方法的返回值使用的。状态及方法更接近原生 JavaScript 写法,绑定它们时仍然用到 this。因为 JSX 的本质是 JavaScript,此处的上下文就是组件本身。重要的事再强调一下, JSX 的本质是 JavaScript,得按 JavaScript 的方式来处理。

需要注意的是:

react 元素的事件处理和 DOM 元素的很相似,但是有一点语法上的不同:

  1. React 事件的命名采用小驼峰式(camelCase),而不是纯小写。
  2. 使用 JSX 语法时你需要传入一个函数作为事件处理函数,而不是一个字符串。

Vue 的单文件组件 JavaScript 代码和 HTML、CSS 样式都是分离的,对模板的操作通过指令来实现的,比如条件语句就需要 v-if 来实现对这一点,Vue 借鉴了 Angular 的做法,因此更适合有设计基础的开发工程师。Vue 自身的 API 很多,更像是一个是 MVVM 框架,有后端开发经验的同学理解起来也很容易。换名话说,Vue 的学习曲线要平滑得多。

如 CartControl 组件中 HTML 模板代码:

<div class="cart-control">
  <div class="cart-decrease" title="减"
    @click.stop.prevent="decrement(product)">
    <span class="iconfont icon-remove-circle"></span>
  </div>
  <input class="cart-count" :value="count"
    @input="inputHandler"></input>
  <div class="cart-add" title="加" @click.stop.prevent="increment(product)">
    <span class="iconfont icon-add-circle"></span>
  </div>
</div>

注意到没有,这个模板用到了 v-bindv-on 指令,使用的是简写方式,这些指令甚至有自己的修饰符。绑定状态及方法时不用上下 this,在 Vue 的 mount 生命周期中,template 会被编译成 AST 语法树。感兴趣的可以深入去了解一下。另外,借助 transform-vue- JSX 插件,Vue 项目是也可以使用 JSX。

二、组件写法不同

React 是类组件写法,也可以使用函数组件。如下面的代码:

class CartControl extends Component {
  constructor(props) {
    super(props);
    this.state = {
      count: props.product.quantity || 1
    }
    this.handleChange = this.handleChange.bind(this)
    this.increment = this.increment.bind(this)
    this.decrement = this.decrement.bind(this)
  }

  static propTypes = {
    product: PropTypes.object.isRequired,
    added: PropTypes.number.isRequired,
    needConfirmed: PropTypes.bool
  }

  increment(e) {
    e.preventDefault()
    const { product, needConfirmed, added } = this.props
    let count = this.state.count;
    let max = count
    if (needConfirmed) {
      max = this.state.count + added;
    }
    if (max < product.inventory) {
      this.setState({ count: ++count });
      this.watchCount(count)
    }
  }
  ...
  render() {
    return (
      <div className="cart-control">
        <div className="cart-decrease" title="减"
          onClick={this.decrement}>
          <span className="iconfont icon-remove-circle"></span>
        </div>
        <input className="cart-count" value={this.state.count}
          onChange={this.handleChange} />
        <div className="cart-add" title="加" onClick={this.increment}>
          <span className="iconfont icon-add-circle"></span>
        </div>
      </div>
    )
  }
}

export default connect(state => state.cart, { willUpdateItem, updateCartItem })(CartControl)

React 就是 ES6 的写法:类、方法、属性,很纯粹。

注意:事件方法一般要在类组件的构造函数中绑定,否则访问不到 this。

而 vue 是声明式的写法,通过在字变量对象对象中设置 mixinsdirectives、propsdatacomputed、生命周期方法、watchmethods 自定义方法来定义组件。

export default {
  name: 'CartControl',
  props: {
    product: {
      type: Object,
      default: function(){}
    }
    ...
  },

  data() {
    return {
      count: this.product.quantity || 1
    }
  },

  watch: {
    count: function(count) {
      if (this.needConfirmed) {
        this.$store.commit('willUpdateCartItem', count)
      } else {
        this.$store.commit('updateCartItem', {
            id: this.product._id,
            count: count
          }
        )
      }
    }
  },

  methods: {
    increment() {
      let max = this.count
      if (this.needConfirmed) {
        max = this.count + this.added;
      }
      if (max < this.product.inventory) {
        this.count++
      }
    }
    ...
}
</script>

所以 react 组件很纯粹,和 Typescript 整合更容易,vue 整合起来稍微复杂。

三、数据流的不同

React 一直不支持双向绑定,提倡的是单向数据流,称之为 onChange/setState 模式。不能对修改 props,如图所示:

React 数据流

Vue 也提倡单向数据流,但通过向父组件 emit 一个事件,或者借助 v-model 实现父子组件双向绑定了,这对于一些特殊场景,比如处理表表单也是很有用的。

注意:新版的 Vue 也不鼓励组件对自己的 props 进行任何修改。

四、监听数据变化的实现不同

Vue 将遍历此 data 对象所有的 property,并使用 Object.defineProperty 通过 getter/setter 以及一些函数的劫持追踪依赖。详见深入响应式原理。正是因为 Vue 会跟踪每一个组件的依赖关系,不需要重新渲染整个组件树,因此可以更快地计算出 VDOM 差异。

React 默认是通过比较引用的方式(diff)进行的,在应用的状态被改变时,全部子组件都会重新渲染。它是为大项目而生的,如果不优化可能导致大量不必要的 VDOM 的重新渲染,甚至还没有直接操作 DOM 来得快。

Vue 的实现简单很多,Vue 使用的是可变数据,可以对 data 对象随意修改。而 React 更强调数据的不可变,对状态的修改必须要用 setState 方法。

React 是这样修改的:

handleChange(e) {
  let val = e.target.value
  // Should be a positive integer
  if (/^[1-9]\d*$/.test(val) && val <= this.props.product.inventory) {
    this.setState({ count: parseInt(val) })
    this.watchCount(val)
  } else {
    e.target.value = this.state.count
  }
}

vue 是这样实现的,

inputHandler(e) {
  let val = e.target.value
  // Should be a positive integer
  if (/^[1-9]\d*$/.test(val) && val < this.product.inventory) {
    this.count = parseInt(val)
  } else {
    e.target.value = this.count
  }
}

五、Redux 和 Vuex 的联系区别

本质上,Redux 和 Vuex 都是对 MVVM 思想的服务,将数据从视图中抽离的一种方案。它们都使用单一的数据源,用了设计模式中的观察者模式或者说发布/订阅模式。在 React 中,initState 相当于 event 对象,dispatch 相当于 trigger 方法, dispatch 函数则相当于订阅的事件。在 Vuex 中,$store 相当于 event 对象,store.commit 相当于 trigger 方法, mutation 中的函数名则相当于订阅的事件。Vuex 借鉴了 Redux,将 store 作为全局的数据中心进行数据管理。

Redux 数据流向:
View –> Actions –> Reducer –> State 变化 –> View变化(同步异步一样)

Vuex 的数据流向:

View –> Commit –> Mutations –> State 变化 –> View 变化(同步操作)

View –> Dispatch –> Actions –> Mutations –> State 变化 –> View变化(异步操作)

  1. 在 Redux 中,我们每一个组件都需要显示的用 connect 把需要的 props 和 dispatch 连接起来。在 Vuex 中,$store 被直接注入到了组件实例中,因此可以比较灵活的使用;
  2. Vuex 改进了 Redux 中的 Action 和 Reducer 函数,以 Mutations 变化函数取代 Reducer,无需 switch,只需在对应的 Mutation 函数里改变 state 值就可以;
  3. Vuex 只能配合 Vue 使用,Redux 可以整合到任何框架中;
  4. 而 Redux 中没有异步操作的 API,得借助 redux-thunk 来实现,Vuex 中可以直接使用 Action 进行异步操作;
  5. 而 Redux 是没有 module 化功能,Vuex 自带就有。
  6. React 和 Vue 中的路由基本上是一样,Vue Router 借鉴了 React Router,核心组件、配置和 API 都差不多。
React 和 Vue 的设计思想是不一样的,前者是映射思维,后者是模板思维。在映射思维的世界观里, JavaScript 数据是唯一的实质。在模板思维看来,html 模板和 JavaScript 数据都是实质,二者是并列的关系;

相关链接

3

评论 (0)

取消