模板引用、组件基础
#### 组件基础
1. 定义和使用简单组件
- 
```vue
<!-- 在App.vue里 -->
<script setup>import HelloWorld from './components/HelloWorld.vue'
</script>
<template><HelloWorld></HelloWorld></template>
<!-- 在HelloWorld.vue里 -->
<template><h2>Hello,Vue3!</h2></template>
<script setup></script>
```
2. 传递属性(Props)
```vue
<!-- 在App.vue里 -->
<script setup>
import HelloWorld from './components/HelloWorld.vue'
</script>
<template>
<HelloWorld title="李焕英"></HelloWorld>
<HelloWorld title="生命一号"></HelloWorld>
<HelloWorld title="希望一号"></HelloWorld>
<HelloWorld title="神州20号"></HelloWorld>
</template>
<!-- 在HelloWorld.vue里 -->
<template>
<h2>Hello,{{title}}!</h2>
</template>
<script setup>
defineProps(['title'])
</script>
```
3. 自定义事件
- 注意:【reactive({num1:0,num2:0})】【v-model="obj.num1"】
```vue
<!-- 在App.vue里 -->
<template>
<ButtonCounter :count="count" @update:count="A"></ButtonCounter>
<p>父组件中的计数值:{{ count }}</p>
</template>
<script setup>
import ButtonCounter from './components/ButtonCounter.vue'
import {ref} from 'vue'
let count = ref(0)
const A = (newA)=>{
count.value = newA
}
</script>
<!-- ButtonCounter.vue里 -->
<template>
<input type="button" :value="'点击次数:'+count" @click="btn">
</template>
<script setup>
import { defineEmits,defineProps } from 'vue';
const props = defineProps(['count'])
const emit = defineEmits(['update:count'])
const btn = ()=>{
emit('update:count',props.count + 1)
}
</script>
```
### 笔记
#### 组件基础
1. 单文件组件 :一般用于构建步骤,将组件定义在一个单独的 .vue 文件中
- 在 `ButtonCounter.vue` 文件中:
```vue
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
<template>
<button @click="count++">{{ count }}</button>
</template>
```
2. JavaScript 对象定义组件:不使用构建步骤时,组件以包含 Vue 特定选项的 JavaScript 对象来定义
```vue
<template>
<button @click="count++">{{ count }}</button>
</template>
<script>
import { ref } from 'vue'
export default {
setup() {
const count = ref(0)
return { count }
}
}
</script>
```
#### 传递 props
1. 概念:Props 是一种特别的 attributes,用于向组件中传递数据。例如,构建博客时,向博客文章组件传递标题和内容等数据就会使用到 props。
- 在组件中需要先声明 props。使用 `<script setup>` 时,可通过 `defineProps` 宏来声明
- 在 `ButtonCounter.vue` 文件中:
```vue
<script setup>
defineProps(['title'])
</script>
<template>
<h4>{{ title }}</h4>
</template>
```
- 若未使用 `<script setup>`,则需以 `props` 选项的方式声明,`props` 对象会作为 `setup()` 函数的第一个参数被传入。
```js
export default {
props: ['title'],
setup(props) {
console.log(props.title)
}
}
```
2. 传递 props** :在使用组件时,以自定义 attribute 的形式传递数据给组件。`<BlogPost title="My journey with Vue" />`
#### 监听事件
1. 场景:有时子组件需要与父组件进行交互。在博客文章组件中实现点击按钮放大文字的功能
- 在子组件中添加按钮,并通过 `$emit` 方法抛出事件。
- 在 `BlogPost.vue` 文件中:
```vue
<template>
<div class="blog-post">
<h4>{{ title }}</h4>
<button @click="$emit('enlarge-text')">Enlarge text</button>
</div>
</template>
- 父组件监听该事件并做出响应
<BlogPost @enlarge-text="postFontSize += 0.1"/>
```
2. 事件声明:可通过 `defineEmits` 宏来声明需要抛出的事件,还可以对事件的参数进行验证。
- 在 `BlogPost.vue` 文件中
```vue
<script setup>
defineProps(['title'])
defineEmits(['enlarge-text'])
</script>
```
3. 若未使用 `<script setup>`,可通过 `emits` 选项定义组件会抛出的事件,并从 `setup()` 函数的第二个参数,即 `setup` 上下文对象上访问到 `emit` 函数
```js
export default {
emits: ['enlarge-text'],
setup(props, ctx) {
ctx.emit('enlarge-text')
}
}
```
#### 模板引用
1. 用途:在某些情况下需要直接访问底层 DOM 元素,可使用特殊的 `ref attribute`。
- 获取引用:`useTemplateRef()`
```vue
<script setup>
import { useTemplateRef, onMounted } from 'vue'
const input = useTemplateRef('my-input')
onMounted(() => {
input.value.focus()
})
</script>
<template>
<input ref="my-input" />
</template>`
```
### 示例代码
- ButtonCount.vue
```vue
<template>
{{ title }}-{{ author }}
</template>
<script>
export default {
props: ['title', 'author'],
setup(props) {
console.log(props)
return { }
}
}
</script>
```
或使用 `<script setup>`:
```vue
<script setup>
let props = defineProps(['title', 'author'])
console.log(props)
</script>
<template>
{{ title }}-{{ author }}
</template>
```
2. App.vue
```vue
<script setup>
import { ref } from 'vue'
import ButtonCount from './components/ButtonCount.vue'
function uu() {
console.log("我是一个自定义的事件,名叫uu")
}
let txt = ref("九九艳阳天")
</script>
<template>
<input type="text" ref="txtUsername" @keypress.enter="uu">
<ButtonCount :title="txt"></ButtonCount>
</template>
```