Vue3学习日记(day4)

响应式状态(Vue3)

methods

对于DOM的更新详解

防抖函数

少量,单组件

多组件

计算属性

可写计算属性


我们继续来对后续的文档进行探究。


响应式状态(Vue3)

响应式状态在vue3进行了修改。

在选项式API中仍然为在data中声明属性,并可以使用this调用此实例。

接下来我们举一个例子,以便于更好理解异同;

(reactive函数:创建一个代理对象)

这是一个点击增加内部数字的按钮。

下例,在vue3中正常更新视图。

const originalState = { count: 0 };
const state = reactive(originalState);
state.count++;

下例,在vue3中无法正常更新视图,在vue2中正常更新视图。

const originalState = { count: 0 };
const state = reactive(originalState);
originalState.count++; 

原因:

Vue 3 使用 Proxy 来实现响应式,当我们使用 reactive 函数将一个对象转换为响应式时,实际上 Vue 在内部创建了一个代理对象来包装这个原始对象。虽然你仍然使用 state.count++ 这样的语法来访问和修改数据,但你实际上操作的已经不是原始对象本身,而是 Vue 创建的代理对象。    

Vue 2 使用了一种称为“脏检查”(dirty checking)的策略的变体,结合了属性的 getter 和 setter,来追踪数据变化。具体来说,Vue 2 使用了 Object.defineProperty 方法来遍历每个对象属性,为它们添加 getter 和 setter,以此来监控数据的变化。在 Vue 2 中,你可以直接操作原始对象,而 Vue 通常能够检测到这些变化并更新视图。

总结:或许看着很烦,你只需要记住在vue3中,请不要在你定义的data实例之外操作属性,如有必要,请使用reactive函数让其被代理,避免响应式失效。


methods

在选项式API中方法请不要使用箭头函数,因为Vue 自动为 methods 中的方法绑定了永远指向组件实例的 this

eg:

export default {
  data() {
    return {
      count: 0
    }
  },
  methods: {
    increment() {
      this.count++
    }
  },
  mounted() {
    // 在其他方法或是生命周期中也可以调用方法
    this.increment()
  }
}
export default {
  methods: {
    increment: () => {
      // 反例:无法访问此处的 `this`!
    }
  }
}

对于DOM的更新详解

在 Vue 中,当你的响应式数据发生变化时,Vue 并不会立即更新 DOM(文档对象模型),而是将这些变化放入一个队列中,并在下一个事件循环(也就是所谓的“next tick”)中进行批量处理。这样做的目的是提高效率,避免频繁的 DOM 操作导致性能下降。

(nextTick:这是 Vue 提供的一个全局函数,它会延迟执行你传入的回调函数,直到 DOM 更新完成。)

eg:

export default {
  data() {
    return {
      count: 0
    };
  },
  methods: {
    increment: function() {
      this.count++;
      console.log('数据已更新');

      // 这里尝试获取更新后的元素,但 DOM 可能还没有更新
      const element = document.querySelector('#my-element');
      console.log(element.textContent); // 这里的值可能是旧的

      // 使用 $nextTick 来确保 DOM 更新完成后再执行代码
      this.$nextTick(() => {
        const updatedElement = document.querySelector('#my-element');
        console.log(updatedElement.textContent); // 这里的值应该是更新后的
      });
    }
  },
  mounted() {
    // 如果需要在组件挂载后执行某些操作,可以在这里写
  }
};

防抖函数

防抖函数:减少函数在短时间内被连续调用的次数,从而优化性能。而是为了防止在高频触发事件(如窗口调整大小、滚动或快速连续点击)时,某个函数被不必要的频繁执行。例如,在用户输入搜索框时,你可能不希望每次键盘敲击都发送一次网络请求,这时就可以使用防抖来限制请求的频率。

少量,单组件

import { debounce } from 'lodash-es'

export default {
  methods: {
    // 使用 Lodash 的防抖函数
    click: debounce(function () {
      // ... 对点击的响应 ...
    }, 500)
  }
}

多组件

(如果多个组件实例都共享这同一个预置防抖的函数,那么它们之间将会互相影响):

export default {
  created() {
    // 每个实例都有了自己的预置防抖的处理函数
    this.debouncedClick = _.debounce(this.click, 500)
  },
  unmounted() {
    // 最好是在组件卸载时
    // 清除掉防抖计时器
    this.debouncedClick.cancel()
  },
  methods: {
    click() {
      // ... 对点击的响应 ...
    }
  }
}

计算属性

下面的例子是根据 author 是否已有一些书籍来展示不同的信息。

此例,正常运行,但模板过于复杂。

<p>Has published books:</p>
<span>{{ author.books.length > 0 ? 'Yes' : 'No' }}</span>
export default {
  data() {
    return {
      author: {
        name: 'John Doe',
        books: [
          'Vue 2 - Advanced Guide',
          'Vue 3 - Basic Guide',
          'Vue 4 - The Mystery'
        ]
      }
    }
  }
}

使用计算属性:

export default {
  data() {
    return {
      author: {
        name: 'John Doe',
        books: [
          'Vue 2 - Advanced Guide',
          'Vue 3 - Basic Guide',
          'Vue 4 - The Mystery'
        ]
      }
    }
  },
  computed: {
    // 一个计算属性的 getter
    publishedBooksMessage() {
      // `this` 指向当前组件实例
      return this.author.books.length > 0 ? 'Yes' : 'No'
    }
  }
}

【笔记:(在computed中如果只需要getter,则不需要声明,自动为getter;如果需要同时定义gettersetter,那么计算属性就需要被定义为一个对象,包含getset两个方法

 computed: {
    uppercaseInput: {
      get() {
        return this.inputValue.toUpperCase();
      },
      set(newValue) {
        this.inputValue = newValue.toUpperCase();
      }
    }

)】

优势:更加简便可见,逻辑更加清晰。

同样,我们使用方法也可以实现对应的逻辑功能,计算属性对于方法来说的优势在于,计算属性值会基于其响应式依赖被缓存。一个计算属性仅会在其响应式依赖更新时才重新计算。这意味着只要 author.books 不改变,无论多少次访问 publishedBooksMessage 都会立即返回先前的计算结果,而不用重复执行 getter 函数。如果是方法,且例子为更大的list集合,当数字无论是否发生变化都会一直执行getter函数。

可写计算属性

1:计算属性默认只读。

2:getter 的职责应该仅为计算和返回该值。不要改变其他状态、在 getter 中做异步请求或者更改 DOM。

3:避免直接修改计算属性值(只读)

4:如果需要可写计算数学,使用setget来更改。

eg:

this.fullName = 'Jane Smith';

fullName的setter将被触发,firstName将被设置为'Jane'lastName将被设置为'Smith'。因此,即使你修改的是fullName,实际上你是在修改firstNamelastName

  • 6
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值