React 对比 VUE 断舍离分(二)

8 篇文章 1 订阅

前言

上一期讲述了React和Vue 在文件结构、模板语法、数据绑定、组件数据交互、组件渲染方式、组件生命周期六大方面的对比。这一期将继续上一期的话题。
在这里插入图片描述

七、状态管理

在状态管理方面,虽然vue跟react采用的不同的框架,但是本质原理上是相同的。vue采用的是自研的,专门为 Vue.js 设计的状态管理库:vuex,随官方版本发布,稳定性能佳。而React则将这部分中间件交给了社区,集思广益。尤属Redux较为突出。

a) vue中的vuex

不采用action方式,最简单的全局状态管理:

  1. store中声明状态
import Vue from 'vue'
import Vuex from 'vuex'
import mutations from './mutations'

Vue.use(Vuex);
export default new Vuex.Store({
  state: {
  //--声明一个状态
    current_level:1
  },
  mutations
})

  1. 声明修改状态的mutation
//--mutation.js
export default {
	changeLevel(state,new_lv){
        state.current_level = new_lv;
    }
}
  1. 使用状态

对于全局状态,一般用computed计算出一个属性进行使用。可以像普通属性一样进行使用。

<template>
  <div>
    <h1>这是全局状态current_level的值:{{current_level}}</h1>
    <button @click="incr()">让current_level+1</button>
  </div>
</template>
<script>
import Child from "./Child";
export default {
  data: function() {
    return {
    };
  },
  name: "State",
  methods: {
    incr(){
      this.$store.commit('changeLevel',this.current_level+1);
    }
  },
  watch:{
    current_level(){
      if(this.current_level == 10)
      {
        alert('状态为10')
      }
    }
  },
  computed:{
    current_level(){
      return this.$store.state.current_level
    }
  }
};
</script>

这样会导致一个问题。所有的状态修改都是同步的。我没法在mutation中处理异步事件。这时候我们可以采用action。关于异步状态维护action的展开,网上有很多实例。可以参阅这里。且接下来react redux的思想,其实就是action的实现。

b) react 中的 redux

就redux而言,我觉得最大的优点就是将状态机分开。每个reducer迭代某一类特定的状态。

1 .声明一个或多个reducer(状态机),可以将一个模块的状态统一写成一个reducer

//--login_reducer.js 这个reducer专门管理登录用户的相关状态
import { STORE_USER_NICNAME, STORE_USER_NAME } from './actions/login_action';
const initialState = {
    userName: '',
    userNikNmae: '',
};
export default function(state = initialState, action) {
    switch (action.type) {
    case STORE_USER_NAME: {
        return {
            ...state,
            userName: action.value,
        };
    }

    case STORE_USER_NICNAME: {
        return {
            ...state,
            userNikNmae: action.value,
        };
    }
    default:
        return state;
    }
} 


//--some_other_reducer.js
import { SET_STATE_1, SET_STATE_2 } from './actions/some_other_action';
const initialState = {
    other_state_1: 1,
    other_state_2: 2,
};
export default function(state = initialState, action) {
    switch (action.type) {
    case SET_STATE_1: {
        return {
            ...state,
            other_state_1: action.value,
        };
    }

    case SET_STATE_2: {
        return {
            ...state,
            other_state_2: action.value,
        };
    }
    default:
        return state;
    }
} 



上述reducer分别导出,再使用combineReducers函数,组合成一个状态机,赋值给store的create函数,完成store的初始化

import { combineReducers } from 'redux';
import LoginReducer from './login_reducer';
import OtherReducer from './other-reducer';

const allReducers = {
   Login:LoginReducer,
   Other:OtherReducer 
};

const rootReducer = combineReducers(allReducers);

let store = createStore(rootReducer);

export default store; 

2 .定义改变状态的action

这个函数表示一个动作,我需要去改变other_state_1值的一个动作

export const SET_STATE_1 = 'set_state_1';
export const SET_STATE_2 = 'set_state_2';

export const state1Change = (value) => ({
    type: SET_STATE_1,
    value,
});
export const state2Change = (value) => ({
    type: SET_STATE_2,
    value,
});

3 .在组件中使用

import React from 'react';
import store from '../store/store';
import { state1Change } from '../store/actions/some_other_action';
class StoreTest extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
        };
        store.subscribe((state) => {
           //--注意这里。不写这个,无法更新视图。
            this.setState({});
        });
    }
    setGlobalState=() => {
        const cur_st1 = store.getState().Other.other_state_1;
        store.dispatch(state1Change(cur_st1 + 1));
    }

    render() {
        const st1 = store.getState().Other.other_state_1;
        return (
            <div>
                <h1>这是直接使用全局状态other_state_1的值:{st1}</h1>
                <button type="button" onClick={this.setGlobalState}>other_state_1的值+1</button>
            </div>
        );
    }
}
export default StoreTest;

