vue3学习compositionAPI和组件高级用法

38 阅读2分钟

生命周期钩子

setup可以用来代替data,methods,computed,watch等等选项,也可以代替生命周期钩子。 可以使用onX导入函数实现生命周期

实现挂载生命周期

  import { onMounted, onUpdated, onUnmounted } from 'vue'
  export default {
    setup() {
      onMounted(() => {
        console.log("lifecircle mounted");
      })
    }
  }

beforecreated和created vue3中没有,直接在setup中写。

image.png

provide和inject

爷组件中

import { provide } from 'vue'
  setup() {
    const name = 'juju';
    let counter = 100;
    provide("name", name);
    provide("counter", counter);

  }

注入

  import { inject } from 'vue'
      const name = inject("name");   //第二个参数是默认值
      let counter = inject("counter");   

同时,如果传入的值是一个ref对象,那么应尽量传入一个readonly对象,避免子孙组件去修改传入的值

    const name = ref('juju');
    let counter = ref(100);
    provide("name", readonly(name));  //在使用provide时多使用readonly,使得子孙组件不能修改数据
    provide("counter", readonly(counter));

vue3中封装写法

建立一个hooks文件夹,放入完成的功能 useCounter.js

import { ref, computed } from 'vue'

export default function() {
  const number = ref(0);
  const doubleNumber = computed(() => number.value * 2);
  const plus = () => {
    number.value++
  }
  const sub = () => {
    number.value--
  }

  return {
    number,
    doubleNumber,
    plus,
    sub
  }
}

组件中引入

import useCounter from './hooks/useCounter.js'


  setup() {

    const increment = () => counter.value++;
    const { number, doubleNumber, plus, sub } = useCounter();
    return {
      increment,
      number,
      doubleNumber,
      plus,
      sub

    }

  }

setup顶层写法

由于script标签里只有setup代码,因此以后可以在标签里直接加入setup

<script setup>
  import { ref } from 'vue';

  const counter = ref(0);
  const increament = () => counter.value++;
  
</script>

对于组件导入,无需写components option

<template>
  <div>
    <h2>当前计数: {{ counter }}</h2>
    <button @click="increament">+1</button>
    <hello-world></hello-world>
  </div>
</template>
<script setup>
  import HelloWorld from './HelloWorld'
  import { ref } from 'vue';

  const counter = ref(0);
  const increament = () => counter.value++;

</script>

对于props,需要导入新函数

<template>
  <div>
    {{ message }}
  </div>
</template>
<script setup>
import { defineProps } from 'vue';
  const props = defineProps({
    message: {
      type: String,
      default: '哈哈啊哈'
    }
  })
</script>

对于事件也需要导入一个函数

<template>
  <div>
    <button @click="emitEvent">发射事件</button>
  </div>
</template>

<script setup>
  import { defineEmits } from 'vue';
  const emit = defineEmits(["increment", "decrement"]);
  const emitEvent = () => {
    emit('increment', '10000')
  }

</script>

<style scoped>

</style>

render函数

通过h函数可以给render函数返回一个vnode从而创建vnode对象。 h函数接受三个参数,

  • 1.一个html标签,一个组件,一个异步组件或函数式组件。 如'div'
  • 2.属性值。如div的class,id等
  • 3.子元素。
<script>
  import { h } from 'vue'
  export default {
    render() {
      return h('h2', {class: 'title'}, "helloworldxixi")
    }
  }
</script>

<style scoped>

</style>

此时就能在页面上创建出一个h2标签。

render函数计数器案例

<script>
  import { h, ref } from 'vue'
  export default {
    setup() {
      const counter = ref(0);
      return {
        counter
      }
    },
    render() {
      return h('div', {class: 'app'}, [
        h('h2', null, `当前计数: ${this.counter}`),
        h('button', {
          onClick: () => this.counter++
        }, "+1"),
        h('button', {
          onClick: () => this.counter--
        }, "-1"),
      ])
    }
  }
</script>

<style scoped>

</style>

由于render绑定了this,因此可以用this.counter获取值

jsx的使用

jsx可以使用一个工具将jsx转成render函数。