4.0 Vue.js中的computed的设计

1、关于computed的功能描述

computed作为计算属性其作用是描述响应式数据的复杂逻辑计算,当所依赖的响应式数据发生改变时计算属性会重新计算,更新逻辑计算的结果。

有个体现计算属性特点的便是比较计算属性和方法的区别,比如我们需要计算两个响应式数据的和

const obj = new reactive({foo: 1, bar: 2})
// 使用计算属性获取值
const value = computed(() => {obj.foo + obj.bar})
// 使用方法获取值
const value = () => obj.foo + obj.bar

其区别为computed有缓存机制,当内部依赖的响应式数据没有改变时则直接从缓存中获取结果,而方法则每次都需要执行。当依赖的响应式数据很多并且逻辑很复杂的时候那么计算属性效率会比方法高很多。

2、计算属性的lazy设计

对于计算属性我们只有在需要值的时候才需要计算,而computed(getter)以一个getter作为参数,即每次计算属性依赖的响应式数据改变的时候都需要重新执行getter,但是每次getter的每一次执行却是不必要的,因为只有当获取计算属性的值时才运行getter获取值,所以对于getter的计算需要懒惰执行。

在上一章节中已经介绍了调度器的作用,所以我们只需要在调度器中加入一个lazy的标记就行了

effect(() => {
    return obj.foo + obj.bar
}, {
	// 调度器中设置lazy标记
    lazy: true
})

function effect(fn, options = {}) {
    const effectFn = () => {
      	// 省略代码
    }
    effectFn.options = options
    effectFn.deps = []
	
	// 如过有缓存标记则直接返回
    if(options.lazy)
        return effectFn
    effectFn()
}

function computed(getter) {
    // 把getter作为一个副作用函数
    const effectFn = effect(getter, {
        lazy: true,
    })

    const obj = {
        // 只有当读取到value时才会触发effectFn
        get value() {
            return effectFn()
        }
    }

    return obj.value
}

这样只有我们在获取计算属性的value时才会触发副作用函数执行,而不会在响应式数据改变时就直接执行。

3、计算属性的缓存

假设我们在上述代码的设计基础下有以下代码

const sum = computed(() => obj.foo + obj.bar)

console.log(sum.value)
console.log(sum.value)
console.log(sum.value)

此时effectFn会接连执行三次,但是每次的结果都是一样的,因为计算属性所依赖的obj.foo \obj.bar的值并没有改变,所以我们可以直接将计算的结果缓存下来。

function computed(getter) {
    // 用来缓存计算的结果
    let value
    // 用于标记是否需要重新计算值
    let dirty = true

    let effectFn = effect(getter, {
        lazy: true
    }) 

    const obj = {
        get value() {
            // 如过需要重新计算值
            if(dirty) {
                value = effectFn()
                dirty = false
            }
            return value
        }
    }

    return obj
}

此时我们多次获取sum.value的值则不会每次都重新计算了,但是这样写有一个非常明显的问题就是我们所依赖的响应式的值改变的时候不会重新计算,所以我们dirty这个标记还需要和依赖的响应式数据联系起来。具体做法是将dirty放入调度器中,这样每次响应式数据被改变的时候都会触发调度器改变dirty的值

function computed(getter) {
    // 用来缓存计算的结果
    let value
    // 用于标记是否需要重新计算值
    let dirty = true

    let effectFn = effect(getter, {
        lazy: true,
        // 当响应式数据修改时,触发副作用函数时修改dirty的值
        scheduler: () => {
            dirty = true
        }
    }) 

    const obj = {
        get value() {
            // 如过需要重新计算值
            if(dirty) {
                value = effectFn()
                dirty = false
            }
            return value
        }
    }

    return obj
}

其实还有一个问题就是当计算属性放入effect形成嵌套时,我们改变obj的值并不会触发外层的effect函数,即:

// 省略代码......

const sum = computed(() => obj.foo + obj.bar)
effect(() => {
    console.log(sum.value)
})

当改变obj.foo/obj.bar的值并不会输出sum.value的值。这是不符合应用场景的,在应用中当我们的计算属性改变的时候页面也会重新渲染。

整个问题分析一下就是effect嵌套的问题,当内层的响应式数据只和getter形成了联系,和外层的副作用函数并没有关系,而内部的value并不是响应式数据还是懒执行的,所以也就不会和外层的副作用函数产生联系了,这里解决的方案就是直接手动将计算属性的结果和外层副作用函数联系起来。


function computed(getter) {
    let value
    let dirty = true

    const effectFn = effect(getter, {
        lazy: true,
        scheduler: () => {
            dirty = true
            // 计算属性依赖的响应式数据发生改变时,手动触发响应
            trigger(obj, 'value')
        }
    })

    const obj = {
        get value() {
            if(dirty) {
                value = effectFn()
                dirty = false
            }
            // 读取value时手动追踪
            track(obj, 'value')
            return value
        }
    }

    return obj
}