react 中直接使用redux,一般情况是各个业务模块相互独立,互不影响。很少涉及到兄弟模块交互等情况。由示例可以看出,直接使用store中的值时,在store变化时,需要手动监听其变化,再判断自身state状态,更新视图,很麻烦。推荐使用react-redux,我也有一篇博客详细介绍了这两者的区别。

八 使用场景
a)vue
i 期待模板搭建应用

Vue应用的默认选项是把markup放在HTML文件中。数据绑定表达式采用的是和Angular相似的mustache语法,而指令(特殊的HTML属性)用来向模板添加功能。
相比之下,React应用不使用模板,它要求开发者借助JSX在JavaScript中创建DOM。

ii 期待简单和“上手就能会”的东西
  • 一个简单的Vue项目可以不需要转译直接运行在浏览器中,所以使用Vue可以像使用jQuery一样简单。当然这对于React来说在技术上也是可行的,但是典型的React代码是重度依赖于JSX和诸如class之类的ES6特性的。
    Vue的简单在程序设计的时候体现更深,让我们来比较一下两个框架是怎样处理应用数据的(也就是state)。
  • React中是通过比较当前state和前一个state来决定何时在DOM中进行重渲染以及渲染的内容,因此需要不可变(immutable)的state。
    Vue中的数据是可变(mutated)的,所以同样的操作看起来更加简洁。
    让我们来看看Vue中是如何进行状态管理的。当向state添加一个新对象的时候,Vue将遍历其中的所有属性并且转换为getter,setter方法,现在Vue的响应系统开始保持对state的跟踪了,当state中的内容发生变化的时候就会自动重新渲染DOM。令人称道的是,Vue中改变state的状态的操作不仅更加简洁,而且它的重新渲染系统也比React 的更快更有效率。
iii 期待应用尽可能的小和快
  • 当应用程序的状态改变时,React和Vue都将构建一个虚拟DOM并同步到真实DOM中。 两者都有各自的方法优化这个过程。
  • Vue核心开发者提供了一个benchmark测试,可以看出Vue的渲染系统比React的更快。测试方法是10000个项目的列表渲染100次。从实用的观点来看,这种benchmark只和边缘情况有关,大部分应用程序中不会经常进行这种操作,所以这不应该被视为一个重要的比较点。
  • 但是,页面大小是与所有项目有关的,这方面Vue再次领先,它目前的版本压缩后只有25.6KB。
    React要实现同样的功能,你需要React DOM(37.4KB)和React with Addon库(11.4KB),共计44.8KB,几乎是Vue的两倍大。

双倍的体积并不能带来双倍的功能。

b)react
i 期待构建一个大型应用程序

同时用Vue和React实现的简单应用程序,可能会让一个开发者潜意识中更加倾向于Vue。这是因为基于模板的应用程序第一眼看上去更加好理解,而且能很快跑起来。但是这些好处引入的技术债会阻碍应用扩展到更大的规模。模板容易出现很难注意到的运行时错误,同时也很难去测试,重构和分解。
相比之下,Javascript模板可以组织成具有很好的分解性和干(DRY)代码的组件,干代码的可重用性和可测试性更好。Vue也有组件系统和渲染函数,但是React的渲染系统可配置性更强,还有诸如浅(shallow)渲染的特性,和React的测试工具结合起来使用,使代码的可测试性和可维护性更好。
与此同时,React的immutable应用状态可能写起来不够简洁,但它在大型应用中意义非凡,因为透明度和可测试性在大型项目中变得至关重要。

i 期待同时适用于Web端和原生APP的框架

React Native是一个使用Javascript构建移动端原生应用程序(iOS,Android)的库。 它与React.js相同,只是不使用Web组件,而是使用原生组件。 如果你学过React.js,很快就能上手React Native,反之亦然。
它的意义在于,开发者只需要一套知识和工具就能开发Web应用和移动端原生应用。如果你想同时做Web端开发和移动端开发,React为你准备了一份大礼。
阿里的Weex也是一个跨平台UI项目,目前它以Vue为灵感,使用了许多相同的语法,同时计划在未来完全集成Vue,然而集成的时间和细节还不清楚。因为Vue将HTML模板作为它设计的核心部分,并且现有特性不支持自定义渲染,因此很难看出目前的Vue.js的跨平台能力能像React和React Native一样强大。

iii 期待最大的生态系统

