导航


HTML

CSS

JavaScript

浏览器 & 网络

版本管理

框架

构建工具

TypeScript

性能优化

软实力

算法

UI、组件库

Node

业务技能

针对性攻坚

AI


准备工作

升级脚手架

npm i @vue/cli -g

vue create 项目名称

Untitled

composition api (组合API)概念

import { watch, ref, toRef, onMounted, computed } from 'vue';
// 在 setup 中使用 composition api

存在意义

setup 的存在,就是为了能够在其中使用 Composition API

🔥 调用时机

props 初始化完毕之后,beforeCreate 之前被调用

Untitled

Untitled

基本使用

<template>
  <div>{{ count }}</div>
</template>

<script>
export default {
  name: 'App',
  setup() {
    return {
      count: 0
    }
  },
}
</script>

返回值

render function

<script>

import { ref, h } from 'vue';

export default {
  name: 'App',
  setup() {
    const count = ref(0);
    return () => h('h1', [count.value]);
  }
}
</script>

render JSX

<script>
  export default {
    name: 'App',
    setup() {
      return () => <div>123</div>;
    }
  }
</script>

参数

props

父组件 App.vue

<template>
  <div>
    <Test :title="title" />
  </div>
</template>

<script>

import { ref, h } from 'vue';
import Test from '@/components/Test';

export default {
  name: 'App',
  setup() {
    const title = ref('Lance');
    setTimeout(() => {
      title.value = 'Lance233';
    }, 1000);
    return {
      title
    };
  },
  components: {
    Test
  }
}
</script>

子组件 Test.vue

<template>
  <h1>{{ title }}</h1>
</template>

<script>
import { watch, watchEffect } from 'vue';
export default {
  name: 'Test',
  props: {
    title: String
  },
  setup(props) {
    console.log(props); // Proxy { title: 'Lance' }
    watchEffect(() => {
      console.log('title:', props.title); // 初始化Lance和变化后Lance233都能监听到
    });
    
    watch(() => {
      return props.title; // 要监听的值
    }, (newVal) => {
      console.log('new Title:', newVal); // 只会监听变化后的值
    });
  }
}
</script>

Untitled

Untitled

Untitled

使用一个对象绑定多个 prop

如果你想要将一个对象的所有属性都当作 props 传入,你可以使用没有参数的v-bind,即只使用 v-bind 而非 :prop-name。例如,这里有一个 post 对象:

const post = {
  id: 1,
  title: 'My Journey with Vue'
}

以及下面的模板:

<BlogPost v-bind="post" />

而这实际上等价于:

<BlogPost :id="post.id" :title="post.title" />

context

<template>
  <h1>{{ title }}</h1>
</template>

<script>
export default {
  name: 'Test',
  props: {
    title: String
  },
  setup(props, context) {
    console.log(context);
  }
}
</script>

Untitled

attrs

<template>
  <h1>{{ attrs.title }}</h1>
</template>

<script>
export default {
  name: 'Test',
  // props: {
  //   title: String
  // },
  setup(props, context) {
    console.log(context.attrs); // 有 title 了
    // 注意得把 props 中的 title 注释掉,才能出现在 attrs 中
    return {
      attrs: context.attrs
    }
  }
}
</script>

Untitled

<template>
  <h1>{{ title }}</h1>
</template>

<script>
export default {
  name: 'Test',
  setup(props, context) {
    return {
      ...context.attrs // 展开后就没有响应式了
    }
  }
}
</script>

emit

父组件

<template>
  <div>
    <Test :count="count" @plus="plus" />
  </div>
</template>

<script>

import { ref } from 'vue';
import Test from '@/components/Test';

export default {
  name: 'App',
  setup() {
    const count = ref(0);
    const plus = num => count.value += num;
    return { count, plus };
  },
  components: { Test }
}
</script>

子组件

<template>
  <div>{{ count }}</div>
  <button @click="plus">增加</button>
</template>

<script>
export default {
  name: 'Test',
  props: {
    count: Number
  },
  emits: ['plus'],
  setup(props, ctx) {
    const plus = () => ctx.emit('plus', 100);
    return { plus }
  }
}
</script>

setup 中的 ctx 与 getCurrentInstance 中的 ctx 的区别

export default {
  setup(props, ctx) {
    console.log(ctx); // 当前setup执行的时候的一个上下文
    console.log(getCurrentInstance().ctx); // 当前组件实例的执行上下文
  }
}

🔥 setup 中 this 为 undefined