目录
一、Vue3的创建
![](https://i-blog.csdnimg.cn/blog_migrate/c0fb2d1cd5c2e284ecb0114bcd2390b7.png)
前提:需要有node.js版本16.0以上
在对应目录下cmd输入:npm init vue@latest 创建
在项目目录底下npm install 安装依赖,不安装会显示找不到vite
vscode里的插件,vue2时安装的是Vetur,Vue3可以安装volar
目录介绍:
二、组合式API
1.setup
因为setup的执行时间非常早,所以是查询不到this的(显示undefind)
练手小案例:
// 在setup里面创建一个数组和一个函数,在浏览器展示出来
<script>
export default {
// 数组 和 函数 在setup的最后需要return输出才能被获取到
setup() {
const ceshi1 = '测试setup能否直接被获取到';
const ceshi2 = () => {
console.log(ceshi1);
}
return { ceshi1, ceshi2 };
}
}
</script>
<template lang="">
<div>
<div>{{ceshi1}}</div>
<button @click="ceshi2">按钮</button>
</div>
</template>
但是上面这样写数据少的时候还好,数据一多要return的也就越多,这时候可以用setup的语法糖
// 在script 后添加setup ,这样里面的setup数据就可以直接调用了,也不需要setup(){ }
<script setup>
// 数组 和 函数 在setup的最后需要return输出才能被获取到
const ceshi1 = '测试setup能否直接被获取到';
const ceshi2 = () => {
console.log(ceshi1);
}
</script>
2.reactive 和 ref(推荐) 函数
在vue中默认的数据不是响应式的,这时候可以使用 reactive 或 ref
reactive( ) -》接收一个对象类型的数据,返回响应式的数据
步骤:1、import 导入
2、调用方法进行转换,而后返回响应式数据
// 不添加reactive时count非响应式,点击按钮无法变更数字
<script setup>
const state = {
count:100
}
const setCount = ()=>{
state.count++
}
</script>
<template lang="">
<div>
<div>{{state.count}}</div>
<button @click="setCount">按钮</button>
</div>
</template>
//------添加后,可以变更数字----------
<script setup>
import { reactive } from 'vue';
const state = reactive({
count:100
})
const setCount = ()=>{
state.count++
}
</script>
ref( ) -》可以接收简单类型或对象类型数据,转换成响应式数据
步骤:1、import 导入
2、调用方法进行转换,而后返回响应式数据
![脚本区域要加.value](https://i-blog.csdnimg.cn/blog_migrate/970f2f41a39d9381e349a4754a02fa12.png)
// 简单类型---------------------
import { ref } from 'vue';
const state2 = ref(0);
const setCount2 = ()=>{
// 在后台需要修改ref包裹的count2里的数据,得修改count2里的value
state2.value++;
}
</script>
<template lang="">
<div>
<div>{{state2}}</div>
<button @click="setCount2">按钮</button>
</div>
</template>
// 复杂类型------------------------
import { ref } from 'vue';
const state2 = ref({aa:10});
console.log(state2);
const setCount2 = ()=>{
// 在后台需要修改ref包裹的count2里的数据,得修改count2里的value
state2.value.aa++;
}
</script>
<template lang="">
<div>
<div>{{state2.aa}}</div>
<button @click="setCount2">按钮</button>
</div>
</template>
3、computed计算属性
步骤:1、import 导入
2、在需要计算的地方调用
// 要求,把数组[1,2,3,4,5,6,7]筛选出比2大的数形成新数组
// 注意:1、别忘记导入
// 2、在需要计算的地方使用computed()计算属性
<script setup>
import { computed,ref } from 'vue';
var list = ref([1, 2, 3, 4, 5, 6, 7]);
// 生成一个计算属性,过滤出>2的数
var newList = computed(()=>{
return list.value.filter((num)=>{
return num >2;
})
})
</script>
<template lang="">
<div>
<div>原数组:{{list}}}</div>
<div>新数组:{{newList}}</div>
</div>
</template>
过滤器filter()的使用
4、watch监视属性
4.1 基本使用
![](https://i-blog.csdnimg.cn/blog_migrate/80f2fb66790e408b4f7f99bd1add1a2a.png)
![](https://i-blog.csdnimg.cn/blog_migrate/d66840280ae9bc9cfa82e04b25e26457.png)
小案例,通过按钮修改num1和name1,并监听
<script setup>
import { ref, watch } from 'vue';
const num1 = ref(0);
const name1 = ref('张三');
const newNum1 = () => {
num1.value++
}
const newName1= ()=>{
name1.value='李四';
}
watch([num1,name1], ([newNum1,newName1], [oldNum1,oldName1])=> {
console.log([newNum1,newName1], [oldNum1,oldName1]);
})
// 如果想一起监听并展示也可以向下面这样,把[newNum1,newName1]整合成一个newArr,后面的同理
// watch([num1,name1], (newArr, oldArr)=> {
// console.log(newArr, oldArr);
// })
</script>
<template lang="">
<div>
<!-- 要求:监听num1和name1的变化 -->
<div>{{num1}}</div>
<button @click="newNum1">+1</button>
<div>{{name1}}</div>
<button @click="newName1">改名字</button>
</div>
</template>
4.2 额外属性 (初始化调用、深度监听)
watch(沃取)里面还有两个属性,immediate、deep(默认都是false状态)
// 想要使用很简单,在箭头函数外面新添一个{}写就行
watch([num1,name1], ([newNum1,newName1], [oldNum1,oldName1])=> {
console.log([newNum1,newName1], [oldNum1,oldName1]);
},{
immediate:true; //<------true时,在初始化时会自动调用一次
deep:true //<------true时,开启深度监听,不开时只能监听到第一层,开启后能监听多层
})
4.3 精准监听
<script setup>
import { ref, watch } from 'vue';
const userInfo = ref({
age:12,
age2:25,
name:'520'
})
const setUserInfo= ()=>{
userInfo.value.age++
}
// 注意这里,精准监听的固定写法,把监视对象换成了箭头函数()=>userInfo.value.age,即userInfo里的age,后面不变
// 而且精准监听不用开deep(深度监听)
watch(()=>userInfo.value.age,(newValue,oldValue)=>{
console.log(newValue);
})
</script>
<template lang="">
<div>
<div>{{userInfo}}</div>
<button @click="setUserInfo">改数字</button>
</div>
</template>
5、生命周期函数
import { onBeforeMount,onMounted } from 'vue';
// 生命周期钩子的使用
// 全部都可以在setup里执行,像beforeMounted、Mounted这些
// 直接写成函数的形式,可以创建多个生命周期钩子,按顺序从上到下执行
const getList = ()=>{
setInterval(() => {
console.log('我是setup里的两秒定时器');
}, 2000);
}
getList()
// 想要在挂载前后生成东西可以这么写
onBeforeMount(() => {
console.log('根据顺序,onBeforeMount必须在onMounted前面')
}),
onMounted(() => {
console.log('我是Mounted,在Vue3中我写成onMounted')
})
onMounted(() => {
console.log('我是Mounted2号,在使用我之前要import导入')
})
</script>
6、父子通信(父传子props)
在父组件中导入子组件,给子组件绑定属性,子组件defineProps接收传递过来的参数,子组件使用传递过来的参数
6.1 非响应式数据传递
// -------父组件中------------
<script setup>
// 导入子组件
import HelloWorld from './components/HelloWorld.vue';
</script>
<template lang="">
<div>
<div>我是app.vue</div>
//调用子组件,并给子组件传递参数pro
<HelloWorld pro="父子成功传参啦"></HelloWorld>
</div>
</template>
// --------子组件中-------------
<script setup>
// 因为是在setup中,无法直接调用props,所以使用defineProps“编译器宏”
// const props = defineProps({ 传递参数名:类型 });
const props = defineProps({
pro:String
});
</script>
<template>
<div>
// 使用传递过来的参数pro
<div >我是子组件HelloWorld.vue-{{pro}}</div>
</div>
</template>
6.2 响应式数据传递 (动态更新)
// --------父组件-------------
<script setup>
// 导入ref
import { ref } from 'vue';
const money = ref(100);
const newMoney = ()=>{
money.value += 10;
}
</script>
<template lang="">
<div>
<div>
老爹的余额{{money}}
<button @click='newMoney'>赚钱</button>
</div>
</div>
</template>
// -------子组件-----------------
<script setup>
const props = defineProps({
// 类型的首字母要大写,传递多个参数时这样写:
pro:String,
money:Number
});
</script>
<template>
<div>
<div>父组件赚了{{ money }}块</div>
</div>
</template>
7、父子通信(子传父emit)
1、子组件内部通过emit方法触发事件(编译器宏获取)
2、父组件中,在子组件标签里通过@绑定事件监听
// -----------父组件---------------
<script setup>
import { ref } from 'vue';
import HelloWorld from './components/HelloWorld.vue';
const money = ref(100);
const changeFn =(Moneys)=>{
money.value = Moneys;
}
</script>
<template lang="">
<div>
<div>我是app.vue</div>
<HelloWorld @changeMoney='changeFn'></HelloWorld>
</div>
</template>
// -------------子组件---------------------
<script setup>
const emit = defineEmits(['changeMoney'])
const buy = ()=>{
emit('changeMoney',15)
}
</script>
<template>
<div>
<div class='zi'>
<button @click="buy">投资后</button>
</div>
</div>
</template>
// 1、通过编译器宏defineEmits定义emit(括号里写要触发的事件名称)
// 2、编写触发事件的方法,和要传递的内容【别忘了在template里写谁触发的事件】
// 3、在父组件里的子组件标签里添加@自定义事件,绑定一个函数
// 4、编写这个函数的方法,并接收子组件传过来的形参
8、模板引用
通过ref标识获取Dom对象或者组件实例对象
<script setup>
import { onMounted,ref } from 'vue';
// 1、调用ref函数生成一个ref对象
const inp = ref(null);
// 3、编写方法
onMounted(()=>{
console.log(inp.vlaue);
// inp是绑定在输入框上的,这里是指挂载完毕后给输入框获取焦点
inp.value.focus()
})
// clickFn是绑定在按钮上的,这里是指点击按钮后,给inp输入框获取焦点
const clickFn=()=>{
inp.value.focus()
}
</script>
<template>
<div>
// 2、通过ref表示绑定对象到标签上
<input ref="inp" type="text">
<button @click="clickFn">输入聚焦</button>
</div>
</template>
8.1、defineExpose( )
// 父组件
<script setup>
import { ref } from 'vue';
import Student from '@/components/Student.vue'
const std = ref(null);
const getStd = ()=>{
console.log(std.value);
}
</script>
<template lang="">
<div>
<Student ref="std"></Student>
<button @click='getStd'>获取Student组件数据</button>
</div>
</template>
// 子组件
<script setup>
const shuxing1 = 999
// 如果不defineExpose进行暴露,则父组件是得不到数据的
defineExpose({
shuxing1
})
</script>
<template>
<div>
用于测试的student
</div>
</template>
9、provide和inject
顶层组件向任意的底层组件传递数据或方法(跨层组件通信),爷爷给孙子曾孙子传递数据
使用的时候别忘了在对应组件里导入!!!!!
import { provide } from 'vue';
import { inject } from 'vue';
![](https://i-blog.csdnimg.cn/blog_migrate/fdf479745802f984b39efd5c241b79a1.png)
9.1、 底层组件怎么修改顶层组件数据?
谁的数据谁来维护,底层组件不能直接修改顶层的数据
解决方法:跨层级传递函数=> 给子孙后代传递可以修改数据的方法
// ---------顶层组件----------------
<script setup>
import school from './components/school.vue';
import { provide,ref } from 'vue';
// 首先定义一个响应式的hello1
const hello1 = ref(100)
// 利用provide传递给底层组件,传递的数值是hello1对象本身
provide('hello1', hello1)
// 给底层组件编写方法changeHello1,让他可以修改hello1的数据
provide('changeHello1', (newHello) => {
hello1.value = newHello
})
</script>
<template>
<div class="top1">
我是顶层组件
<school></school>
</div>
</template>
// ---------底层组件------------------
<script setup>
import { inject } from 'vue';
// 1、创建一个hello2,利用inject来接收顶层组件的hello1
const hello2 = inject('hello1')
console.log(hello2);
// 4、创建changeHello1 用来接收顶层组件传过来的changeHello1修改数据的方法
const changeHello1 = inject('changeHello1')
// 5、当按钮被点击时,changeHello1调用了顶层组件中changeHello1 里的方法,
// 把(1200)给到了hello1.value里,从而修改了数值,需要注意方法的控制器是顶层组件持有的
const clickFn = ()=>{
changeHello1(1200)
}
</script>
<template>
<div class="top3">
// 2、使用hello2
我是底层组件--{{ hello2 }}
// 3、创建一个点击事件用于修改顶层组件传过来的数据
<button @click="clickFn">更新父组件传递的数据</button>
</div>
</template>