优势
组合式API
同功能相关的内容进行集合式管理
使用creat-vue 创建项目
执行npm i下载对应的配置文件
项目目录
setup 允许直接在script中编写组合式API
组合式api
setup
执行时机
1.先于beforeCreat函数
2.setup 函数中获取不到this
3.数据与函数需要在setup最后return才能在模板中应用
js
<script>
export default{
setup(){
console.log("setup函数" + this);
//数据
const data="hello vue3"
//函数
const logMessage=()=>{
console.log(data);
}
//使用数据与函数需要return
return{
data,
logMessage
}
},
beforeCreate(){
console.log("beforecreate函数")
}
}
</script>
4.每次都需要return麻烦
---使用语法糖
setup语法糖
js
<script setup>
//数据
const data="hello vue3"
//函数
const logMessage=()=>{
console.log(data);
}
</script>
组合式API reactive 与 ref函数
用函数调用的方式生成响应式数据
reactive()
1.作用
接受对象类型的参数传入,并返回一个响应式的对象
2.核心步骤
接收对象类型数据,返回响应式对象
js
<script setup>
//导入
import { reactive } from 'vue';
//执行函数 传入参数 变量接收
const state=reactive(对象类型数据)
</script>
js
<script setup>
//导入
import { reactive } from 'vue';
//执行函数 传入参数 变量接收
const state=reactive({
count:100
})
const res=()=>{
state.count++
}
</script>
<template>
<div>学习vue3</div>
<div>{{ state.count }}
</div>
<button @click="res">加一</button>
</template>
ref()
1.作用
接收简单类型或对象类型的数据 传入
返回一个响应式的对象
2.本质
在原有数据的基础上外层包了一层对象,包成了复杂数据类型
3.底层
包成复杂类型之后,再借用reactive实现响应式
4.注意
脚本中访问数据: .value
template中 .value不需要加(帮我们扒了一层)
5.操作
js
<script setup>
//导入
import { ref } from 'vue';
//执行函数 传入参数 变量接收
const count =ref(简单数据类型或者复杂类型数据)
</script>
computed()
js
<script setup>
//1.导入computed函数
import { computed } from 'vue';
//2.执行函数在回调参数中 return 基于响应式数据做计算的值,用于变量的接收
const computedState = computed(()=>{
return 基于响应式数据做计算之后的值
})
</script>
js
<script setup>
import { computed ,ref} from 'vue';
//声明数据
const list = ref([1,2,3,4,5,6,7])
console.log(list);
console.log(list.value)
//基于list 派生计算属性,从list中过滤出>2
const computedState = computed(()=>{
return list.value.filter(item => item > 2 )
})
//定义一个修改数据的方法
const addFn = ()=>{
list.value.push(666)
}
</script>
<template>
<div>学习vue3</div>
<div>原始数据: {{ list }}</div>
<div>计算后的数据:{{ computedState }}</div>
<button @click="addFn">加666</button>
</template>
watch
监听一个或多个数据的变换,数据变化时执行回调函数
1.导入watch函数
2.执行watch函数(传入ref响应式数据,和回调函数)
深度监听
js
<script setup>
//1.导入watch
import { ref,watch } from 'vue';
//2.调用watch 监听变化
const count = ref(0)
const name=ref('zs')
const chageCount=()=>{
count.value++;
}
const changeName=()=>{
name.value='ls'
}
//1 监听单个数据变化
// 3.immediate 立即执行(一进页面就触发)
watch(count,(newvalue,oldValue)=>{
console.log(`count 发生变化,老值为${oldValue}新值为${newvalue}`);
},
{
immediate:true
})
//2.监听多个数据变化
watch(
[count,name],
([newCount,newName],[oldCount,oldName])=>{
console.log('count或name的值变化了',[newCount,newName],[oldCount,oldName]);
}
)
// 4.deep 深度监视(默认watch进行浅层监视
// const ref1=ref(简单数据类型) 可以直接监视简单数据的变化, 监视不到复杂数据类型内部(只有修改复杂数据类型的地址的时候,才能监听到)
// const ref2=ref(复杂数据类型)
const userInfo=ref({
name:'ww',
age:18
})
const setUserInfo=()=>{
userInfo.value.age++
}
watch(userInfo,(newvalue)=>{
console.log(newvalue);
},{
deep:true
})
</script>
<template>
<div>{{ count }}</div>
<button @click="chageCount">改数字</button>
<div>{{ name }}</div>
<button @click="changeName">改名字</button>
_______________
<div>{{ userInfo }}</div>
<button @click="setUserInfo">改复杂类型中的名字</button>
</template>
精准侦听对象的某个属性
在不开启deep的前提下侦听age的变化,只有当age变化的时候才执行回调
js
const userInfo=ref({
name:'ww',
age:18
})
js
//5.对对象中的属性进行监视
watch(()=>userInfo.value.age,(newValue,oldValue)=>{
console.log(newValue,oldValue)
})
生命周期函数
js
<script setup>
//1.beforeCreated 和 created 的相关代码
// 一律放在setup中执行
import { onMounted } from 'vue';
// beforeCreated 和 created
const getList=()=>{
setTimeout(()=>{
console.log("发送请求,获取数据");
},2000)
}
//模拟一进入页面发送请求
getList()
//2.如果有代码需要在mounted生命周期函数中执行
onMounted(()=>{
console.log("Mounted生命周期函数 - 逻辑1");
})
//2.写成函数的调用方式,可以调用多次,不会冲突,而是按照顺序依次执行
onMounted(()=>{
console.log("Mounted生命周期函数 - 逻辑2");
})
</script>
父子通信
父传子
defineProps的原理
编译阶段的标识,遇到后会进行编译转化
1.给子组件以添加属性的方式传值
2.在子组件中,通过props接收
js
父组件
<script setup>
import { ref } from 'vue';
const money=ref(100)
const changeMoney=()=>{
money.value+=100
}
//1.局部导入子组件
import SonCom from '@/components/son-com.vue'
</script>
<template>
<!-- 2.导入后直接使用 -->
<div>
<div>父组件-- {{ money }}</div>
<button @click="changeMoney">挣钱</button>
<!-- 给子组件以添加属性的方式传值 -->
<!-- 1.传递固定值:car="宝马车" -->
<!-- 2.动态传递值: :money="money"-->
<SonCom car="宝马车" :money="money"></SonCom>
</div>
</template>
js
<script setup>
子组件
//Attention : 由于写了setup,无法直接配置props选项,此处借用'编译器宏'函数来接收子组件传递的数据
const props=defineProps({
car:String,
money:Number
})
console.log(props.car,props.money);
</script>
<template>
<!-- 对于props传递过来的数据,模板中可以直接使用 -->
<div class="son">我是子组件--{{ car }} {{ money }}</div>
</template>
<style scoped>
.son{
border: 1px solid #000;
padding: 30px;
}
</style>
子传父
1.子组件内部通过emit方法触发事件
2.父组件中给子组件标签通过@绑定事件
js
<script setup>
子组件
const props=defineProps({
car:String,
money:Number
})
console.log(props.car,props.money);
const emit=defineEmits([
'changeMoney'
])
const buy=()=>{
//1.子组件中通过emit触发事件(通过编译器宏定义)
emit('changeMoney',5)
}
</script>
<template>
<div class="son">我是子组件--{{ car }} {{ money }}</div>
<button @click="buy">花钱</button>
</template>
<style scoped>
.son{
border: 1px solid #000;
padding: 30px;
}
</style>
js
<script setup>
父组件
import { ref } from 'vue';
const money=ref(100)
const changeMoney=()=>{
money.value+=100
}
import SonCom from '@/components/son-com.vue'
const changeFn=(newMoney)=>{
money.value=newMoney
}
</script>
<template>
<div>
<div>父组件-- {{ money }}</div>
<button @click="changeMoney">挣钱</button>
<!-- 2.给子组件添加属性的方式,父组件接收 -->
<SonCom
@changeMoney="changeFn"
car="宝马车"
:money="money"></SonCom>
</div>
</template>
模板引用 与 defineExporse宏函数
模板引用,可以获取dom,也可以获取组件
// 1.通过ref函数生成ref对象
// 2.通过ref标识,进行绑定
// 3.通过ref对象,.value即可访问到绑定的元素(必须渲染完成后才能拿到,使用生命周期钩子)
js
<script setup>
import { onMounted, ref } from 'vue';
const inp=ref(null)
console.log(inp.value);
//通过生命周期钩子onMounted
onMounted(()=>{
console.log(inp.value);
// inp.value.focus()//一进页面就聚焦
})
const changFn=()=>{
inp.value.focus()
}
</script>
<template>
<div>
<input ref="inp" type="text">
<button @click="changFn">点击让输入框聚焦</button>
</div>
</template>
defineExporse()
默认情况在< script setup> 语法糖下,组件内部的属性与方法时不开放给父组件访问的,通过defineExporse编译宏指定哪些属性与方法允许访问
js
//APP.vue
<script setup>
import TestCom from '@/components/test-com.vue'
import { onMounted, ref } from 'vue';
//----------------------------------------------------------------
const inp=ref(null)
console.log(inp.value);
//通过生命周期钩子onMounted
onMounted(()=>{
console.log(inp.value);
// inp.value.focus()//一进页面就聚焦
})
const changFn=()=>{
inp.value.focus()
//当点击按钮的时候,肯定已经渲染完毕
}
//---------------------------------------------------------------
const testRef=ref(null)
const clickFn=()=>{
console.log(testRef.value);
console.log(testRef.value.count);
console.log(testRef.value.sayHi);
}
</script>
<template>
<div>
<input ref="inp" type="text">
<button @click="changFn">点击让输入框聚焦</button>
</div>
<TestCom ref="testRef"></TestCom>
<button @click="clickFn">获取组件</button>
</template>
js
//组件
<script setup>
const count = 9999
const sayHi=()=>{
console.log("打招呼");
}
defineExpose({
count,
sayHi
})
</script>
<template>
<div>
我是用于测试的组件----{{ count }}
</div>
</template>
provide 和 inject
js
//顶层组件
<script setup>
import CenterCom from '@/components/center-com.vue'
import { provide, ref } from 'vue';
// 1. 跨层传递普通数据
provide('theme-clolor','pink')
// 2.跨层传递响应式数据
const count=ref(100)
provide('count',count)
// setTimeout(()=>{
// count.value+=100
// },2000)
// 3.修改数据
const changeCount=(newCount)=>{
count.value=newCount
}
provide('setCount',changeCount)
</script>
<template>
<div>我是顶层组件</div>
<CenterCom></CenterCom>
</template>
js
//底层组件
<script setup>
import { inject } from 'vue';
const themeColor=inject('theme-clolor')
//-----------------------------------
const count=inject('count')
//-----------------------------
const setCount=inject('setCount')
const changeCount=()=>{
setCount(10000)
}
</script>
<template>
<div>我是底层组件----{{ themeColor }}---------{{ count }}</div>
<button @click="changeCount">修改数据</button>
</template>
vue3新特性
defineOptions
- 背景
defineModel
js
//主组件
<script setup>
import Myinput from '@/components/my-input.vue'
import { ref } from 'vue';
const txt=ref('123456')
</script>
<template>
<Myinput v-model="txt"></Myinput>
{{ txt }}
</template>
js
<script setup>
import { defineModel } from 'vue';
const modelValue=defineModel()
</script>
<template>
<input type="text" :value="modelValue"
@input="e=>modelValue=e.target.value">
</template>
Pinia快速入门
vue的最新 状态管理工具 vueX的替代品