Vue3和React18瞎学之路(暂6)

70 阅读3分钟

1、数据渲染更新

vue

  使用ref, reactive两个api创建的数据,修改后会页面会自动渲染更新。

<template>
    <div> {{count}} </div>
    <div> {{user.name}} 今年 {{user.age}}了</div>
</template>
import { ref, reactive} from 'vue'
const count = ref(1)
const user = reactive({name:'cat', age:3})
setTimeout(function() {
    conut.value ++ //页面自动渲染更新
    user.age = 4 //页面自动渲染更新
}, 1000)

React

  使用useState这个api构建数据,返回一个数组,第一项是初始的数据,第二项是个渲染函数,调用它会触发组件的重新渲染。

const App = () => {
    const [count, setCount] = useState(1)
    const [user, setUser] = useState({name:'cat', age:3})
    const add = () => {
        // setCount(count + 1 )
        setCount((count) => count + 1)
        setUser({...user, {age:user.age + 1}})
    }
    return <div>
        <button onClick={add}>加1</button>
        {count}
        <div> {user.name} 今年 {user.age}了</div>
    </div>
}

  如上述例子,使用setCount钩子用于组件重新渲染(自己命名,一般都是set+变量),两种方式,一种是直接传修改后的值,setCount(count+1); 值得注意的是,setCount是一个异步重新渲染的过程,当add函数里面的代码足够多的时候,会出现这么一种情况:当连续两次快速的点击的时候,此时页面count应该是3,但是显示为2; React针对这种情况,给setCount出了一种输入函数的的方式,可以这么写: setCount((preCount) => preCount + 1), return出去的值就是最新的值,然后参数preCount始终是最新的值。

2、操作Dom

Vue

  使用ref,访问其返回值的.value属性即可获取相应dom。

<template>
    <div ref="wrapRef" class="wrap"></div>
</template>
import { ref, onMounted } from 'vue'
const wrapRef = ref(null)
onMounted(() => {
    console.log(wrapRef.value);  // 打印出该dom 
})

React

  使用useRef钩子,访问其返回的.current属性即可获取相应dom,注意只能在函数组件中使用钩子。

import ReactDom from 'react-dom/client'
import { useRef } from 'react'
const App = () => {
    const wrapRef = useRef()
    const getRef = () => {
        console.log(wrapRef.current) // 打印出该dom
    }
    return <div ref={wrapRef}>
        <button onClick={getRef}>获得ref</button>
    </div>
}
const root = ReactDom.createRoot(document.querySelector('#root'))
root.render(<App />)

  在类组件中可以使用 React.createRef() api去创建存储dom属性的对象。

3、渲染一个列表

Vue

  使用v-for在dom上渲染。

<tempalte>
    <ul>
        <li v-for="user in dataSource" :key=user.id > {{ user.name }}</li>
    </ul>
</template>
const dataSource = [
    {
        id:1,
        name:'小白',
        age: 23
    },
     {
        id:2,
        name:'小红',
        age: 24
    },
]

React

  使用map进行循环渲染。

const App = () => {
    const dataSource = [
        {
            id:1,
            name:'小白',
            age: 23
        },
         {
            id:2,
            name:'小红',
            age: 24
        }
    ]
    return <ul>
        {dataSource.map((user) => {return <li key={user.id}>{ user.name }</li>})}
    </ul>
}

4、父传子

Vue

  通过属性传递和defineProps接收父组件的数据,例如:

  // 父组件

<template>
    <Child data="[1,2,3]" />
</template>

  // 子组件

const props = defineProps({
    data: {
        type: Object,
        default: () => []
    }
})
console.log(props.data) // [1,2,3]

React

  通过属性传递和函数组件的传参接收父组件的数据,例如:

// 函数组件
function Calendar() {
      const data = {name:'cat', age:18}
      return <CalendarItem data={data} />
}

function CalendarItem(props) {
    console.log(props.data) // {name:'cat', age:18}
}
// 类组件
class App extends React.Component {
    data = {
        name: 'cat',
        age: 18
    };
    render() {
        return (
            <div>
                <Child data={this.data} />
                Hello, World !
            </div>
        )
    }
}

class Child extends React.Component {
    render() {
        return <div>{this.props.data.name}</div>  // cat
    }
}

5、子传父

Vue

  子组件使用defineEmits定义事件抛出。

// 子组件 Child.vue
<tepmlate>
    <button @click="submit">点击</button>
</template>
<script setup>
   const emit = defineEmits(['onSubmit'])
   const submit = () => {
       emit('onSubmit', 'something')
   }
</script>

// 父组件
<tempalte>
    <Child @onSubmit="onSubmit" />
</template>
<script setup>
   const onSubmit = (value) => {
       console.log(value)  // 'something'
   }
</script>

React

  父组件上定义属性传递方法,子组件通过函数传参的方式传递数据。

const Child = (props) => {
    const submit = () => {
        props.onSubmit('something')
    }
    return <button onClick={submit}></button>
}

const App = () => {
    const onSubmit = (value) => {
        console.log(value) // 'something'
    } 
    return <div>
        <Child onSubmit={onSubmit} />
    </div>
}

6、将DOM传递到指定位置

  例如将弹出组件放置到根目录上。

Vue

  使用Teleport组件,<Teleport> 接收一个 to prop 来指定传送的目标。to 的值可以是一个 CSS 选择器字符串,也可以是一个 DOM 元素对象。

// 这段代码的作用就是告诉Vue“把以下模板片段传送到body标签下”。
<Teleport to="body">
    <div v-if="open" class="modal">
        <p>Hello from the modal!</p> 
        <button @click="open = false">Close</button> 
    </div>
</Teleport>

React

  使用ReactDOM.createPortalapi, 语法ReactDOM.createPortal(jsx, dom), 例如:

import ReactDOM from "react-dom";

const root = document.querySelector('#root')
const Backdrop = (props) => {
    return ReactDOM.createPortal(<div className="backdrop">
        {props.children}
    </div>, root);
};

  周末了,不干了,下周边学边再更新吧