我已经使用React很长时间了,所以当有人说“嘿,你应该尝试一种不同的前端框架”时,我的回答总是“哼,但我已经如此高效了=P”。然而,Vue已经有了足够多的酷炫发展,让我想要尝试一下。结果我愉快地惊讶了!Vue有一堆很棒的功能,让我作为React开发者感到羡慕。让我们深入探讨一些Vue的模式,以及它们与React方法的对比!
1. 安装过程愉快
Vue的开箱即用体验远远领先——npm create vue@latest
感觉像是一个“设计好的体验”,而npm create-react-app
只是一个普通的NPM命令。我更喜欢像在Vue中一样交互地选择要安装的包,而不是CRA的流程。
此外,Vue安装的包提供了比CRA更完整的开发体验,涵盖了诸如路由、状态管理和代码格式化等领域。
Vue的安装过程令人愉快地互动。
另外,我们能不能谈谈当你为新项目打开localhost
时,起始页面有多么有帮助?
接下来的所有Vue示例都使用Vue 3的Composition API,它与函数式React最相似。
2. 直观的响应式系统
与React的状态管理相比,Vue的响应式系统感觉更直观,而且没有那么多样板代码。Vue会自动处理依赖跟踪和更新,使状态管理变得简单。
Vue示例
<template>
<p>{{ count }}</p>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
const count = ref(0);
onMounted(() => {
setInterval(() => {
count.value++;
}, 1000);
});
</script>
React等效
为了实现类似的响应式效果,React需要更多的样板代码,特别是对于依赖于先前状态值的效果和状态更新。还有谁每次想使用它们时都不得不查阅useEffect
、useMemo
和useCallback
之间微妙的区别呢?🙋🏾♂️
function Counter() {
const [count, setCount] = React.useState(0);
React.useEffect(() => {
const interval = setInterval(() => {
setCount(currentCount => currentCount + 1);
}, 1000);
return () => clearInterval(interval);
}, []);
return <p>{count}</p>;
}
3. 单文件组件
单文件组件(SFCs)肯定是一种爱恨交加的东西,但我认为它们很棒,尤其是对于小型组件。在我看来,将HTML、JavaScript和CSS封装在一个文件中有助于更好地组织和阅读代码。
Vue单文件组件
<script setup lang="ts">
import { defineProps } from 'vue'
defineProps({
message: String
})
</script>
<template>
<div class="message-box">
<p>{{ message }}</p>
</div>
</template>
<style scoped>
.message-box {
padding: 20px;
border: 1px solid #eee;
}
</style>
React等效
在React中,实现相同的封装通常涉及将不同的关注点分开到不同的文件中,或者采用CSS-in-JS库,这可能会增加复杂性。
function MessageBox({ message }) {
return (
<div className="message-box">
<p>{message}</p>
</div>
);
}
// CSS通常单独管理,或通过CSS-in-JS解决方案管理
4. 条件渲染
Vue的指令系统(v-if
、v-for
等)提供了比React更可读的条件渲染方法。随着您的if/else语句变得更加复杂,这种优势会变得更加明显。
带有指令的Vue示例
<script setup lang="ts">
import { ref } from 'vue';
const isSubscribed = ref(false);
const isSubscriptionExpiring = ref(true);
// 上面的属性会动态更新...
</script>
<template>
<div>
<p v-if="!isSubscribed">请订阅以访问高级功能。</p>
<p v-else-if="isSubscriptionExpiring">您的订阅即将到期。请续订以继续享受高级功能。</p>
<p v-else>欢迎回来,尊贵的高级用户!</p>
</div>
</template>
React等效
function SubscriptionStatus() {
const isSubscribed = false;
const isSubscriptionExpiring = true;
// 上面的属性会动态更新...
return (
<div>
{isSubscribed ? (
isSubscriptionExpiring ? (
<p>您的订阅即将到期。请续订以继续享受高级功能。</p>
) : (
<p
>欢迎回来,尊贵的高级用户!</p>
)
) : (
<p>请订阅以访问高级功能。</p>
)}
</div>
);
}
当然,您可以将基于JSX的逻辑移动到一个JS函数中,但在Vue中,初始过程更容易理解。
5. 计算属性
Vue的计算属性简化了依赖于响应式数据的复杂逻辑处理。它们会自动缓存,并且仅在其依赖项更改时重新计算,从而优化性能。
Vue示例
<script setup lang="ts">
import { computed, ref } from 'vue'
const price = ref(10)
const quantity = ref(3)
const totalPrice = computed(() => price.value * quantity.value)
</script>
<template>
<p>总价:{{ totalPrice }}</p>
</template>
React等效
在React中,类似的功能需要使用useMemo hook,这会给组件逻辑增加复杂性和冗余性。
function TotalPrice() {
const [price, setPrice] = React.useState(10);
const [quantity, setQuantity] = React.useState(3);
const totalPrice = React.useMemo(() => {
return price * quantity;
}, [price, quantity]);
return <p>总价:{totalPrice}</p>;
}
6. 流畅的状态管理
Pinia是Vue推荐的状态管理解决方案之一。由于与Vue的紧密集成和周到的API,Pinia感觉比React + Redux中的等效代码更流畅。
使用Pinia的Vue
// stores/counter.js
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => {
return { count: 0 }
},
actions: {
increment() {
this.count++
},
},
})
// components/MyCounter.vue
<script setup>
import { useCounterStore } from '@/stores/counter'
const counter = useCounterStore()
</script>
<template>
<button @click="counter.increment">递增</button>
<div>当前计数:{{ counter.count }}</div>
</template>
使用Redux的React
// counterSlice.js
import { createSlice } from '@reduxjs/toolkit'
export const counterSlice = createSlice({
name: 'counter',
initialState: {
value: 0,
},
reducers: {
increment: (state) => {
state.value += 1
}
},
})
export const { increment } = counterSlice.actions
export default counterSlice.reducer
// Counter.js
import React from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { decrement, increment } from './counterSlice'
export function Counter() {
const count = useSelector((state) => state.counter.value)
const dispatch = useDispatch()
return (
<button onClick={() => dispatch(increment())}>
递增
</button>
<span>{count}</span>
)
}
总结
我初次学习Vue的经历拓宽了我对良好设计模式和良好构建API的视野。很明显,Vue从一开始就优先考虑了开发者体验和应用性能。我认为这里最重要的教训是,无论您的技能水平如何,或者您已经掌握了哪些工具,您都可以通过尝试新事物来学习!