数据和方法

阅读: 7612     评论:0

Data

组件的 data 选项是一个函数。Vue 在创建新组件实例的过程中会自动调用此函数。

data选项通常返回一个对象,然后 Vue 会通过响应性系统将其包裹起来,并以 $data 的形式存储在组件实例中。

为方便起见,作为语法糖,该对象的任何顶级属性也可以通过组件实例直接调用:

const app = Vue.createApp({
  data() {
    return { count: 4 }
  }
})

const vm = app.mount('#app')

console.log(vm.$data.count) // => 4
console.log(vm.count)       // => 4

// 修改 vm.count 的值也会更新 $data.count
vm.count = 5
console.log(vm.$data.count) // => 5

// 反之亦然
vm.$data.count = 6
console.log(vm.count) // => 6

这些实例属性仅在实例首次创建时被自动添加,所以你需要确保它们都在 data 函数返回的对象中。必要时,要对尚未提供所需值的属性使用 nullundefined 或其他占位的值。

在Vue实例被初始化后,再往data中手动添加新属性虽然是可以操作的,但该新属性不具备响应式功能,只是个傻瓜属性。

Vue 使用 $ 前缀通过组件实例暴露自己的内置 API。Vue还为内部属性保留 _ 前缀。也就是说,你给自家的变量起名字一定不能用这两个符号开头。

methods

Vue通过methods 选项为组件实例添加方法,选项对应的值是一个“字典”对象,对象中的每个元素是你自定义的一系列方法:

const app = Vue.createApp({
  data() {
    return { count: 4 }
  },
  methods: {
    increment() {
      // `this` 指向该组件实例
      this.count++
    }
  }
})

const vm = app.mount('#app')

console.log(vm.count) // => 4

vm.increment()

console.log(vm.count) // => 5

Vue 会自动为 methods 绑定 this,以便于它始终指向组件实例。这将确保方法在用作事件监听或回调时保持正确的 this 指向。所以在定义 methods 时应避免使用箭头函数,因为这会阻止 Vue 绑定恰当的 this 指向。

methods 和组件实例的其它所有属性一样可以在组件的模板中被访问。在模板中,它们通常被当做事件监听使用,比如:

<button @click="increment">Up vote</button>

在上面的例子中,点击 <button> 时,会调用 increment 方法。

也可以直接在模板支持 JavaScript 表达式的任何地方调用方法:

<span :title="toTitleDate(date)">
  {{ formatDate(date) }}
</span>



// 思考一下,如果是这样,会不会调用toTitleDate方法呢?
// <span title="toTitleDate(date)">

防抖和节流

科普

案例:浏览器的scroll(滚动条滚动)、keypress(按动按键)、mousemove(鼠标移动)、窗口拖动等等事件在触发时,会不断的调用绑定在事件上的回调函数,如果回调函数比较复杂就会导致响应跟不上触发,有可能造成页面的卡顿,极大地浪费资源,降低前端的性能。

对此有两种解决方案:防抖(debounce ) 和 节流(throttling );

防抖:对在短时间内多次触发事件的回调函数,只执行最后一次,或者只在最开始时执行。

节流:类似防抖,不过节流是在一段时间之内只允许回调函数执行一次。

总之,防抖是整个过程只允许最开始或结尾执行一次。节流是在整个过程中每隔一定时间执行一次。根据不同场景选择合适的用法。对于有停顿的高频触发事件建议选择防抖,然而对于高频触发并且连续的事件,选择节流。

参考: https://segmentfault.com/a/1190000018428170?utm_source=tag-newest

无防抖功能的例子:

<html>
    <script src="https://unpkg.com/vue@next"></script>
    <body>

        <div id="test">
          <span @drag="print">选择这段文本拖动它观察console</span>
        </div>

        <script>
          const app = Vue.createApp({
            methods: {
              print(){
                console.log('drag')
              }
            },
          })
          app.mount('#test')
          </script>
    </body>
</html>

Vue 没有内置支持防抖和节流功能,但可以使用 Lodash 等库来实现。

如果某个组件仅使用一次,可以在 methods 中直接应用防抖:

<script src="https://unpkg.com/lodash@4.17.20/lodash.min.js"></script>
<script>
  Vue.createApp({
    methods: {
      // 用 Lodash 的防抖函数
        // lodash会自动注册为下划线变量
      click: _.debounce(function() {
        // ... 响应点击 ...
      }, 500)
    }
  }).mount('#app')
</script>

使用lodash为上面的例子添加防抖功能:

<html>
    <script src="https://unpkg.com/vue@next"></script>
    <script src="https://unpkg.com/lodash@4.17.20/lodash.min.js"></script>

    <body>

        <div id="test">
          <span @drag="print">选择这段文本拖动它观察console</span>
        </div>

        <script>
          const app = Vue.createApp({
            methods: {
              print:_.debounce(function(){
                console.log('drag')
              },500)
            },
          })
          app.mount('#test')
          </script>
    </body>
  </html>

但是,当上面的方法应用于可复用组件时,却存在潜在的问题,因为它们都共享相同的防抖函数。

为了使组件实例彼此独立,可以在组件的生命周期钩子的 created 函数里添加该防抖函数,最后在unmounted钩子函数里移除防抖函数:

app.component('save-button', {
  created() {
    // 用 Lodash 的防抖函数
    this.debouncedClick = _.debounce(this.click, 500)
  },
  unmounted() {
    // 移除组件时,取消定时器
    this.debouncedClick.cancel()
  },
  methods: {
    click() {
      // ... 响应点击 ...
    }
  },
  template: `
    <button @click="debouncedClick">
      Save
    </button>
  `
})

 模板语法 计算属性和侦听器 

评论总数: 0


点击登录后方可评论