[纯原创无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
				})
			}
		}
	})

}
相关推荐
会飞的鱼先生32 分钟前
vue3 内置组件KeepAlive的使用
前端·javascript·vue.js
苹果酱05671 小时前
【Azure Redis 缓存】在Azure Redis中,如何限制只允许Azure App Service访问?
java·vue.js·spring boot·mysql·课程设计
前端付豪2 小时前
🚀 2025 年 React 全攻略:40 个高频问题深度解析与实战指南
前端·react.js
咪库咪库咪3 小时前
vue1
前端·vue.js
李是啥也不会3 小时前
Vue中Axios实战指南:高效网络请求的艺术
前端·javascript·vue.js
JavaDog程序狗4 小时前
【实操】uniapp纯前端搞个识别植物花草小程序
前端·vue.js·uni-app
Aiolimp4 小时前
React JSX 基本用法
前端·react.js
高峰君主4 小时前
跨端时代的全栈新范式:React Server Components深度集成指南
前端·react.js·前端框架
じ☆ve 清风°4 小时前
Vue.js 核心特性解析:响应式原理与组合式API实践
前端·vue.js