毫无疑问,React是目前最受欢迎的前端框架。它在NPM上每个月的下载量超过了250万次,相比之下,Vue是65万次。人气不仅仅是一个肤浅的数字,这意味着更多的文章,教程和更多Stack Overflow的解答,还意味有着更多的工具和插件可以在项目中使用,让开发者不再孤立无援。
这两个框架都是开源的,但是React诞生于Facebook,有Facebook背书,它的开发者和Facebook都承诺会持续维护React。相比之下,Vue是独立开发者尤雨溪的作品。尤雨溪目前在全职维护Vue,也有一些公司资助Vue,但是规模和Facebook和Google没得比。不过请对Vue的团队放心,它的小规模和独立性并没有成为劣势,Vue有着固定的发布周期,甚至更令人称道的是,Github上Vue只有54个open issue,3456个closed issue,作为对比,React有多达530个open issue,3447个closed issue。

九、其他细节
1、 this指向问题
a) vue this指向唯一

不论在哪个生命周期钩子函数或者是自定义事件处理函数,this皆指向组件实例对象。不会造成this指向混乱的问题。

b) react 将this的指向交给了开发者维护

官档描述是为了开发者能跟定制事件处理函数中this的指向,但是大部分情况下,我们不得不采用一些奇怪的方式解决this指向的问题。
例如

this.handleClick = this.handleClick.bind(this)

或者

 handleClick() {
    
 }
 render() {
   return (
     <div>
       <input type="text" ref={this.myTextInput} />
       <input type="button" value="Focus the text input" onClick={this.handleClick.bind(this)} />
     </div>
   );
 }

或者

 handleClick= ()=> {
    
 }
 render() {
   return (
     <div>
       <input type="text" ref={this.myTextInput} />
       <input type="button" value="Focus the text input" onClick={this.handleClick} />
     </div>
   );
 }

或者可能造成内存泄漏的

 handleClick() {
    
 }
 render() {
   return (
     <div>
       <input type="text" ref={this.myTextInput} />
       <input type="button" value="Focus the text input" onClick={()=>{
       	this.handleClick()
       } />
     </div>
   );
 }
2、 判断组件是否渲染的方式
a) vue 提供了v-if操作符 配合计算属性
<template>
  <div>
    <span v-if = "islogin">用户已登录</span>
    <span v-if = "islogin_and_validate">用户已登录并且密码正确</span>
  </div>
</template>

<script>
export default {
  data: function() {
    return {
      islogin:true,
      password_validate:false
    };
  },
  computed:{
    islogin_and_validate(){
      return this.islogin && this.password_validate;
    }
  },
  name: "home",
  components: {},

  mounted() {}
};
</script>

b)react 大量的三元表达式
import React from 'react';
class IfOrNot extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            islogin: true,
            password_validate: false,
        };
    }

    render() {
        return (
            <div>
                {
                    !this.state.islogin ? <span>用户还未登录</span> : this.state.password_validate ? <span>用户登录并且密码正确</span> : <span>用户登录但密码不对</span> 
                }
            </div>
        );
    }
}
export default IfOrNot;

3、计算属性的使用
a) vue 提供了computed关键字

在Vue中使用计算属性非常方便。计算属性也是通过依赖收集实现的。当你的计算属性中,使用了其他的属性或者计算属性,其他的依赖属性变化的时候,计算属性本身也会进行通知。

 computed: {
    boys() {
      return this.org_data.filter(m => {
        return m.agient === "boy";
      });
    },
    boys_smoke() {
      return this.boys.filter(m => {
        return m.smoke;
      });
    },
    boys_smoke_and_sao() {
      return this.boys_smoke.filter(m => {
        return m.sao;
      });
    }
  },
b) react 暂时没有相关机制

不过可以通过如下实现简单的computed

get boys() {
        const { org_data } = this.state;
        return (
            org_data.filter(m => m.agient === 'boy').map((m, index) => <h3 key={index}>{m.name}</h3>)
        );
}
render() {
        return (
            <div>
                <h1>男孩们</h1>
                {this.boys}
                <h1>抽烟的男孩们</h1>
                {this.boys_smoke}
            </div>
        );
    }

写在最后

实际上,React和Vue都是非常优秀的框架,它们之间的相似之处多过不同之处,并且它们大部分最棒的功能都是相通的。个人是Vue爱好者,本篇文章若涉及到一些问题还请各位博友留言指正。

2022.6.3日(长期有效):打个广告,苏州华为终端BG面向社会招聘人才,Java /C C++ / Python / Javascript 。有兴趣来苏州的同学们 可以加我V 15850277051 ,走内推流程,有问必答!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值