Composition API

834 阅读2分钟

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

一、Composition API使用

在不借助任何构建工具的情况下,使用script标签设置type为module的方式引入vue.esm-browser.js模块,来学习Composition API使用

注意:如果直接右键在浏览器中打开页面,会报跨域的错误如下截图,需要借助vscode的Live Server插件在本地运行一个服务才可以正常访问,安装Live Server,然后右键“open with Live Server”,为什么会跨域可以参考:blog.csdn.net/qq_44163269…

  • creatApp: 创建Vue对象
  • setup: CompositionApI的入口
  • reactive:创建响应式对象
<body>
  <div id="app">
    x: {{ position.x }} <br>
    y: {{ position.y }} <br>
  </div>
  <script type="module">
    import { createApp, reactive } from './node_modules/vue/dist/vue.esm-browser.js'
	// createApp 的作用是创建一个vue对象,接收一个选项作为参数,也就是一个组件的选项,与Vue.js 2.x给Vue构造函数传入的选项一样,可以传入data,methods,created,components等
    const app = createApp({
      setup () {
        // 第一个参数 props,响应式对象,不能被解构
        // 第二个参数 context, attrs、emit、slots
        const position = reactive({
          x: 0,
          y: 0
        })
        return {
          position
        }
      },
      mounted () {
        this.position.x = 100
      }
    })
    console.log(app)

    app.mount('#app')
  </script>
</body>

二、setup中的生命周期钩子函数

  • 在setup中可以使用组件生命周期的钩子函数,但是要在函数名称前面加on并且函数名称首字母大写,例如:mounted在setup中要写成onMounted,还要在import中导入使用的钩子函数
  • setup在beforeCreate和created之间执行,对应的代码都可以在setup中执行,所以不需要再在setup中注册beforeCreate和created
  • onUnmounted相当于2.x版本中的destoryed
  • 新增钩子函数:onRenderTracked onRenderTriggered(都是在render函数被重新调用的时候触发,区别在于onRenderTracked 在首次调用render时也会触发,而onRenderTriggered首次调用render时不会触发)
<body>
  <div class="" id="app">
    x: {{ position.x }} <br>
    y: {{ position.y }}
  </div>
  <script type="module">
    import { createApp, reactive, onMounted, onUnmounted } from './node_modules/vue/dist/vue.esm-browser.js' // 按需导入

    function useMousePosition() {
      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
    }

    // createApp 的作用是创建一个vue对象,接收一个选项作为参数,也就是一个组件的选项,与Vue.js 2.x给Vue构造函数传入的选项一样,可以传入data,methods,created,components等
    const app = createApp({
      setup() {
        const position = useMousePosition()

        return {
          position
        }
      }
    })

    console.log(app)
    app.mount('#app')
  </script>
</body>

三、reactive-toRefs-ref

  • reactive创建的响应式数据解构后不再是响应式,toRefs可以把响应式对象的所有属性也转换成响应式的,所以可以解构toRefs返回的对象,解构之后还是响应式数据;
  • reactive是把普通对象转化成响应式对象,而ref是将基本类型数据包装成响应式对象。 toRefs的使用:
<body>
  <div class="" id="app">
    x: {{ x }} <br>
    y: {{ y }}
  </div>
  <script type="module">
    import { createApp, reactive, onMounted, onUnmounted, toRefs } from './node_modules/vue/dist/vue.esm-browser.js' // 按需导入

    function useMousePosition() {
      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 toRefs(position) // toRefs把响应式对象的所有属性也转化成响应式的
    }

    // createApp 的作用是创建一个vue对象,接收一个选项作为参数,也就是一个组件的选项,与Vue.js 2.x给Vue构造函数传入的选项一样,可以传入data,methods,created,components等
    const app = createApp({
      setup() {
        const { x, y } = useMousePosition() // toRefs返回的对象,解构之后还是响应式数据

        return {
          x,
          y
        }
      }
    })

    console.log(app)
    app.mount('#app')
  </script>
</body>

ref的使用:

<body>
  <div id="app">
    <button @click="increase">点击加1</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++ // 代码中使用的时候value不能省略,模板中使用可以省略
        }
      }
    }

    createApp({
      setup() {
        return { 
          ...useCount() 
        } // 把变量和方法一起解构出来
      }
    }).mount('#app')
  </script>
</body>

四、Computed

computed可以创建一个响应式数据,这个响应式数据依赖于其他响应式数据,就是计算属性。

  • 第一种用法
    • computed(()=>count.value+1)
  • 第二种用法
const count = ref(1)
const plusOne = computed({
  get: () => count.value + 1,
  set: val => {
    count.value = val - 1
  }
})

案例:

<body>
  <div id="app">
    <button @click="push">添加待办</button>
    <span>未完成的数量:{{ activeCount }}</span>
  </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: true },
    ]

    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>
</body>

五、Watch

1. Watch的三个参数:

  • 第一个参数:要监听的数据,可以是ref或者是reactive响应式数据
  • 第二个参数:监听到数据变化后执行的函数,这个函数有两个参数分别是新值和旧值
  • 第三个参数:选项对象,deep和immediate

2.Watch的返回值

  • 取消监听的函数 案例:
<body>
  <div id="app">
    请选择一个yes/no的问题:
    <input v-model.lazy="question">
    <p>{{answer}}</p>
  </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>

六、WatchEffect

  • 是Watch函数的简化版本,也用来监视数据的变化,不同的是没有第二个参数
  • 接受一个函数作为参数,监听函数内响应式数据的变化,当函数内响应式数据发生变化时函数会立即再调用一次
  • 也是返回一个取消监听的函数 案例:
<body>
  <div id="app">
    <button @click="increase">increase</button>
    <button @click="stop">stop</button>
    <span>{{count}}</span>
  </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>