React対VUEの限界点(1)

序文

初めて大きな工場に入ったとき、どうしてもReactに出会いました。あらゆるためらい、ためらい、ためらいの後、彼はまだ彼を受け入れるしかありませんでした。この記事では主に、vueテクノロジースタックから反応する100の悲しみを紹介します。VUEとReactを包括的に比較したかったので、単純な命題のようですが、この記事を書くのは本当に難しいです。この記事は、自分の才能と10日間以上の反応経験を組み合わせて、多くの情報を参照した後に作成しました。記事に含まれるいくつかの未熟な見解については、訂正のためのメッセージを残していただければ幸いです。
在这里插入图片描述

同じ点:

次のように、2つの主な機能のほとんどは同じです。

  • 仮想DOM、すばやくDOMを変更
  • コンポーネント開発
  • レスポンシブコンポーネント
  • サーバー側レンダリング
  • アプリケーション開発ファミリーバケット:ルーティング+状態管理+パッケージングなど

この記事では主に、コーディングレベルから実装レベル、アプリケーションレベルまで、ReactとVueの比較について説明します。

差:

1.ファイル構造

a)vueは.vueで終わるファイルを使用します

一般に、vueファイルはコンポーネントを記述し、対応するコンテンツ要素はtemplate+ script+ styleルートタグブロックでラップされます。templatedom構造をscript部分的に説明し、部分的にロジックを記述し、styleコンテンツのスタイルを記述します。編成は非常に明確です。これは伝統を受け入れる方法であり、開発者にとって比較的フレンドリーです。

<template>
  <div>
    <i-input style="width:200px" v-model="value"></i-input>
    <span>{
    
    {
    
    value}}</span>
  </div>
</template>
<script>
export default {
    
    
  data: function() {
    
    
    return {
    
    
      value: "test"
    };
  },
  name: "home",
  components: {
    
    },
  mounted() {
    
    }
};
</script>
<style>
@import url(../style/home.less);
</style>
b)Reactは.jsxで終わるファイルを使用します

Reactは従来のes6モジュール化手法を使用してコンポーネントを説明します。コンポーネントはクラスであり、コンポーネントのプロパティとステータスはクラスで記述されます。最後に、htmlテンプレートコンポーネントがrender関数で返されます。Reactでは、すべてがjsオブジェクトです。したがって、スタイルもcss_moduleによって要素に追加されます。

import React from 'react';
import ReactDOM from 'react-dom';
import {
    
     DatePicker } from 'antd';
import {
    
    cssObj} from '/style/index.css'
class Text extends React.Component {
    
    
    render() {
    
    
        return (
            <div>
	            <p className={
    
    cssObj.p}>This is a react Component123451s</p>
	            <div className = "my-image" ></div>
	            <DatePicker/>
            </div>
        );
    }
}
export default Text;

2、テンプレート構文

vue采用模板语法,react采用JSX来编写DOM, 模板语法是在HTML中加入一些赋值markup,而JSX语法是将JS代码与DOM标签混合在一起使用. 对于没有接触过两者的前端开发来说,模板语法更容易理解,上手快,且结构简单,编写容易. 具体区别见下面的例子:

a) VUE模板语法

采用HTML + moustache(双大括号赋值) + 指令的模板语法, 易学,简单,上手非常快.(也支持JSX, 但推荐使用模板语法)

指令: 接收表达式,当表达式变化时,响应式的作用在DOM上.

<div class="todo-list">
  <h3>待办列表</h3>
  <ul class="todo-ul">
    <li v-for="(item, key, index) in todoList" :key="key" 
      :id="key" @click="clickTask(key)" :class="{success: item.status}">
      {
    
    {
    
     index+1 }}. {
    
    {
    
     item.content }} 
      <span v-if="item.status">(完成)</span>
      <span class="create-time">{
    
    {
    
     item.createTime}}</span>
    </li>
  </ul>
</div>
  • v-for: 循环指令, 遍历todoList对象
  • @click: v-on:click的缩写,绑定点击事件
  • :class: v-bind:class的缩写,表示item.status为true时,添加success到li的class
  • { {}}: 大括号赋值语句, 可以接收表达式
  • v-if: 条件判断,当值为true时,该DOM才显示