关于计算属性,在使用时应该避免直接赋值,计算属性更多的是作为一个快照,记录响应式书记的逻辑关系结果的,他的改变只能是由他所以来的源发生改变之后触发,而不是手动赋值。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 基于vue.js的移动端设计是一种应用vue.js框架开发移动端应用的设计方法。vue.js是一种轻量级、灵活、易学易用的JavaScript框架,可以用于构建用户界面。在移动端设计vue.js可以帮助我们实现响应式的界面设计,提供良好的用户体验。 基于vue.js的移动端设计具有以下特点和优势: 1. 组件化开发:vue.js使得我们可以将页面划分为多个组件,每个组件都有自己的功能和样式。这样我们可以方便地对不同的组件进行修改和重用,提高开发效率。 2. 响应式设计vue.js采用了双向数据绑定的方式,可以实时更新界面上的数据。这使得移动端应用能够根据用户的操作动态地改变界面显示,提供更好的交互体验。 3. 轻量级框架:vue.js的文件大小较小,加载速度快,适合用于移动端应用的开发。同时,它也具有良好的性能,可以在移动设备上流畅运行。 4. 强大的生态系统:vue.js拥有丰富的插件和第三方库,可以方便地扩展功能。这使得我们可以快速地添加一些常用的组件和工具,提高开发效率。 基于vue.js的移动端设计需要了解vue.js的基本语法和特性,并熟悉移动端开发的相关技术和工具。同时,还需要考虑移动设备的特点,如不同尺寸的屏幕、触摸操作等,来优化用户体验。在具体的项目,我们可以使用vue-cli创建项目、使用vue-router进行页面导航、使用vuex进行状态管理等。 总之,基于vue.js的移动端设计可以帮助我们开发出高质量的移动应用,提供良好的用户体验。它是一种灵活、高效的设计方法,值得我们在移动端应用开发探索和应用。 ### 回答2: 基于vue.js的移动端设计是指利用vue.js这个优秀的前端框架来构建适用于移动设备的网页或应用程序。vue.js是一个轻量级的框架,具有响应式设计和双向数据绑定的特性,非常适合用于开发移动端的用户界面。 使用vue.js可以提供更好的用户体验和性能表现。它的虚拟DOM机制可以高效地对应用的视图进行更新和渲染,减少了页面重新加载的次数,使得移动端的网页或应用程序更加流畅。 在开发移动端设计时,vue.js还提供了丰富的组件库,可以方便地构建各种移动端页面需要的交互元素和视图组件,例如按钮、表单、列表等。这样不仅可以快速构建界面,还能保持一致的设计风格,提高用户的使用体验。 另外,vue.js还支持移动端常用的触摸事件,可以通过监听用户的触摸手势来实现更多的交互效果。同时,vue.js也可以与其他常用的移动端开发工具和插件进行集成,例如打包工具webpack,移动端UI库Vant等,进一步丰富功能和提升开发效率。 总之,基于vue.js的移动端设计具有响应式设计、高性能、丰富的组件库和易于集成等特点,能够帮助开发者快速构建出优秀的移动端网页和应用程序。 ### 回答3: 基于Vue.js的移动端设计是一种使用Vue.js框架来开发移动端应用程序的方法。Vue.js是一种流行的JavaScript框架,它通过响应式的数据绑定和组件化的开发方式,可以简化移动端应用开发的复杂性。 首先,基于Vue.js的移动端设计可以利用到Vue.js强大的数据绑定功能。Vue.js使用了双向数据绑定的概念,它可以确保数据和视图的自动同步。在移动端设计,我们可以将应用的数据和视图绑定起来,当数据发生变化时,视图会自动更新,从而提供更好的用户体验。 其次,基于Vue.js的移动端设计还可以充分利用Vue.js的组件化开发方式。组件化开发将应用的各个功能模块划分为独立的组件,每个组件都有自己的数据、视图和逻辑。这种方式有助于代码的复用性和维护性,同时也能提高开发效率。 另外,Vue.js还提供了一些移动端开发常用的插件和工具,例如Vue Router和Vuex。Vue Router可以用来管理移动端应用的路由,实现页面之间的跳转和导航;而Vuex则可以用来管理应用的状态,实现不同组件之间的状态共享。 总体而言,基于Vue.js的移动端设计具有简洁、高效和灵活等优点。它能够帮助开发人员快速搭建出结构清晰、交互流畅的移动应用,同时也为项目的维护和后续的扩展提供了便利。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值