Vue3学习第二天

我心飞翔 分类:javascript

数据,方法,计算属性和侦听器

如果我们在click方法中使用箭头函数,因为this会一层一层往上找,那么此时的this执行的是window

<body>
  <div id="root">
  </div>
  <script>
     // this = window
    // data & methods & computed & watcher
    const app = Vue.createApp({
      data () {
        return {
          tip: 'vue3学习',
        }
      },
      methods: {
        alertClick: () => {
          console.log('click', this)
        }
      },
      template: `
      <div @click="alertClick">{{tip}}</div>
      `
    })
    const vm = app.mount('#root')
  </script>
</body>
 

控制台显示结果:

this.png

结论: 所以在Vue中我们最好定义方法的时候不要用箭头函数去写,可以采用下面的代码方法

<body>
  <div id="root">
  </div>
  <script>
    // data & methods & computed & watcher
    const app = Vue.createApp({
      data () {
        return {
          tip: 'vue3学习',
        }
      },
      methods: {
        alertClick() {
          console.log('click', this)
        }
      },
      template: `
      <div @click="alertClick">{{tip}}</div>
      `
    })
    const vm = app.mount('#root')
  </script>
</body>
 

控制台显示结果:

nothis.png

结论: 这样写的话,Vue会自动将this绑定到vue的实例上面

除了上面这样用,我们还可以在插值表达式中使用方法

<body>
  <div id="root">
  </div>
  <script>
    // data & methods & computed & watcher
    const app = Vue.createApp({
      data () {
        return {
          tip: 'VUE',
        }
      },
      methods: {
        formatString(value) {
          return value.toLowerCase()
        }
      },
      template: `
      <div>{{formatString(tip)}}</div>
      `
    })
    const vm = app.mount('#root')
  </script>
</body>
 

这样控制台输出的结果就会将大写的VUE都转成小写的vue

tolow.png

computed的使用

<body>
  <div id="root">
  </div>
  <script>
    // data & methods & computed & watcher
    const app = Vue.createApp({
      data () {
        return {
          tip: 'VUE',
          num: 4,
          price: 10,
        }
      },
      computed: {
        totalPrice() {
          return this.num * this.price
        }
      },
      methods: {
      },
      template: `
      <div>{{totalPrice}}</div>
      `
    })
    const vm = app.mount('#root')
  </script>
</body>
 

当我们代码中需要计算一个总价,为了更加语义化,我们可以使用computed方法,这样当我们中totalPrice依赖的numprice发生变化时,vue会自动计算totalPrice的值。

第二种,我们也可以通过methods的方法去计算总价,看下methods中的方法和computed有什么不同?

<body>
  <div id="root">
  </div>
  <script>
    // data & methods & computed & watcher
    const app = Vue.createApp({
      data () {
        return {
          tip: 'VUE',
          num: 4,
          price: 10,
        }
      },
      computed: {
        totalPrice() {
          return this.num * this.price
        }
      },
      methods: {
        getTotalPrice() {
          return this.num * this.price
        }
      },
      template: `
      <div>{{getTotalPrice()}}</div>
      `
    })
    const vm = app.mount('#root')
  </script>
</body>
 

当我们在methods中写了一个getTotalPrice方法,在控制台中通过vm.$data.price修改值,发现总价也会自动变化,这样看起来二者没有区别,但是如果仔细研究会发现二者还是有差异的?
当我们把代码这样写,如下

<body>
  <div id="root">
  </div>
  <script>
    // data & methods & computed & watcher
    const app = Vue.createApp({
      data () {
        return {
          tip: 'VUE',
          num: 4,
          price: 10,
        }
      },
      computed: {
        totalPrice() {
          return Date.now()
        }
      },
      methods: {
        getTotalPrice() {
          return Date.now()
        }
      },
      template: `
      <div>{{tip}} -- {{totalPrice}} --- "你好我是computed中的"</div>
      <div>{{tip}} -- {{getTotalPrice()}}--- "你好我是methods中的"</div>
      `
    })
    const vm = app.mount('#root')
  </script>
</body>
 

控制台输出结果:

update.png

当我们在控制台通过vm.$data.tip修改为110,看看控制台的变化?

updated.png

下面说下computed和methods的区别?

computed: 当计算属性依赖的内容发生变化时,才会重新执行计算,如果依赖的内容没有发生变化,会有缓存的。

mehtods:只要页面重新渲染,才会重新计算

虽然computedmethods都能实现相同的效果,但是computed内存带有缓存的效果,所以computed在做页面渲染的时候会更高效一些,一般来说我们能既能采用methods又能采用computed,一般我们会采用computed

watch的使用

实现效果:当price发生变化时,等几秒钟打印"price change"这个字符串,可以使用watch做一些异步操作

<body>
  <div id="root">
  </div>
  <script>
    // data & methods & computed & watcher
    const app = Vue.createApp({
      data () {
        return {
          tip: 'VUE',
          num: 4,
          price: 10,
        }
      },
      watch: {
        price() {
          setTimeout(() => {
            console.log('price change')
          }, 3000)
        }
      },
      computed: {
        totalPrice() {
          return Date.now()
        }
      },
      methods: {
        getTotalPrice() {
          return Date.now()
        }
      },
      template: `
      <div>{{tip}} -- {{totalPrice}} --- "你好我是computed中的"</div>
      <div>{{tip}} -- {{getTotalPrice()}}--- "你好我是methods中的"</div>
      `
    })
    const vm = app.mount('#root')
  </script>
</body>
 

当我们在控制台输入vm.$data.price = 500, 等3s控制台会打印出"price change"字符串

watch.png

我们用watch仿造computed做一下计算

<body>
  <div id="root">
  </div>
  <script>
    // data & methods & computed & watcher
    const app = Vue.createApp({
      data () {
        return {
          tip: 'VUE',
          num: 4,
          price: 10,
          totalPrice: 40
        }
      },
      watch: {
        price(newValue, oldValue) {
          this.totalPrice = newValue * this.num
        }
      },
      computed: {
        // totalPrice() {
        //   return Date.now()
        // }
      },
      methods: {
        // getTotalPrice() {
        //   return Date.now()
        // }
      },
      template: `
      <div>{{totalPrice}}</div>
      `
    })
    const vm = app.mount('#root')
  </script>
</body>
 

我们在控制台输入vm.$data.price = "100",回车后发现得到的是400,看起来和计算属性computed实现的效果是一样的。

控制台输出结果:

newwatch.png

结论:但是我们发现,如果使用watch我们在data中需要再定义一个变量。所以一个同步功能可以用watchcomputed同时实现,我们用computed会更加简洁一些,如果是异步功能使用watch会更好一些。

回复

我来回复
  • 暂无回复内容