验证码: 看不清楚,换一张 查询 注册会员,免验证
  • {{ basic.site_slogan }}
  • 打开微信扫一扫,
    您还可以在这里找到我们哟

    关注我们

vue3.0中的computed怎么写

阅读:840 来源:乙速云 作者:代码code

vue3.0中的computed怎么写

      vue3.0 computed写法

      用computed计算属性之前别忘了引入

      vue3.0中的computed怎么写

      使用完毕别忘了导出

      computed里面还有两个方法:get和set

      • get方法:

      vue3.0中的computed怎么写

      结果:

      vue3.0中的computed怎么写

      get方法是读取数据时候调用的,监测到数据变化以后就自动执行:

      vue3.0中的computed怎么写

      vue3.0中的computed怎么写

      结果:

      vue3.0中的computed怎么写

      点击以后:

      vue3.0中的computed怎么写

      vue3.0中的computed怎么写

      说明get在程序运行时自动调用,后面监测到数据变化就再次调用

      我们改一下代码:

      vue3.0中的computed怎么写

      点击前结果:

      vue3.0中的computed怎么写

      vue3.0中的computed怎么写

      点击后结果:

      vue3.0中的computed怎么写

      vue3.0中的computed怎么写

      所以我们能得出: 点击button以后,执行到plusOne.value = 2时候,相当于调用了:

      // 其中参数val就是修改的值2
      set: val => {
              console.log('executing function set')
              return count.value = val - 1
            }

      所以现在count的值为2-1=1,这样的值改变引起set方法的注意,被监测到了,所以继续执行:

      get: () => {
              console.log('executing function get')
              return count.value + 1
            }

      这样count的值变成1+1 = 2

      所以最后显示2

      vue3.0 computed的使用及其注意点

      为什么使用

      当我们不想在template的html元素上写很长的js逻辑时,我们就会想使用计算属性computed

      使用

      computed

      传入一个 getter 函数,返回一个默认不可手动修改的 ref 对象。

      const count = ref(1)
      const plusOne = computed(() => count.value + 1)
      
      console.log(plusOne.value) // 2
      
      plusOne.value++ // 错误!
      // 或者传入一个拥有 get 和 set 函数的对象,创建一个可手动修改的计算状态。
      
      const count = ref(1)
      const plusOne = computed({
        get: () => count.value + 1,
        set: (val) => {
          count.value = val - 1
        },
      })
      
      plusOne.value = 1
      console.log(count.value) // 0
      // 更多文档: https://vue3js.cn/vue-composition-api/#computed

      正文

      计算属性,可能会依赖其他 reactive 的值,同时会延迟和缓存计算值

      export function computed(
        getterOrOptions: ComputedGetter | WritableComputedOptions
      ) {
        let getter: ComputedGetter
        let setter: ComputedSetter
      
        // 如果传入是 function 说明是只读 computed
        if (isFunction(getterOrOptions)) {
          getter = getterOrOptions
          setter = __DEV__
            ? () => {
                console.warn('Write operation failed: computed value is readonly')
              }
            : NOOP
        } else {
          // 不是方法说明是自定义的 getter setter 
          getter = getterOrOptions.get
          setter = getterOrOptions.set
        }
      
        let dirty = true
        let value: T
        let computed: ComputedRef
      
        // 创建 effect, 我们在看 effect 源码时知道了传入 lazy 代表不会立即执行,computed 表明 computed 上游依赖改变的时候,会优先 trigger runner effect, scheduler 表示 effect trigger 的时候会调用 scheduler 而不是直接调用 effect
        const runner = effect(getter, {
          lazy: true,
          // mark effect as computed so that it gets priority during trigger
          computed: true,
          scheduler: () => {
            // 在触发更新时把dirty置为true, 不会立即更新 
            if (!dirty) {
              dirty = true
              trigger(computed, TriggerOpTypes.SET, 'value')
            }
          }
        })
      
        // 构造一个 computed 返回
        computed = {
          __v_isRef: true,
          // expose effect so computed can be stopped
          effect: runner,
          get value() {
            // dirty为ture, get操作时,执行effect获取最新值
            // 
            if (dirty) {
              value = runner()
              dirty = false
            }
            // dirty为false, 表示值未更新,直接返回 
            track(computed, TrackOpTypes.GET, 'value')
            return value
          },
          set value(newValue: T) {
            setter(newValue)
          }
        } as any
        return computed
      }

      注意事项

      如果存在计算属性依赖其他异步或者props传进的属性,再通过state.xxx获取最新属性值进行判断,那么就必须写在getter回调里,例如:

      const haveFile = computed(() => state.jobInfo.fileName ? state.jobInfo.fileName.includes('http') : false);
      const permitProduct = computed(() => !state.isPower || state.isDqcFinish);
      const permitDownl = computed(() => !state.isPower || !haveFile.value);

      我们可以看到permitProduct 和permitDownl 都依赖state.isPower这个变量值,且该变量写在watch监听中,随时可能改变,因此,我们console.log写在permitDownl 变量的下一行,可能看不到最新结果的打印:

      const haveFile = computed(() => state.jobInfo.fileName ? state.jobInfo.fileName.includes('http') : false);
      const permitProduct = computed(() => !state.isPower || state.isDqcFinish);
      const permitDownl = computed(() => !state.isPower || !haveFile.value);
      console.log('state.isPower ===>', state.isPower);

      正确的做法,应该是写在getter回调里:

      const haveFile = computed(() => state.jobInfo.fileName ? state.jobInfo.fileName.includes('http') : false);
      const permitProduct = computed(() => !state.isPower || state.isDqcFinish);
      const permitDownl = computed(() => {
          console.log('state.isPower ===>', state.isPower); // 此时可以获得最新值
          return !state.isPower || !haveFile.value;
      });

      并且要注意的一点是,如果当前计算属性依赖其他计算属性,例如上面所写的permitDownl 依赖于 haveFile,这时,写法就必须是haveFile.value而非haveFile

      计算属性获取值在非template区域,而是在js区域内,则必须使用propname.value去获取值! 

    分享到:
    *特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们: hlamps#outlook.com (#换成@)。
    相关文章
    {{ v.title }}
    {{ v.description||(cleanHtml(v.content)).substr(0,100)+'···' }}
    你可能感兴趣
    推荐阅读 更多>