b)react JSX语法
<div className="todo-list">
  <h3>待办列表</h3>
  <ul class="todo-ul">
    {
    
    Object.keys(todoList).forEach((k, i) => (
      <li key={
    
    i} id={
    
    k} onClick={
    
    () => {
    
    this.clickTask(k)}}
        className={
    
    todoList[k].status?'success':''}>
        {
    
    i}. {
    
    todoList[k].content}
        {
    
    todoList[k].status && <span>(完成)</span>}
        <span class="create-time">{
    
    {
    
     todoList[k].createTime}}</span>
      </li>
    ))}
  </ul>
</div>

jsx语法将JS逻辑与DOM标签混在一起,学习成本会比较高,对比模板语法来说编写也复杂一些.

三、数据绑定

这是个人认为react与Vue最大的区别,这一点的不同直接导致了编程风格和思想的不同。

a) vue的双向绑定

Vue.js 最核心的功能有两个,一是响应式的数据绑定系统,二是组件系统。所谓双向绑定,指的是vue实例中的data与其渲染的DOM元素的内容保持一致,无论谁被改变,另一方会相应的更新为相同的数据。这是通过设置属性访问器实现的。你不需要去关注视图层怎么变化的,而只需要关注数据。

<template>
  <div>
    <i-input style="width:200px" v-model="value"></i-input>
    <span>{
    
    {
    
    value}}</span>
  </div>
</template>
<script>
export default {
    
    
  data: function() {
    
    
    return {
    
    
      value: "test"
    };
  },
  name: "home",
  components: {
    
    },
  mounted() {
    
    }
};
</script>

上例中,我在任一函数中操作this.data.value值,会使所有引用这个value值的元素自动同步视图,反之,input改变,会同步修改所有与之绑定的数据。

b) react的单向数据流

react中通过将state(Model层)与View层数据进行双向绑定达数据的实时更新变化,具体来说就是在View层直接写JS代码Model层中的数据拿过来渲染,一旦像表单操作、触发事件、ajax请求等触发数据变化,则进行双同步。就是说,数据影响视图,但是视图对数据的影响需要开发者手动控制。一个简单的例子:

class DataBind extends React.Component {
    
    
    constructor(props) {
    
    
        super(props);
        this.handleChange = this.handleChange.bind(this);
        this.state = {
    
    
            value: 123,
        };
    }

    handleChange(e) {
    
    
        this.setState({
    
    
            value: e.target.value,
        });
    }

    render() {
    
    
        return (
            <div>
                <input value={
    
    this.state.value} onChange={
    
    this.handleChange} />
                <div>{
    
    this.state.value}</div>
            </div>
        );
    }
}

如果不使用onChange手动setState,则不会更新状态。

补充:

  • 那如果我想要在vue里监听数据变化怎么处理?

使用watcher,可以监听任何一种数据变化,从而在处理函数中做一些其他数据操作。当然,所有的数据操作都会直接影响视图。

四、组件的数据交互

i)父子组件通信
a) vue

在vue中,父组件传值通过为子组件添加属性实现。这个跟react基本保持一致,不同的是,在vue中,子组件需要在子组件的props属性中预先设置接受的属性。对于子传父,则通过事件进行。

:name 中的:是v-bind的简写。 如果不使用:,则后面的字符串中的内容会被当做字符串解析。
@是v-on的缩写 vue中定义事件的方式。提供了很多默认事件,也可以定义自定义事件。

//--父组件
<template>
  <div>
    <h1>这是父组件</h1>
    <template v-for="(child_data,index) in child_datas">
      <Child @my-callback="getValFromChild" :name="child_data.name" :key="index"></Child>
    </template>
  </div>
</template>
<script>
import Child from "./Child";
export default {
    
    
  data: function() {
    
    
    return {
    
    
      child_datas: [
        {
    
    
          name: "子组件1"
        },
        {
    
    
          name: "子组件2"
        }
      ]
    };
  },
  name: "Parent",
  methods: {
    
    
    getValFromChild(msg) {
    
    
      alert("收到子组件消息:" + msg);
    }
  },
  components: {
    
    
    Child
  }
};
</script>


//--子组件
<template>
  <div>
    <button @click="sendToParent">发送给父消息</button>
    {
    
    {
    
    this.name}}
  </div>
</template>

<script>
export default {
    
    
  props: ["name"],
  data: function() {
    
    
    return {
    
    };
  },
  name: "child",
  components: {
    
    },
  methods: {
    
    
    sendToParent() {
    
    
      this.$emit("my-callback", `我是你儿子(${
      
      this.name})`);
    }
  },
  mounted() {
    
    }
};
</script>


