Vue3核心语法
OptionsAPI与CompositionAPI
Vue2
的API
设计是Options
(配置)风格的。Vue3
的API
设计是Composition
(组合)风格的。
Options APl的弊端
Options
类型的API
,数据、方法、计算属性等,是分散在:data
、methods
、computed
中的,若想新
增或者修改一个需求,就需要分别修改:data
、methods
、computed
,不便于维护和复用。
Composition API的优势
可以用函数的方式,更加优雅的组织代码,让相关功能的代码更加有序的组织在一起。
Vue3.0的响应式
- 实现原理:
- 通过Proxy(代理):拦截对象中任意属性的变化,包括:属性值的读写、属性的添加、属性的删除等。
- 通过Reflect(反射):对被代理对象的属性进行操作。
- MDN文档中描述的Proxy与Reflect:
Proxy:Proxy的MDN文档
Reflect:Reflect的MDN文档
new Proxy(data,{
//拦截读取属性值
get(target,prop){
return Reflect.get(target,prop)
},
//拦截设置属性值或添加新属性
set (target,prop,value){
return Reflect.set(target,prop,value)
},
//拦截删除属性
deleteProperty (target,prop){
return Reflect.deleteProperty(target,prop)
}
})
proxy.name 'tom'
拉开序幕的setup
setup概述
setup
是Vue3
中一个新的配置项,值是一个函数,它是Composition API
“表演的舞台”,组件中所用到的:数
据、方法、计算属性、监视等等,均配置在setup
中。
特点如下:
setup
函数返回的对像中的内容,可直接在模板中使用。setup
中访问this
是undefined
。setup
函数会在beforeCreate
之前调用,它是"领先"所有钩子执行的。
- setup函数的两种返回值:
- 若返回一个对象,则对象中的属性、方法,在模板中均可以直接使用。(重点关注!)
- 若返回一个渲染函数:则可以自定义渲染内容。(了解)
- 注意点:
- 尽量不要与Vue2.x配置混用
- Vue2.x配置(
data
、methods
、computed
)中可以访问到setup
中的属性、方法 - 但在setup中不能访问到Vue2.x配置(
data
、methods
、computed
)。 - 如果有重名,setup优先。
- Vue2.x配置(
setup
不能是一个async
函数,因为返回值不再是return
的对象,而是promise
,模板看不到return
对象中的属性。
- 尽量不要与Vue2.x配置混用
- setup的两个注意点
- setup执行的时机
- 在peforeCreate之前执行一次,this是
undefined
。
- 在peforeCreate之前执行一次,this是
- setup的参数
- props:值为对象包含:组件外部传递过来且组件内部声明接收了的属性。
- context:上下文对象
- attrs:值为对象,包含:组件外部传递过来,但没有在
props
配置中声明的属性,相当于this.$attrs
。 - slots:收到的插槽内容,相当于
this.$slots
。 - emit:分发自定义事件的函数,相当于
this.$emit
。
- attrs:值为对象,包含:组件外部传递过来,但没有在
ref创建:基本类型的响应式数据
- 作用:定义响应式变量。
- 语法:
let xxx=ref(初始值)
。 - 返回值:一个
RefImpl
的实例对象,简称ref对象
或ref
,ref
对象的value
属性是响应式的, - 注意点:
JS
中操作数据需要:xxx.value
,但模板中不需要.value
,直接使用即可。- 对于
let name=ref('张三')
来说,name
不是响应式的,name.value
是响应式的。
<template>
<div class="person">
<h2>姓名:{{ name }}</h2>
<h2>年龄:{{ age }}</h2>
<button @click="changeName">修改名字</button>
<button @click="changeAge">修改年龄</button>
<button @click="showSex">查看性别</button>
</div>
</template>
<script lang="ts">
export default {
name:'PersonComponent',
}
</script>
<script lang="ts" setup name='PersonComponent'>
import { ref } from 'vue';
const name = ref("张三")
const age = ref(18)
const sex = "男"
// 方法
function changeName() {
name.value = "王五"
console.log(name)
}
function changeAge() {
age.value+=1
}
function showSex() {
alert(sex)
}
</script>
<style scoped>
.person{
background-color: pink;
box-shadow: 0 0 10px ;
border-radius: 10px;
padding: 20px;
}
button{
margin-right: 10px;
}
</style>
reactive创建:对象类型的响应数据
<template>
<div class="person">
<h2>一辆{{ car.brand }}车,价值{{ car.price }}万</h2>
<button @click="changePrice">修改汽车的价格</button>
<br>
<h2>游戏列表:
<ul>
<li v-for="g in games" :key="g.id">{{ g.name }}</li>
</ul>
</h2>
<button @click="changeFirstGameName">修改游戏</button>
</div>
</template>
<script lang="ts" setup name="Person">
import { defineComponent, reactive } from 'vue';
const car = reactive({
brand: 'Benz',
price: 100
});
const games = reactive([
{ id: "1", name: "王者荣耀" },
{ id: "2", name: "英雄联盟" },
{ id: "3", name: "和平精英" }
])
console.log(car)
function changePrice() {
car.price += 10;
}
function changeFirstGameName() {
games[0].name = "羊了个羊"
}
defineComponent({
name: 'PersonInfo'
})
</script>
<style scoped>
.person {
background-color: pink;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
button {
margin-right: 10px;
}
</style>
ref创建:对象类型的响应数据
<template>
<div class="person">
<h2>一辆{{ car.brand }}车,价值{{ car.price }}万</h2>
<button @click="changePrice">修改汽车的价格</button>
<br>
<h2>游戏列表:
<ul>
<li v-for="g in games" :key="g.id">{{ g.name }}</li>
</ul>
</h2>
<button @click="changeFirstGameName">修改游戏</button>
</div>
</template>
<script lang="ts" setup name="Person">
import { defineComponent, ref } from 'vue';
const car = ref({
brand: 'Benz',
price: 100
});
const games = ref([
{ id: "1", name: "王者荣耀" },
{ id: "2", name: "英雄联盟" },
{ id: "3", name: "和平精英" }
])
console.log(car)
function changePrice() {
car.value.price += 10;
}
function changeFirstGameName() {
games.value[0].name = "羊了个羊"
}
defineComponent({
name: 'PersonInfo'
})
</script>
<style scoped>
.person {
background-color: pink;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
button {
margin-right: 10px;
}
</style>
ref对比reactive
- 宏观角度看:
ref
用来定义:基本类型数据、对象类型数据:reactive
用来定义:对象类型数据。
- 区别:
ref
创建的变量必须使用.value
(可以使用volar
插件自动添加.value
)。reactive
重新分配一个新对象,会失去响应式(可以使用Object.assign
去整体替换)。
- 使用原则:
- 若需要一个基本类型的响应式数据,必须使用
ref
。 - 若需要一个响应式对象,层级不深,
ref
、reactive
都可以。 - 若需要一个响应式对象,且层级较深,推荐使用
reactive
。
- 若需要一个基本类型的响应式数据,必须使用
<template>
<div class="person">
<h2>一辆{{ car.brand }}车,价值{{ car.price }}万</h2>
<button @click="changePrice">修改汽车的价格</button>
<button @click="changeBrand">修改汽车的品牌</button>
<button @click="changeCar">修改汽车</button>
<hr>
<h2>当前求和为:{{ sum }}</h2>
<button @click="changeSum">sum+1</button>
</div>
</template>
<script lang="ts" setup name="Person">
import { defineComponent, ref } from 'vue';
// const car = reactive({
// brand: 'Benz',
// price: 100
// });
const car = ref({
brand: 'Benz',
price: 100
});
const sum = ref(0);
// function changePrice() {
// car.price += 10;
// }
// function changeBrand() {
// car.brand = 'hongqi';
// }
function changePrice() {
car.value.price += 10;
}
function changeBrand() {
car.value.brand = 'hongqi';
}
function changeCar() {
// Object.assign(car, {
// brand: 'Aodi',
// price: 10
// });
car.value = {
brand: 'Aodi',
price: 10
};
}
function changeSum() {
sum.value += 1;
}
defineComponent({
name: 'PersonInfo'
})
</script>
<style scoped>
.person {
background-color: pink;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
button {
margin-right: 10px;
}
</style>
toRefs与toRef
- 作用:将一个响应式对象中的每一个属性,转换为
ref
对象。 - 备注:
toRefs
与toRef
功能一致,但toRefs
可以批量转换 - 语法如下:
<template>
<div class="person">
<h2>name:{{ name }}</h2>
<h2>age:{{ age }}</h2>
<button @click="changeName">修改名字</button>
<button @click="changeAge">修改年龄</button>
</div>
</template>
<script lang="ts" setup name="Person">
import { defineComponent, reactive, toRefs } from 'vue';
const person = reactive({
name: '张三',
age: 18,
})
defineComponent({
name: 'PersonComponent',
})
const {name,age} = toRefs(person);
function changeName() {
name.value += '三';
}
function changeAge() {
age.value += 1;
}
</script>
<style scoped>
.person {
background-color: pink;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
button {
margin-right: 10px;
}
</style>
计算属性(computed)
<template>
<div class="person">
姓:<input type="text" v-model="firstname"><br>
名:<input type="text" v-model="lastname"><br>
<button @click="changeFullName()">将全名改为li-si</button>
全名:<span>{{ fullname}}</span>
</div>
</template>
<script lang="ts" setup>
import { computed, ref } from 'vue';
const firstname = ref('张');
const lastname = ref('三');
// 这样定义的fullname是一个计算属性,且是只读的
// const fullname=computed(() => {
// return firstname.value.slice(0,1).toUpperCase() + firstname.value.slice(1)+'-'+ lastname.value;
// });
const fullname = computed( {
get(){
return firstname.value.slice(0,1).toUpperCase() + firstname.value.slice(1)+'-'+ lastname.value;
},
set(val){
const [str1,str2]=val.split('-');
firstname.value=str1
lastname.value=str2
}
});
function changeFullName() {
fullname.value='李-四'
}
</script>
<style scoped>
.person {
background-color: pink;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
button {
margin-right: 10px;
}
</style>
watch
- 作用:监视数据的变化(和
Vue2
中的watch
作用一致) - 特点:
Vue3
中的watch
只能监视以下四种数据:ref
定义的数据。reactive
定义的数据。- 函数返回一个值(
getter
函数)。 - 一个包含上述内容的数组。
我们在Vue3
中使用watch
的时候,通常会遇到以下几种情况:
*情况一
监视ref
定义的【基本类型】数据:直接写数据名即可,监视的是其value
值的改变。
<template>
<div class="person">
<h1>情况一:监视【ref】定义的【基本类型】数据</h1>
<h2>当前求和为:{{ sum }}</h2>
<button @click="changeSum">点击sum+1</button>
</div>
</template>
<script lang="ts" setup>
import { ref, watch } from 'vue';
const sum=ref(0)
function changeSum() {
sum.value+=1;
}
// 监视
watch(sum,(newValue,oldValue)=>{
console.log('sum被修改了',newValue,oldValue)
})
</script>
<style scoped>
.person {
background-color: pink;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
button {
margin-right: 10px;
}
</style>
*情况二
监视ref
定义的【对像类型】数据:直接写数据名,监视的是对像的【地址值】,若想监视对像内部的数据,要
手动开启深度监视。
注意:
- 若修改的是
ref
定义的对象中的属性,newValue
和oldValue
都是新值,因为它们是同一个对象。 - 若修改整个
ref
定义的对象,newValue
是新值,oldValue
是旧值,因为不是同一个对象了。
<template>
<div class="person">
<h1>情况二:监视【ref】定义的【对象类型】数据</h1>
<h2>姓名:{{ person.name }}</h2>
<h2>年龄:{{ person.age }}</h2>
<button @click="changeName">修改名字</button>
<button @click="changeAge">修改年龄</button>
<button @click="changePerson">修改人</button>
</div>
</template>
<script lang="ts" setup name="Person">
import { ref, watch } from 'vue';
const person = ref({
name:'张三',
age:18
})
function changeName(){
person.value.name += '五'
}
function changeAge(){
person.value.age += 1
}
function changePerson(){
person.value = {
name:'李四',
age:90
}
}
// 监视,情况一:监视【ref】定义的【对象类型】数据,监视的是对象的地址值,若想监视对象内容属性的变化,需要手动开启深度监视
// watch(person,(newValue,oldValue)=>{
// console.log('person变化了',newValue,oldValue)
// })
// 监视`ref`定义的【对像类型】数据:直接写数据名,监视的是对像的【地址值】,若想监视对像内部的数据,要手动开启深度监视
// watch的第一个参数是监视的数据
// watch的第二个参数是监视的回调
// watch的第二个参数是配置对象()
watch(person,(newValue,oldValue)=>{
console.log('person变化了',newValue,oldValue)
},{deep:true,immediate:true})
</script>
<style scoped>
.person {
background-color: pink;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
button {
margin-right: 10px;
}
</style>
*情况三
监视reactive
定义的【对象类型】数据,且默认开启了深度监视。
<template>
<div class="person">
<h1>情况三:监视【ref】定义的【对象类型】数据</h1>
<h2>姓名:{{ person.name }}</h2>
<h2>年龄:{{ person.age }}</h2>
<button @click="changeName">修改名字</button>
<button @click="changeAge">修改年龄</button>
<button @click="changePerson">修改人</button>
</div>
</template>
<script lang="ts" setup name="Person">
import { reactive, watch } from 'vue';
const person = reactive({
name:'张三',
age:18
})
function changeName(){
person.name += '五'
}
function changeAge(){
person.age += 1
}
function changePerson(){
Object.assign(person,{
name:'王五',
age:19
})
}
//监视,情况三:监视`reactive`定义的【对象类型】数据,且默认开启了深度监视。
watch(person,(newValue,oldValue)=>{
console.log('person被修改了',newValue,oldValue)
})
</script>
<style scoped>
.person {
background-color: pink;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
button {
margin-right: 10px;
}
</style>
*情况四
监视ref
或reactive
定义的【对象类型】数据中的某个属性,注意点如下:
- 若该属性值不是【对象类型】,需要写成函数形式。
- 若该属性值是依然是【对象类型】,可直接编,也可写成函数,不过建议写成函数。
结论:监视的要是对象里的属性,那么最好写函数式,注意点:若是对象监视的是地址值,需要关注对象内部,
需要手动开启深度监视。
<template>
<div class="person">
<h2>姓名:{{ person.name }}</h2>
<h2>年龄:{{ person.age }}</h2>
<h2>汽车:{{ person.car.c1 }}、{{ person.car.c2 }}</h2>
<button @click="changeName">修改名字</button>
<button @click="changeAge">修改年龄</button>
<button @click="changeFirstCar">修改第一台车</button>
<button @click="changeSecondCar">修改第二台车</button>
<button @click="changeCar">修改车</button>
</div>
</template>
<script lang="ts" setup name="Person">
import { reactive, watch } from 'vue';
const person = reactive({
name: '张三',
age: 18,
car:{
c1:"Benz",
c2:"BMW"
}
});
function changeName() {
person.name += '三';
}
function changeAge() {
person.age += 1;
}
function changeFirstCar() {
person.car.c1 ='hongqi'
}
function changeSecondCar() {
person.car.c2 ='Aodi'
}
function changeCar() {
person.car.c1 ='hongqi';
person.car.c2 ='Aodi';
}
watch(()=>{return person.name},(newValue, oldValue) => {
console.log('person.name被修改了', newValue, oldValue);
})
</script>
<style scoped>
.person {
background-color: pink;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
button {
margin-right: 10px;
}
</style>
*情况五
情况五:监视多个数据
<template>
<div class="person">
<h1>情况五:监视多个数据</h1>
<h2>姓名:{{ person.name }}</h2>
<h2>年龄:{{ person.age }}</h2>
<h2>汽车:{{ person.car.c1 }}、{{ person.car.c2 }}</h2>
<button @click="changeName">修改名字</button>
<button @click="changeAge">修改年龄</button>
<button @click="changeFirstCar">修改第一台车</button>
<button @click="changeSecondCar">修改第二台车</button>
<button @click="changeCar">修改车</button>
</div>
</template>
<script lang="ts" setup name="Person">
import { reactive, watch } from 'vue';
const person = reactive({
name: '张三',
age: 18,
car:{
c1:"Benz",
c2:"BMW"
}
});
function changeName() {
person.name += '三';
}
function changeAge() {
person.age += 1;
}
function changeFirstCar() {
person.car.c1 ='hongqi'
}
function changeSecondCar() {
person.car.c2 ='Aodi'
}
function changeCar() {
person.car.c1 ='hongqi';
person.car.c2 ='Aodi';
}
// 监视,情况五:监视上述多个数据
watch([()=>person.name,()=>person.car.c1] ,(newValue, oldValue) => {
console.log("person.car被修改了", newValue, oldValue);
},{deep:true})
</script>
<style scoped>
.person {
background-color: pink;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
button {
margin-right: 10px;
}
</style>
watchEffect
- 官网:立即运行一个函数,同时响应式地追踪其依赖,并在依赖更改时重新执行该函数。
watch
对比watchEffect
- 都能监听响应式数据的变化,不同的是监听数据变化的方式不同
watch
:要明确指出监视的数据watchEffect
:不用明确指出监视的数据(函数中用到哪些属性,那就监视哪些属性)。
示例代码:
<template>
<div class="person">
<h2>需求:当水温达到60度,或水位达到80cm,给服务器发送请求</h2>
<h2>当前水温为:{{ temp }}°C</h2>
<h2>当前水位为:{{ height }}cm</h2>
<button @click="changeTemp">点我temp+10</button>
<button @click="changeHeight">点我height+10</button>
</div>
</template>
<script lang="ts" setup name="Person">
import { ref, watchEffect } from 'vue';
const temp = ref(10);
const height = ref(0);
function changeTemp() {
temp.value+=10
}
function changeHeight() {
height.value+=10
}
// 监视 watch实现
/*watch([temp,height],(value)=>{
const [newTemp,newHeight]=value
console.log(newTemp,newHeight)
if(newTemp>=60||newHeight>=80){
console.log("预警!")
}
})*/
// 监视 watchEffect实现
watchEffect(()=>{
if(temp.value>=60||height.value>=80){
console.log("预警!")
}
})
</script>
<style scoped>
.person {
background-color: pink;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
button {
margin-right: 10px;
}
</style>
【标签的ref属性】
作用:用于注册模板引用。
- 用在普通
DOM
标签上,获取的是DOM
节点。 - 用在组件标签上,获取的是组件实例对象。
用在普通DOM
标签上:
<template>
<div class="person">
<h1>中国</h1>
<h2 ref="title2">河南</h2>
<h3>前端</h3>
<button @click="showLog">点我输出h2</button>
</div>
</template>
<script lang="ts" setup name="Person">
import { defineExpose, ref } from 'vue';
//创建一个title2,用于存储ref标记的内容
const title2 = ref()
const a = ref(1)
const b = ref(2)
const c = ref(3)
function showLog() {
console.log(title2.value)
}
defineExpose({a,b,c})
</script>
<style scoped>
.person {
background-color: pink;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
button {
margin-right: 10px;
}
</style>
回顾TS中的接口泛型自定义类型
<template>
<div class="person">
<h3>{{ person }}</h3>
<h3>{{ personList }}</h3>
</div>
</template>
<script lang="ts" setup name="Person">
import { type PersonInter, type Persons } from '@/types';
const person:PersonInter={id:'1',name:'张三',age:18}
const personList:Persons=[
{id:'1',name:'张三',age:18},
{id:'2',name:'李四',age:20},
{id:'3',name:'王五',age:30}
]
</script>
<style scoped>
.person {
background-color: pink;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
button {
margin-right: 10px;
}
</style>
props的使用
//Person.vue
<template>
<div class="person">
<ul>
<li v-for="item in list" :key="item.id">
{{ item.name }}--{{ item.age }}
</li>
</ul>
</div>
</template>
<script lang="ts" setup name="Person">
import { withDefaults } from 'vue';
import {type Persons } from '../types/index';
// 只接收list
// defineProps(['list'])
// 接收list+限制类型
// defineProps<{list:Persons}>()
//接收list+限制类型+限制必要性+指定默认值
// withDefaults(defineProps<{list?:Persons}>(),{
// list:()=>[{id:'1',name:'haha',age:18}]
// })
// 接收a,同时将props保存起来
// const x=defineProps(['a'])
// console.log(x)
</script>
<style scoped>
.person {
background-color: pink;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
button {
margin-right: 10px;
}
</style>
//App.vue
<template>
<Person a="haha" :list="personList"/>
</template>
<script lang="ts" setup name="App">
import Person from './components/Person.vue';
import {reactive} from 'vue';
import {type Persons} from "@/types";
const personList=reactive<Persons>([
{
id:'1',
name:'李四',
age:18,
x:10
},
{
id:'2',
name:'王五',
age:20,
},
{
id:'3',
name:'张三',
age:35,
}
])
</script>
生命周期
人的生命周期:
【时刻】 | 【要做的事】 |
---|---|
出生 | 哭 |
经历 | 哭、笑 |
死亡 | 遗嘱 |
组件的生命周期:
【时刻】 | 【调用特定的函数】 |
---|---|
创建 | created |
挂载 | mounted |
更新 | |
销毁 |
- 概念:
Vue
组件实例在创建时要经历一系列的初始化步骤,在此过程中Vue
会在合适的时机,调用特定的函
数,从而让开发者有机会在特定阶段运行自己的代码,这些特定的函数统称为:生命周期钩子 - 规律:
生命周期整体分为四个阶段,分别是:创建、挂载、更新、销毁,每个阶段都有两个钩子,一前一后。 Vue2
的生命周期- 创建阶段:
beforeCreate
、created
- 挂载阶段:
beforeMount
、mounted
- 更新阶段:
beforeUpdate
、updated
- 销毁阶段:
beforeDestroy
、destroyed
- 创建阶段:
Vue3
的生命周期- 创建阶段:
setup
- 挂载阶段:
onBeforeMount
、onMounted
- 更新阶段:
onBeforeUpdate
、onUpdated
- 销毁阶段:
onBeforeUnmount
、onUnmounted
- 创建阶段:
- 常用的钩子:
onMounted
(挂载完毕)、onUpdated
(更新完毕)、onBeforeUnmount
(卸载之前) - 示例代码:
<template>
<div class="person">
<h2>当前求和为:{{ sum }}</h2>
<button @click="add">点我sum+1</button>
</div>
</template>
<script lang="ts" setup name="Person">
import { onBeforeMount, onBeforeUnmount, onBeforeUpdate, onMounted, onUnmounted, onUpdated, ref } from 'vue'
// 数据
const sum=ref(0)
// 方法
function add() {
sum.value+=1
}
// 创建
console.log("子--创建成功")
// 挂载
onBeforeMount(()=>{
console.log("子--挂载成功")
})
// 挂载完毕
onMounted(()=>{
console.log("子--挂载完毕")
})
// 更新前
onBeforeUpdate(()=>{
console.log("子--更新前")
})
// 更新后
onUpdated(()=>{
console.log("子--更新后")
})
// 销毁前
onBeforeUnmount(()=>{
console.log("子--销毁前")
})
// 销毁后
onUnmounted(()=>{
console.log("子--销毁后")
})
</script>
<style scoped>
.person {
background-color: pink;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
button {
margin-right: 10px;
}
</style>
自定义hooks
import { computed, onMounted, ref } from 'vue'
export default function () {
// 数据
const sum = ref(0)
const bigSum=computed(()=>{
return sum.value*10
})
// 方法
function add() {
sum.value += 1
}
// 钩子
onMounted(() => {
add()
})
// 向外部提供东西
return {
sum,
add,
bigSum
}
}
import axios from 'axios'
import { reactive,onMounted } from 'vue'
export default function (){
// 数据
const dogList = reactive([
'https://images.dog.ceo/breeds/pembroke/n02113023_4373.jpg'
])
// 方法
async function addDog() {
try {
const result = await axios.get('https://dog.ceo/api/breeds/image/random')
if (result.data && result.data.message) {
dogList.push(result.data.message)
}
} catch (error) {
console.error('获取狗狗图片失败:', error)
}
}
// 钩子
onMounted(() => {
addDog()
})
//向外部提供东西
return {dogList, addDog}
}
import { computed, onMounted, ref } from 'vue'
export default function () {
// 数据
const sum = ref(0)
const bigSum=computed(()=>{
return sum.value*10
})
// 方法
function add() {
sum.value += 1
}
// 钩子
onMounted(() => {
add()
})
// 向外部提供东西
return {
sum,
add,
bigSum
}
}