文章内容输出来源 拉勾教育大前端高薪训练营

本文主要围绕 Composition API 来讲解如何使用,分别是以下几个API 函数, 通过学习,可以让你可以更快上手 Composition API ,掌握 Vue.js 3.0 的新特性。

  • 生命周期钩子变化
  • reactive API
  • toRefs API
  • ref API
  • computed API变化
  • watch API变化
  • toRefs 原理
  • watchEffect API

1、Compostion API

安装Vue3.0 ,体验 createApp 的使用

npm install vue@3.0.0-rc.1
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="app">
    x: {{ position.x }}
    y: {{ position.y }}
  </div>
  <script type="module">
    import { createApp } from './node_modules/vue/dist/vue.esm-browser.js'
    const app = createApp({
      data () {
        return {
          position: {
            x: 0,
            y: 0
          }
        }
      }
    })
    console.log(app)
    app.mount('#app')
  </script>
</body>
</html>

Vue 3.0Vue2.0 的区别,成员要少很多,没有$开头, 使用方式和以前一样

在这里插入图片描述

2、生命周期钩子函数

setUp 函数

import { createApp, reactive, onMounted, onUnmounted } from './node_modules/vue/dist/vue.esm-browser.js'
const app = createApp({
  setup () {
    // 第一个参数 props
    // 第二个参数 context, attrs, emit, slots
    const position = reactive({
      x: 0,
      y: 0
    })
    const update = e => {
      position.x = e.pageX;
      position.y = e.pageY;
    }
    
    onMounted (() => {
      window.addEventListener('mousemove', update)
    })

    onUnmounted (() => {
      window.removeEventListener('mousemove', update)
    })
    return {
      position
    }
  }
})
console.log(app)
app.mount('#app')

当鼠标移动的时候显示鼠标移动的位置,当组件卸载时,鼠标移动的事件也要移除

在这里插入图片描述

将获取鼠标位置的方法封装到一个函数中,优化代码

import { createApp, reactive, onMounted, onUnmounted } from './node_modules/vue/dist/vue.esm-browser.js'
function useMousePosition () {
  // 第一个参数 props
  // 第二个参数 context, attrs, emit, slots
  const position = reactive({
    x: 0,
    y: 0
  })
  const update = e => {
    position.x = e.pageX;
    position.y = e.pageY;
  }
  
  onMounted (() => {
    window.addEventListener('mousemove', update)
  })

  onUnmounted (() => {
    window.removeEventListener('mousemove', update)
  })
  return position
}
const app = createApp({
  setup () {
    const position = useMousePosition()
    return {
      position
    }
  }
})
console.log(app)
app.mount('#app')

3、reactive、toRefs 、ref 函数

都是创建响应式数据的

先看上一节出现的小问题

import { createApp, reactive, onMounted, onUnmounted } from './node_modules/vue/dist/vue.esm-browser.js'
function useMousePosition () {
  // 第一个参数 props
  // 第二个参数 context, attrs, emit, slots
  const position = reactive({
    x: 0,
    y: 0
  })
  const update = e => {
    position.x = e.pageX;
    position.y = e.pageY;
  }
  
  onMounted (() => {
    window.addEventListener('mousemove', update)
  })

  onUnmounted (() => {
    window.removeEventListener('mousemove', update)
  })
  return position
}
const app = createApp({
  setup () {
    // const position = useMousePosition()
    const { x, y} = useMousePosition()
    return {
      x,
      y
    }
  }
})
console.log(app)
app.mount('#app')

useMousePosition进行解构后,数据不是响应式的了

这里的 position 是响应式对象,因为在useMousePosition中调用了reactive 函数,把传入的对象包装成了 Proxy 对象,也就是说 position 就是 proxy对象,当 position 访问 x, y的时候会调用代理中的 getter 拦截收集依赖,变化的时候会调用 setter

使用 toRefs

import { createApp, reactive, onMounted, onUnmounted, toRefs } from './node_modules/vue/dist/vue.esm-browser.js'
...
return toRefs(position)

toRefs原理

toRefs 要求传入的参数 必须为代理对象,当前的 position 就是 reactive返回的代理对象,如果不是的话,会发出警告,提示传递代理对象,
内部会创建一个新的对象,然后遍历传入代理对象的所有属性,把所有属性的值都转换成响应式对象,相当于将postionx, y属性转换成响应式对象,
挂在到新创建的对象上,最后把新创建的对象返回。内部为代理对象的每一个属性创建一个具有 value 属性,value属性具有 getter,setter, getter 中返回对象属性的值,
setter中给代理对象赋值。所以返回的每一个属性都是响应式的

ref 把普通数据转转换成响应式数据,ref 可以把基本类型包装成响应式数据

<div id="app">
  <button @click="increase">点击</button>
  <span>{{ count }}</span>
</div>
<script type="module">
  import { createApp, ref } from './node_modules/vue/dist/vue.esm-browser.js'
  function useCount () {
    const count = ref(0)
    return {
      count,
      increase: () => {
        count.value++
      }
    }
  }
  createApp({
    setup() {
      return {
        ...useCount()
      }
    }
  }).mount('#app')
</script>

4、Computed

第一种用法

  • wacth(() => { count.value + 1})

第二种用法

const count = ref(1)

const plusOne = computed({
  get: () => {
    count.value + 1
  },
  set: val => {
    conut.value = val - 1
  }
})
<div id="app">
  <button @click="push">点击</button>
  未完成 {{ activeCount }}
</div>
<script type="module">
  import { createApp, reactive, computed } from './node_modules/vue/dist/vue.esm-browser.js'

  const  data = [
    {
      text: '看书',
      completed: false
    },
    {
      text: '敲代码',
      completed: false
    },
    {
      text: '学习',
      completed: false
    }
  ]

  createApp({
    setup() {
      const todos = reactive(data)
      const activeCount = computed(() => {
        return todos.filter(item => !item.completed).length
      })

      return {
        activeCount,
        push: () => {
          todos.push({
            text: '开会',
            completed: false
          })
        }
      } 
    }
  }).mount('#app')
</script>

5、Watch

Watch 的三个参数

  • 第一个参数: 要监听的数据
  • 第二个参数: 监听到数据变化后执行的函数,这个函数有两个参数分别是新值和旧值
  • 第三个参数: 选项对象, deep 和 immediate
    Watch 的返回值
  • 取消监听的函数
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
<div id="app">
  请问一个 yes/no 的问题
  <input v-model="question"></input>
  {{answer}}
</div>
<script type="module">
  import { createApp, ref, watch } from './node_modules/vue/dist/vue.esm-browser.js'

  createApp({
    setup() {
      const question = ref('')
      const answer = ref('')
      watch(question, async (newValue, oldValue) => {
        const response = await fetch('https://www.yesno.wtf/api')
        const data = await response.json()
        answer.value = data.answer
      })
      return {
        question,
        answer
      }
    }
  }).mount('#app')
</script>
</body>
</html>

6、watchEffect

  • 是watch 函数的简化版本,也用来监视数据的变化
  • 接收一个函数作为参数,监听函数内响应式数据的变化
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <button @click="increase">increase</button>
    <button @click="stop">stop</button>
    <br>
    {{count}}
  </div>
  <script type="module">
    import { createApp, ref, watchEffect } from './node_modules/vue/dist/vue.esm-browser.js'

    createApp({
      setup() {
        const count = ref(0)
        const stop = watchEffect(() => {
          console.log(count.value)
        })
        return {
          count,
          stop,
          increase: () => {
            count.value++
          }
        }
      }
    }).mount('#app')
  </script>
</body>
</html>

完整代码请点击这里

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