从vue2到react17-理解响应式数据

631 阅读2分钟

我正在参加「掘金·启航计划」

vue和react是当前社区中star最多的两大前端框架,这篇文章将从响应式数据的角度,剖析一下两个框架的异同。

vue和react的对比

image.png

相同点

  • 使用虚拟dom
  • 轻量级
  • 提供了响应式和组件化的视图组件
  • 都有生命周期

不同点

  • vue是双向绑定,react是单向数据流
  • vue使用html模板,react使用jsx

vue的响应式有哪些实现方案

在复杂的项目中,某些数据需要依赖其他一个或者多个数据变化的场景很常见。因此产生了响应式数据和响应式函数的概念。vue2.x中实现响应式数据有两种方案: 计算属性computed侦听器watch

computed

计算属性用于vue模板中有复杂的逻辑需要计算时。

例如:

var vm = new Vue({
    el: '#example',
    data: {
        message: 'Hello'
    },
    computed: {
        // 计算属性的 getter
        reversedMessage: function () {
            // `this` 指向 vm 实例
            return this.message.split('').reverse().join('')
        }
    }
})

watch

侦听属性一般用于需要在数据变化时执行异步或开销较大的操作时。

例如:

var watchExampleVM = new Vue({
    el: '#watch-example',
    data: {
        question: '',
        answer: 'I cannot give you an answer until you ask a question!'
    },
    watch: {
      // 如果 `question` 发生改变,这个函数就会运行
        question: function (newQuestion, oldQuestion) {
            this.answer = 'Waiting for you to stop typing...'
            this.debouncedGetAnswer()
        }
    },
    created: function () {
        this.debouncedGetAnswer = _.debounce(this.getAnswer, 500)
    },
})

vue的computed 和 watch 的区别在于。computed必须有一个返回值,这个值是一个响应式的属性,依赖属性变化时重新计算。watch则是一个响应式函数,当依赖属性变化时候执行。

react中的‘响应式数据’方案

严格来说,react官方采用单向数据流思想,并没有响应式的概念。但是react为了性能优化,采用了异步setState方案,由此导致了数据变化不能及时体现在页面上的问题。

为了解决这个问题,react提供了一个官方hook: useRef

const refContainer = useRef(initialValue);

console.log(refContainer.current)

useRef通常被用于父组件获取自组件dom,而由于useRef的current值相对render来说,相当于一个全局变量,始终可以取到state最新的值。因此,useRef也可以用于获取某个依赖的最新值

例如:

const [dep, setDep] = useState(0);
const depRef = useRef(dep);

setDep(1);
console.log(dep);  // 0
console.log(depRef.current); // 1