组件开发方式:
Vue 使用单文件组件(SFC), HTML, JS 和 CSS 在一个文件内实现
<template> <div class="my-component"> <!-- HTML模板 --> </div> </template> <script> export default { // JavaScript代码 } </script> <style> .my-component { /* CSS样式 */ } </style>
React使用 JSX 和 JavaScript
import React from 'react'; import './MyComponent.css'; function MyComponent() { return ( <div className="my-component"> {/* JSX 模板 */} </div> ); } export default MyComponent;
数据响应:
- Vue3 基于响应式数据, 底层通过 new Proxy() 实现对数据变更的监控,相比于 React 更加的简单
- React 采用 setState or useState,手动的方式进行变更。
生命周期
Vue3 生命周期更加灵活,8 个生命周期能够对组件各个阶段做到精确的控制
beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeUnmount、unmounted
React 生命周期更加精简
constructor、componentDidMount、componentDidUpdate、componentWillUnmount
路由&状态管理
- Vue3 使用 Pinia/Vuex,router 使用 Vue-Router, 提供了一种简单和直接的状态管理方式
import { defineStore, acceptHMRUpdate } from 'pinia'
import { useUserStore } from './user'
export const useCartStore = defineStore({
id: 'cart',
state: () => ({
rawItems: [] as string[],
}),
getters: {
items: (state): Array<{ name: string; amount: number }> =>
state.rawItems.reduce((items, item) => {
const existingItem = items.find((it) => it.name === item)
if (!existingItem) {
items.push({ name: item, amount: 1 })
} else {
existingItem.amount++
}
return items
}, [] as Array<{ name: string; amount: number }>),
},
actions: {
addItem(name: string) {
this.rawItems.push(name)
},
removeItem(name: string) {
const i = this.rawItems.lastIndexOf(name)
if (i > -1) this.rawItems.splice(i, 1)
},
async purchaseItems() {
const user = useUserStore()
if (!user.name) return
console.log('Purchasing', this.items)
const n = this.items.length
this.rawItems = []
return n
},
},
})
if (import.meta.hot) {
import.meta.hot.accept(acceptHMRUpdate(useCartStore, import.meta.hot))
}
React 使用 Redux/Mobx, router 使用 React-Router, 提供了更灵活的状态管理方案
// actions export const Add = { type:'add' } export const Sub = { type:'sub' } // reducer export default function counterReducer(state = initialState, action) { switch (action.type) { case 'add': return Object.assign({}, state, { count: state.count + 1 }); case 'sub': return Object.assign({}, state, { count: state.count - 1 }); default: return state; } } //设置一个初始值 const initialState = { count: 0, }
视图功能
Vue3 的视图通过 Vue3 定义的指令 + 模板的方式,包含样式,事件,表单,lot,DOM 节点操作, Provide/inject
<template> <div> <ul> <li v-for="item,index in list" @click="handleClick(index)" :style="{color: 'red'}" ></li> </ul> <div class="container"> <header> <slot name="header"></slot> </header> <main> <slot></slot> </main> <footer> <slot name="footer"></slot> </footer> </div> <div> <input name="username" :v-model="user.name" /> </div> </form> </div> </template> <script> methods: { handleClick(index){ } } </script>
React 视图使用原生 JS + 模板的方式,包含样式,时间,表单,Children, DOM 节点操作, Context
function MyComp() {
return (
<>
<ul ref="List">t
{
list.map((v, i)=> <li onClick={handleClick(i)} style={{color: 'red'}}></li>)
}
</ul>
<form>
<div>
<input name="username" onChange="(e) => handleInputChange(e)" value={user.name} />
</div>
</form>
</>
)
}
const handleClick = (index) => {
return () => {
console.log(index)
}
}