b) react

react中数据传递是一般是通过将回调函数作为props传递到子组件。子组件在适当的时候进行调用

//--父组件
class Parent extends React.Component {
    
    
    constructor(props) {
    
    
        super(props);
        this.state = {
    
    
            child_datas: [
                {
    
    
                    name: '子组件1',
                },
                {
    
    
                    name: '子组件2',
                },
            ],
        };
    }
    onReceiveMeg = (msg) => {
    
    
        alert('收到子组件消息:' + msg);
    }
    render() {
    
    
        return (
            <div>
                <h1>这是父组件</h1>
                {
    
    
                    this.state.child_datas.map((child_data, i) => (
                        <Child name={
    
    child_data.name} key={
    
    i} sendmsg_fn={
    
    this.onReceiveMeg}></Child>
                    ))
                }
                
            </div>
        );
    }
}

//--子组件
class Child extends React.Component {
    
    
    constructor(props) {
    
    
        super(props);
        this.state = {
    
    
            
        };
    }
    sendToParent=() => {
    
    
        this.props.sendmsg_fn(this.props.name);
    }
    render() {
    
    
        return (
            <div>
                <button type="button" onClick={
    
    this.sendToParent}>发送给父消息</button>
                {
    
    this.props.name}
            </div>
        );
    }
}
ii) 兄弟组件通信

兄弟组件间通信基本依赖第三方转发实现。二者原理基本相同,这里不再赘述。

五、 组件的渲染方式

a) vue 自动渲染

Vue宣称可以更快地计算出Virtual DOM的差异,这是由于它在渲染过程中,会跟踪每一个组件的依赖关系,不需要重新渲染整个组件树。

1 在 Vue 应用中,组件的依赖是在渲染过程中自动追踪的,所以系统能精确知晓哪个组件确实需要被重渲染。

2 你可以理解为每一个组件都已经自动获得了 shouldComponentUpdate,并且没有上述的子树问题限制。

3 Vue 的这个特点使得开发者不再需要考虑此类优化,从而能够更好地专注于应用本身。

详解:

  1. Vue的编译器在编译模板之后,会把这些模板编译成一个渲染函数。而函数被调用的时候就会渲染并且返回一个虚拟DOM的树。这个树非常轻量,它的职责就是描述当前界面所应处的状态。

  2. 当我们有了这个虚拟的树之后,再交给一个patch函数,负责把这些虚拟DOM真正施加到真实的DOM上。在这个过程中,Vue有自身的响应式系统来侦测在渲染过程中所依赖到的数据来源。

  3. 在渲染过程中,侦测到的数据来源之后,之后就可以精确感知数据源的变动。到时候就可以根据需要重新进行渲染。

  4. 当重新进行渲染之后,会生成一个新的树,将新树与旧树进行对比,就可以最终得出应施加到真实DOM上的改动。最后再通过patch函数施加改动

概况为:

  • 当某个数据属性被用到时,触发 getter,这个属性就会被作为依赖被 watcher 记录下来。

  • 整个函数被渲染完的时候,每一个被用到的数据属性都会被记录。

  • 相应的数据变动时,例如给它一个新的值,就会触发 setter,通知数据对象对应数据有变化。

  • 此时会通知对应的组件,其数据依赖有所改动,需要重新渲染。

  • 对应的组件再次调动渲染函数,生成 Virtual DOM,实现 DOM 更新。

b) react的根组件渲染
  • 在 React 应用中,当某个组件的状态发生变化时,它会以该组件为根,重新渲染整个组件子树。

  • 如要避免不必要的子组件的重渲染,你需要在所有可能的地方使用 PureComponent,

  • 或是手动实现 shouldComponentUpdate 方法。

换句话说,在Vue中,我修改数据的时候,不用去关心怎样修改数据能够造成尽可能小的渲染代价,或者可以说不用去管React的render函数被调用了几次,什么时候调用,该不该使用shouldComponentUpdate生命周期钩子函数判断是否再调用render.

六、组件生命周期

a) vue 的生命周期钩子

在这里插入图片描述

b) react 的生命周期钩子

在这里插入图片描述

小结

篇幅原因。今天先写到这里,下一篇博文React 对比 VUE 断舍离分(二)

おすすめ

転載: blog.csdn.net/qq_29722281/article/details/106249445