阅读 176

Composition API

setup

这是vue为组合式API提供的使用的地方,它里面的所有逻辑都在组件创建之前就开始执行了,也就是先于beforeCreate、created,所以存在this指向为空的情况,也不能使用data、methods的内容。

<template>
  <div>
    这是我的vue练习手册
  </div>
</template>

<script lang="ts">
import { defineComponent } from 'vue'

export default defineComponent({
  data () {
    return {
      name: '杨小羊'
    }
  },
  setup () {
    console.log('hello Vue!我已经打入了setup内部。')
    console.log(this)
  }
})
</script>
复制代码

// 运行结果: image.png

setup接收两个参数:props,context
执行setup,只能访问到props,attrs,slots,emit这几个property。

  • props是父组件向子组件传的、且已经被子组件通过props接收的所有属性
  • attrs是除子组件用props接收的以外的其他属性
  • slots即同通过插槽来传入的所有对象
  • emit用来分发函数

setup返回值:一般都以对象形式返回,其中的属性、方法,可以在模板中直接使用

// 父组件
<template>
  <div>
    <Setupcomponent :name='myname' :num='giveChildNum' @changenum='changeNumFun'>
      <template v-slot:header>
        <div>header</div>
      </template>
      <template v-slot:content>
        <div>content</div>
      </template>
    </Setupcomponent>
  </div>
</template>

<script lang="ts">
import { defineComponent, ref } from 'vue'
import Setupcomponent from './setup.vue'

export default defineComponent({
  components: {
    Setupcomponent
  },
  data () {
    return {
      myname: '杨小羊'
    }
  },

  setup () {
    const giveChildNum = ref(1) // ref涉及到响应式API,先知道它可以定义一个响应式数据,下篇文章会简述
    const changeNumFun = () => {
      giveChildNum.value = 2
    }

    return {
      giveChildNum,
      changeNumFun
    }
  }
})
</script>

// 子组件
<template>
  <h3>
    我是子组件
  </h3>

  <!-- 基础值,props、attrs、emit -->
  <div>{{attrsName}}</div>
  <div>{{num}}</div>
  <button @click="handleNumClick">num+1</button>

  <!-- 插槽 slot -->
  <slot name="header"></slot>
  <slot name="content"></slot>
</template>

<script lang="ts">
import { defineComponent, h } from 'vue'

export default defineComponent({
  props: {
    num: Number
  },
  setup (props, { attrs, slots, emit }) {
    console.log(props)
    console.log(attrs)
    console.log(emit)

    // 基础属性
    const attrsName = attrs.name
    const handleNumClick = () => {
      emit('changenum')
    }
    
    // 插槽
    const { header, content, footer } = slots
    h('div', [h('header', header), h('div', content), h('footer', footer)])
    
    return {
      attrsName,
      handleNumClick
    }
  }
})
</script>
复制代码

控制台打印:

image.png

页面展示:

image.png

生命周期钩子

官网对比图,简单明了:

image.png

这里我只简单写两个新增的钩子来展示,想要执行逻辑,就在对应的钩子里写就好:

import { defineComponent, h, inject, onMounted, onRenderTriggered, onRenderTracked, getCurrentInstance } from 'vue'
setup () {
    onMounted(() => console.log('onMounted'));
    onRenderTriggered((event) => console.log('onRenderTriggered,是状态触发,不会跟踪每个值,是给你变化值的信息,并且每个新值和旧值都会明确展示出来', event));
    onRenderTracked((event) => console.log('onRenderTracked,是状态跟踪,setup中return出去的所有值,都会跟踪。只要页面有update的情况就会跟踪,然后生成一个event对象。', event));
}
复制代码

Provide / Inject

// 父组件
<template>
  <div>
    <h2>
      这是我的vue练习手册
    </h2>

    <Setupcomponent />
  </div>
</template>

<script lang="ts">
import { defineComponent, ref, provide } from 'vue'
import Setupcomponent from './setup.vue'

export default defineComponent({
  components: {
    Setupcomponent
  },

  setup () {
    const intro = ref('程序媛')
    const changeintro = () => {
      debugger
      intro.value = '小菜鸡'
    }
    provide('intro', intro)
    provide('changeintro', changeintro)

    return {
      giveChildNum,
      changeNumFun
    }
  }
})
</script>

// 子组件
<template>
  <h3>
    我是子组件
  </h3>
  
  <div>{{injectVal}}</div>
  <button @click="handleInjectClick">inject按钮</button>
</template>

<script lang="ts">
import { defineComponent, inject } from 'vue'

export default defineComponent({
  setup () {
    // inject
    const injectVal = inject('intro')
    const handleInjectClick = inject('changeintro')

    return {
      injectVal,
      handleInjectClick
    }
  }
})
</script>
复制代码

运行过程:

image.png image.png

getCurrentInstance

通过getCurrentInstance方法可以获取vue实例,官网推荐用于高阶用法和库的开发

import { defineComponent, h, inject, onMounted, onRenderTriggered, onRenderTracked, getCurrentInstance } from 'vue'
setup () {
    const getCurrentInstanceVal = getCurrentInstance()
    console.log(getCurrentInstanceVal)
}
复制代码

getCurrentInstanceVal内容为: image.png

ctx中的内容:

image.png

proxy的内容:

image.png

可以看到两者内容很相似,只是后者包装了一层proxy。

语法糖

这个是根据上面的代码示例,写出的简化版子组件
script标签上直接加入setup属性,就可以省去导出部分的代码,setup中定义的属性和方法还是可以直接使用,清晰简洁。

<template>
  <h3>
    我是语法糖形式的子组件
  </h3>

  <div>{{propsVal.num}}</div>
  <button @click="handleNumClick">num+1</button>
</template>

<script lang="ts" setup>
import { defineEmit, defineProps } from 'vue'

const propsVal = defineProps({
  name: String,
  num: Number
})

const emit = defineEmit(['changenum'])
const handleNumClick = () => {
  emit('changenum')
}
</script>
复制代码
文章分类
前端
文章标签