vue3.0 Study

Vue3源码模块化分

  • runtime-core、runtime-dom、runtime-test这三个文件夹都是Vue 运行时相关的核心代码。
  • compiler-core、compiler-dom、compiler-sfc这三个文件夹是 Vue 实现的编译器相关代码。
  • server-renderer 是服务端渲染部分。
  • vue 文件夹是整个项目打包构建之后的出口文件。
  • reactive 文件夹是响应式系统部分

ref VS reactive

对于基本数据类型,函数传递或者对象解构时,会丢失原始数据的引用,换言之,我们没法让基本数据类型,或者解构后的变量(如果它的值也是基本数据类型的话),成为响应式的数据。

  1. 通过创建一个对象(Ref), 将原始数据保存在Ref的属性value当中,再将它的引用返回给使用者
  2. 通过toRefs(object)函数, 解决对象的解构丢失原始数据引用的问题
    通过遍历对象,将每个属性值都转成Ref数据,这样解构出来的还是Ref数据,自然就保持了响应式数据的引用 toRefs 解决的问题就是,开发者在函数中错误的解构 reactive,来返回基本类型。const { x, y } = = reactive({ x: 1, y: 2 }),这样会使 x, y 失去响应式,于是官方提出了 toRefs 方案,在函数返回时,将 reactive 转为 refs,来避免这种情况。
  3. 总的来说, reactive 目前支持的类型为 Object|Array|Map|Set|WeakMap|WeakSet , refs支持的类型为基本数据类型, toRefs解决对象解构赋值后引用丢失问题
    <template>
        <div class="about">
            <h1>This is an about page</h1>
            <p>
                <span>{{ obj1.fruit }}</span>
                <button @click.prevent="updateObj1">更新1</button>
            </p>
            <p>
                <span>{{ fruit }} -- {{ animal }}</span>
                <button @click="updateObj2">更新2</button>
            </p>
        </div>
    </template>

    <script>
        import { ref, toRefs, reactive } from 'vue'

        // 修改对象1
        function useObject1() {
            let obj1 = reactive({ fruit: 'apple' })
            let updateObj1 = () => obj1.fruit = obj1.fruit == 'apple' ?  'banana' : 'apple'
            return {
                obj1,
                updateObj1
            }
        }

        // 修改对象2
        function useObject2() {
            let obj2 = reactive({ fruit: 'apple', animal: 'monkey' })
            let updateObj2 = () =>  obj2 = { fruit: 'pear', animal: 'snake' }
            return toRefs(obj2)
        }

        export default {
            name: 'About',
            setup(props, context) {
                const { obj1, updateObj1 } = useObject1()
                const { fruit, animal } = useObject2()

                return {
                    obj1,
                    updateObj1,
                    fruit,
                    animal
                }
            }
        }
    </script>

computed

计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要 msg 还没有发生改变,多次访问 text 计算属性会立即返回之前的计算结果,而不必再次执行函数。

通过 computed 传入一个 getter 函数,返回一个默认不可手动修改的 ref 对象。或者传入一个拥有 get 和 set 函数的对象,创建一个可手动修改的计算状态。

    <template>
        <h1>{{ text }}</h1>
        <button @click="change">count is: {{ state.count }}</button>
        <p>Edit <code>components/HelloWorld.vue</code> to test hot module replacement.</p>
    </template>

    <script>
        import { ref, reactive, computed } from 'vue'
        export default {
            name: 'HelloWorld',
            props: {
                msg: String
            },
            setup(props){
                let state = reactive({count: 0})
                let text = computed(() => {
                    return props.msg.split('').reverse().join('')
                })
                const change = () => state.count++
                return { state, change, text }
            }
        }
    </script>

effect

effect其实就是一个依赖收集函数,在它内部访问了响应式数据,响应式数据就会把这个effect函数作为依赖收集起来,下次响应式数据改了就触发它重新执行。
reactive返回的就是个响应式数据,这玩意可以和effect搭配使用。

首先要知道,effect函数会立即开始执行,再执行之前,先把effect自身变成全局的activeEffect,以供响应式数据收集依赖。

并且activeEffect的记录是用栈的方式,随着函数的开始执行入栈,随着函数的执行结束出栈,这样就可以维护嵌套的effect关系。

举个简单的栗子吧:

    // 响应式数据
    const data = reactive({ count: 0 })
    // 依赖收集
    effect(() => console.log(data.count))
    // 触发上面的effect重新执行
    data.count ++

就这个例子来说,data是一个响应式数据。

effect传入的函数因为内部访问到它上面的属性count了,

所以形成了一个count -> effect的依赖。

下次count改变了,这个effect就会重新执行

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值