[纯原创无Ai] 我把React调教成vue的模样了

为什么我要这么做?

本人一个重度vue患者,最近想学习react,但是总是感觉浑身不舒服,比如不理解为什么管理状态需要调用React.useState,还要解构一个真数据一个设置器函数。比如为什么React没有像Vue那样导出好几个生命周期函数,而是要在React.useEffect里面找到合适的调用时机。React给我的一整个感觉就是:不方便,不顺手,找不到逻辑该写哪,很让初学者挠头。估计是因为我用了好几年的vue,被宠坏了,没办法改过来

于是!

我开始对React大刀阔斧,想办法把它调教成我熟悉的风格,一开始是只有两个生命周期函数,用了两天,感觉对react的其他部分也有点意见,既然函数名都换了,那干脆直接定义一个useVue得了,传入一个类似于vue的配置对象,直接获得媲美于vue的开发习惯

封装的useVue代码

js 复制代码
import React from "react";
import * as immer from 'immer';

function onMounted(cb) {
  React.useEffect(() => {
    cb()
  }, []);
}

function onBeforeUnmount(cb) {
  React.useEffect(() => {
    return cb
  }, []);
}

function useCustomReactive(originalData) {
  let [data, setDataHandler] = React.useState(originalData)
  function setData(draftchange) {
    setDataHandler(immer.produce(data, draftchange))
  }
  return [data, setData]
}


/**
 * 使用 Vue 风格的配置对象
 * @param {Object} vm - vm配置对象,必传
 * @param {返回值是JSX组件的函数} vm.template - 必需的模板函数,用于渲染内容 通过 `<p> {this.$data.xxx} </p>` 访问数据
 * @param {初始化数据对象|返回一个对象的函数} [vm.data] - 数据对象或返回数据对象的函数 通过 `this.$setData(draft=>{ draft.xxx = this.$data.xxx+1 })` 设置数据。
 * @param {对象} [vm.methods] - 方法配置 通过 `this.$methods.func_name()` 调用。
 * @param {对象} [vm.computed] - 计算属性对象 通过 `<p> {this.$computed.xxx} </p>` 访问数据
 * @param {生命周期} [vm.mounted] - 挂载完成时的回调函数
 * @param {生命周期} [vm.beforeUnmount] - 卸载前的回调函数
 * @returns {React组件} 模板函数的返回值
 */
export function useVue(vm) {
  if (vm.data) {
    if (typeof vm.data === 'function') {
      vm.data = vm.data()
    }
    let [$data, $setData] = useCustomReactive(vm.data)
    vm.$data = $data
    vm.$setData = $setData
  }
  if (vm.methods) {
    for (let functionName in vm.methods) {
      vm.methods[functionName] = vm.methods[functionName].bind(vm)
    }
    vm.$methods = vm.methods
  }
  if (vm.computed) {
    for (let propertyName in vm.computed) {
      vm.computed[propertyName] = vm.computed[propertyName].bind(vm)
    }
    vm.$computed = vm.computed
  }

  if (vm.mounted) onMounted(vm.mounted.bind(vm))
  if (vm.beforeUnmount) onBeforeUnmount(vm.beforeUnmount.bind(vm))

  return vm.template()
}

使用示例

jsx"use 复制代码
import React from 'react';
import { Button } from '@douyinfe/semi-ui';
import { useVue } from '@/app/utils.js'


export default function MyComponents() {

	return useVue({

		template() {
			return <>
				<Button onClick={this.$methods.toggle_show_load_button}>显示或隐藏加载按钮</Button>
				<Button onClick={this.$methods.init_list} style={{ 'display': this.$data.show_button ? 'block' : 'none' }}>开始加载</Button>
				<br />
				<ul>
					{this.$data.list.map(item => <li key={item.key}>{item.value}</li>)}
				</ul>
				<br />
				<ol>
					{this.$computed.all_chunk().map(item => <li key={item}>{item}</li>)}
				</ol>
			</>
		},

		data() {
			return {
				show_button: true,
				list: [],
				chunk_1: [1, 2, 3, 4, 5],
				chunk_2: [6, 7, 8],
			}
		},

		computed: {
			all_chunk() {
				return [...this.$data.chunk_1, ...this.$data.chunk_2]
			}
		},

		mounted() {
			this.$methods.toggle_show_load_button()
		},

		methods: {
			init_list() {
				setTimeout(() => {
					this.$setData(draft => {
						draft.list = (new Array(10)).fill(0).map((_, key) => ({ value: Math.random(), key }))
						draft.chunk_1 = this.$data.chunk_1.slice(0,3)
					})
				}, 2000) // 模拟请求,两秒后加载出数据
			},
			toggle_show_load_button() {
				this.$setData(draft => {
					console.log(this.$data.show_button)
					draft.show_button = !this.$data.show_button
				})
			}
		}
	})

}
相关推荐
光影少年6 小时前
react的hooks防抖和节流是怎样做的
前端·javascript·react.js
小毛驴8506 小时前
Vue 路由示例
前端·javascript·vue.js
m0_719084117 小时前
React笔记张天禹
前端·笔记·react.js
Ziky学习记录7 小时前
从零到实战:React Router 学习与总结
前端·学习·react.js
青青家的小灰灰8 小时前
React 19 核心特性与版本优化深度解析
react.js
TT哇8 小时前
【实习 】银行经理端两个核心功能的开发与修复(银行经理绑定逻辑修复和线下领取扫码功能开发)
java·vue.js
却尘9 小时前
Next.js 请求最佳实践 - vercel 2026一月发布指南
前端·react.js·next.js
星光不问赶路人10 小时前
vue3使用jsx语法详解
前端·vue.js
weixin79893765432...10 小时前
Vue 组件的更新过程(编译系统 + 响应式系统 + 虚拟 DOM & Diff)
vue.js
早點睡39011 小时前
高级进阶 React Native 鸿蒙跨平台开发:@react-native-community-slider 滑块组件
react native·react.js·harmonyos