2023 vue 转 react 开发指南

前言

本文所有vue示例基于vue2.0react示例基于16.8+ Hook模式

指令

v-bind

<input v-bind:value="value" />  // vue
<input value={value} /> // react

v-model

<input v-model="value" />  // vue
<input v-bind:value="value" @change="(e) => emit('input', e.target.value)" />  // vue
<input value={value} onChange={(e)=>{setValue(e.target.value)}} /> // react

v-if

可以简单理解为 jsx 直接将 if 搬到html中

<div v-if="isShow"> ... </div> // vue
{isShow && <div> ... </div>} // react

v-html

可以简单理解为 jsx 直接将 if 搬到html中

<div v-html="content"></div> // vue
<div dangerouslySetInnerHTML={{__html: content}}></div> // react

v-for

可以简单理解为 jsx 直接将 if 搬到html中

// vue
<ul id="example-1">
  <li v-for="item in items" :key="item.message">
    {{ item.message }}
  </li>
</ul>
<scritp>
export default {
  data: {
    items: [{ message: 'Foo' },{ message: 'Bar' }]
  }
}
</script>

// react
function renderItems() {
  const [items, setItems] = useState([{ message: 'Foo' },{ message: 'Bar' }])
  return (
	<ul id="example-1">
	  {items.map(item => {
	    return <li key={item.message}>{item.message}</li>
	  })}
	</ul>	
  )
}

数据

data / watch

// vue
data() {
  return {
    visible: false,
  }
},
watch: {
  visible(val) {
    // do something ...
  }
},

// react
const [visible, setVisible] = useState(false)

useEffect(() => {
  // do something ...
}, [visible])

ref

// vue
<template>
  <input ref="inputEl" type="text" />
  <button onClick={onButtonClick}>Focus the input</button>
</template>
<scritp>
export default {
  methods: {
    onButtonClick: function () {
      this.$refs.inputEl.focus()
    }
  }
}
</script>

// react
function TextInputWithFocusButton() {
  const inputEl = useRef(null);
  const onButtonClick = () => inputEl.current.focus();
  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </>
  );
}

事件

事件语法

jsx 中,所有事件有on开头,所有事件名称首字母大写

<input @change="(e) => this.value = e.target.value" />  // vue
<input onChange={(e)=> setValue(e.target.value)} /> // react

事件修饰符

vue事件修饰符的效果
.stop : 阻止事件冒泡,在JSX中使用 event.stopPropagation()
.prevent:阻止默认行为,在JSX中使用 event.preventDefault()

数据通信

父子通信

  1. 父组件传值到子组件
  2. 父组件调用子组件方法
  3. 子组件调用父组件方法

vue

// Father.vue
<template>
  <div>
    <Child ref="child" :fatherMsg="data" @fatherMethod="fatherMethod"></Child>
    <Button @click="fatherFun">点击调用子组件方法</Button>
  </div>
</template>
<script>
  import Child from './Child';
  export default {
      data() {
        return {
           msg: 'father'
        }
      },
    components: {
      Child
    },
    methods: {
      fatherMethod() {
        // do something...
      },
      fatherFun() {
        this.$refs.child.childFun(); // or $on、$refs.child.$emit("childFun")    
      },
    }
  };
</script>

// Child.vue
<template>
  <div>
  	<div>{{FatherMsg}}</div>
    <button @click="childMethod">点击调用父组件方法</button>
  </div>
</template>
<script>
  export default {
  	props: ['fatherMsg']
    methods: {
      childMethod() {
        this.$emit('fatherMethod'); // or this.$parent.fatherMethod();
      },
      childFun() {
        // do something...
      },
    }
  };
</script>

react

// Father.jsx
import {useState,useRef } form React
import Child from './Child';

const Father = () => {
  const child = useRef(null)
  const [fatherMsg, setFatherMsg] = useState('father')
  const fatherMethod = () => {
    // do something
  }
  const fatherFun = () => {
    child.current.childFun()
  }
  return (
    <div>
      <Child ref={child} fatherMsg={fatherMsg} fatherMethod={fatherMethod} />
      <Button onClick={fatherFun}>点击调用子组件方法</Button>
    </div>
  )
}

// Child.jsx
import {forwardRef,useImperativeHandle } form React

const Child = forwardRef((props, ref) => {
  const { fatherMsg, fatherMethod } = props
  const childFun = () => {
    // do something
  }
  useImperativeHandle(ref, () => ({
    childFun,
  }))

  return (
    <div>
      <div>{fatherMsg}</div>
      <button onClick={fatherMethod}>点击调用父组件方法</button>
    </div>
  )
})

多层级数据通信

vue

// 1. 通过 Vue.prototype
Vue.prototype.DEV_MODE = true
Vue.prototype.$_ = _

// 2. 通过vuex
Vue.use(Vuex);
const store = new Vuex.Store({
  modules: {
    history: {
      state: {
        allow: true,
      },
      mutations: {
        NotAllowToPushStack: (state, allow) => {
          state.allow = allow;
        },
      },
      actions: {},
    },
  },
  getters: {
    allow: state => state.history.allow,
  },
});
export default store;

react

// 1. 通过 Context 向组件树深层传递数据 
const defaultHistoryContext = { allow: true}
const HistoryContext = createContext(defaultHistoryContext)

const Other = () => {
  // 调用 useContext 来读取和订阅 context
  const { allow } = useContext(HistoryContext)
  return <div>{allow ? <div>允许</div> : <div>禁止</div>}</div>
}

const App = () => {
  const [value, setValue] = useState(defaultHistoryContext)
  return (
    <HistoryContext.Provider value={value}>
      <Other />
    </HistoryContext.Provider>
  )
}

// 2. 通过 recoil 实现 Context 相似功能
// 2.1 store 文件
import { atom } from 'recoil'

const historyState = atom({
  key: 'history',
  default: {
    allow: true,
  },
})

export default historyState

// 2.2 Other.jsx
import { useRecoilState } from 'recoil'

const Other = () => {
  const [allow, setAllow] = useRecoilState(historyState)
  return <div>{allow ? <div>允许</div> : <div>禁止</div>}</div>
}

export default Other

生命周期

vue

new Vue({
  beforeCreate() {
    console.log('beforeCreate');
  },
  created() {
    console.log('created');
  },
  beforeMount() {
    console.log('beforeMount');
  },
  mounted() {
    console.log('mounted');
  },
  beforeUpdate() {
    console.log('beforeUpdate');
  },
  updated() {
    console.log('updated');
  },
  beforeDestroy() {
    console.log('beforeDestroy');
  },
  destroyed() {
    console.log('destroyed');
  },
})

react

通过 Hook 模拟生命周期

const LifeInner = () => {
  const mounted = useRef()
  useEffect(() => {
    if (!mounted.current) {
      mounted.current = true
    } else {
      console.log('updated')
    }
  })

  useEffect(() => {
    console.log('mounted')

    return () => {
      console.log('destroyed')
    }
  }, [])
}

const Life = memo(LifeInner, (prevProps, nextProps) => {
  console.log('shouldComponentUpdate')
  // return true 更新组件 false 则不更新组件
})

参考资料

React 官方文档
Vue 官方文档
Recoil 中文文档

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值