Vue3
一、创建vue3项目
1、官网
https://cn.vitejs.dev/guide/
2、创建项目
# 使用npm npm create vite@latest
3、vite为什么这么快
- 冷启动 - 热加载 - 按需编译
二、setup函数
1、setup特性
- setup为Vue3.0中一个新的配置项,值为一个函数
- setup是所有Composition API(组合API)编写的位置
- 组件中所用到的:数据、方法等等,均要配置在setup中
- setup函数的返回值:返回一个对象,对象中的属性、方法, 在模板中均可以直接使用
注意:
- 尽量不要与Vue2.x配置混用
- Vue2.x配置(data、methos、computed...)中可以访问到setup中的属性、方法。
- 但在setup中不能访问到Vue2.x配置(data、methos、computed...)。
- 如果有重名, setup优先。
2、示例:
<template> {{name}}--{{age}}--{{xx}} </template> <script> export default { name: 'App', data(){ return { xx:this.name } }, setup(){ let name='lqz' let age =19 return { name,age } }, } </script>
3、setup执行的时机
在Vue 3中,setup
函数是用来配置组件的入口点。它是在组件实例创建之前执行的,而不是在beforeCreate
钩子之前执行。这是因为setup
函数的目的是为了设置组件的响应式数据、
计算属性、方法等,它会返回一个对象,包含这些配置项,然后这些配置项将会被合并到组件实例中。
在beforeCreate之前执行一次,this是undefined。 # setup的参数 props:值为对象,包含:组件外部传递过来,且组件内部声明接收了的属性。 context:上下文对象 attrs: 值为对象,包含:组件外部传递过来,但没有在props配置中声明的属性, 相当于 this.$attrs。 slots: 收到的插槽内容, 相当于 this.$slots。 emit: 分发自定义事件的函数, 相当于 this.$emit。 # 总结: setup执行是在beforeCreate,没有this对象,以后不要用this了 如果写setup函数,想接收父组件自定义属性传入的值,需要 export default { setup(props) { console.log(props.msg) }, props: ['msg'] } 如果是vue3的最新写法,想接收父组件自定义属性传入的值,需要 <script setup> defineProps(['msg']) </script>
4、vue3兼容vue2,但是最好不要混用
<template> <div class="home"> <p>我的名字是:{{ name }}</p> <p>我的年龄是:{{ age }}</p> <button @click="handleClick">点我看信息</button> </div> </template> <script> export default { setup() { // 1 定义数据 const name = 'lqz' let age = 19 // 2 定义方法 const showInfo = () => { alert(`姓名是:${name},年龄是:${age}`) } return {name, age, showInfo} }, methods: { handleClick() { alert(`姓名是:${this.name},年龄是:${this.age}`) } } } </script>
三、ref函数
1、ref函数绑定响应式
导入ref:import {ref} from 'vue'
<template> <div class="home"> <p>我的名字是:{{ name }}</p> <p>我的年龄是:{{ age }}</p> <button @click="handleAdd">点我年龄+1</button> <button @click="handleChangeName">点我秒变彭于晏</button> </div> </template> <script> // 变量要具备响应式---》页面内容变化,变量和变,变量变化,页面也变 // 普通变量,通过ref绑定响应式 // 引用类型变量:通过reactive 绑定响应式 import {ref} from 'vue' export default { setup() { // 1 定义数据 let name = ref('lqz') let age = ref(19) // 2 定义方法 const handleAdd = () => { age.value += 1 console.log(typeof age) } const handleChangeName = () => { name.value = '彭于晏' } return {name, age, handleAdd,handleChangeName} }, } </script>
2、vue3中使用const定义方法和使用let定义方法的场景
在Vue 3中,通常会使用const
或function
关键字来定义组件的方法。使用const
关键字定义方法是合法的,
当你使用const
定义方法时,它会被视为一个常量,意味着它不会在每次重新渲染组件时被重新创建。这种优化可以提高性能,因为不需要在每次渲染时重新创建方法。
然而,如果你使用const
定义一个方法,并且该方法内部依赖于组件的响应式数据或属性,可能会遇到问题。因为常量方法内部无法访问响应式数据。在这种情况下,你应该使用function
关键字定义方法,或者将方法定义为组件的实例方法,以确保它可以访问到组件的响应式数据。
使用let
定义方法通常不是一个好的做法,因为它会导致方法在每次重新渲染时被重新创建,这可能会影响性能。然而,在某些特殊情况下,你可能希望在每次渲染时都创建一个新的方法实例,这时使用let
定义方法就是合适的。
四、reactive函数
1、父组件
<template> <div class="home"> <p>我的名字是:{{ data.name }}</p> <p>我的年龄是:{{ data.age }}</p> <p>我的爱好是:{{ hobby }}</p> <button @click="addAge">点我年龄+1</button> <br> {{ obj.hobby }} <br> <button @click="changeHobby">点我把保龄球换成足球</button> <hr> <h2>这里是父传子的消息</h2> <HelloWorld msg="我是你baba发过来的"></HelloWorld> </div> </template> <script> import {reactive, ref} from 'vue' import HelloWorld from "@/components/HelloWorld.vue"; export default { setup() { let hobby = ref('篮球') let obj = ref({ age: 99, hobby: '保龄球' }) const changeHobby = () => { console.log(obj) obj.value.hobby = '足球' } let data = reactive({ name: '彭于晏', age: 19 }) const addAge = () => { //data.age++ console.log(typeof data) console.log(data) // 是一个代理对象,无法拿出原来对象,但是操作起来跟操作源对象一样 data.age++ } return {hobby, data, addAge, obj, changeHobby} }, components: { HelloWorld } } </script>
补充:
/*ref
作用: 定义一个响应式的数据
语法: const xxx = ref(initValue)
创建一个包含响应式数据的引用对象(reference对象,简称ref对象)。
JS中操作数据: xxx.value
模板中读取数据: 不需要.value,直接:<div>{{xxx}}</div>
备注:
接收的数据可以是:基本类型(值类型)、也可以是对象(引用类型)类型。
reactive
作用: 定义一个对象类型的响应式数据(基本类型不要用它,要用ref函数)
语法:const 代理对象= reactive(源对象)接收一个对象(或数组),返回一个代理对象(Proxy的实例对象,简称proxy对象)
reactive定义的响应式数据是“深层次的”,无论套多少层,都具备响应式
# 总结:
如果用基本数据类型:数字,字符串,布尔,用ref做响应式
如果是对象类型,用ref和reactive都可以,但是建议使用reactive
如果使用ref包裹对象类型,多了一层value
2、子组件
<template> <div class="hello"> <h1>{{ msg }}</h1> </div> </template> <script > export default { name: 'HelloWorld', setup(props, context, attrs, slots, emit) { console.log(props.msg) console.log(context) }, props: ['msg'] } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> h3 { margin: 40px 0 0; } ul { list-style-type: none; padding: 0; } li { display: inline-block; margin: 0 10px; } a { color: #42b983; } </style>
五、计算和监听属性
1、计算属性:computed、监听属性 watch
<template> <div class="home"> <input type="text" v-model="name.firstName"> <input type="text" v-model="name.lastName"> <br> <input type="text" v-model="fullName"> <button @click="age++">点我年龄加</button> </div> </template> <script> // 导入 import {computed, watch, reactive, ref, watchEffect} from 'vue' export default { setup() { // 计算属性:computed let name = reactive({ firstName: 'liu', lastName: 'qz' }) let fullName = computed({ get() { return name.firstName + '-' + name.lastName }, set(value) { const nameArr = value.split('-') name.firstName = nameArr[0] name.lastName = nameArr[1] } }) let age = ref(19) // 监听属性 // 监听基本类型 watch(age, (newValue, oldValue) => { console.log(oldValue) console.log(newValue) }) // 监听对象 watch(() => name.firstName, (newValue, oldValue) => { console.log(oldValue) console.log(newValue) }) // watchEffect函数 watchEffect(() => { const x1 = age.value const x2 = name.firstName console.log('watchEffect配置的回调执行了') }) return {name, fullName, age} } } </script>
补充:
在计算属性computed中,set(value)方法用于设置fullName的值,其中value是接收前端传进来要修改的值,fullName改变,firstName和lastName跟着改变。
六、生命周期
1、 Vue3.0中可以继续使用Vue2.x中的生命周期钩子,但有有两个被更名:
# vue2 生命周期---8个 # vue3 变了 -把生命周期写下setup函数中 beforeDestroy改名为 beforeUnmount destroyed改名为 unmounted beforeCreate created beforeMount mounted beforeUpdate updated beforeUnmount unmounted
2、Vue3.0也提供了 Composition API 形式的生命周期钩子,与Vue2.x中钩子对应关系如下:
beforeCreate===>setup() created=======>setup() beforeMount ===>onBeforeMount mounted=======>onMounted beforeUpdate===>onBeforeUpdate updated =======>onUpdated beforeUnmount ==>onBeforeUnmount unmounted =====>onUnmounted
3、示例
<template> <div class="home"> <h1>首页</h1> </div> </template> <script> import axios from "axios"; import { computed, watch, reactive, ref, watchEffect, onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted } from 'vue' export default { name: 'HomeView', setup() { // 第一个beforeCrete console.log('我是beforeCrete') // 第二个Creted let name = ref('lqz') console.log('Creted') // axios.get().then(res => { // name.value = res.data.name // }) // 直接启动定时器 let t = setInterval(() => { console.log('lqz') }, 3000 ) // 第三个:onBeforeMount onBeforeMount(() => { console.log('挂载了') }) onBeforeUnmount(() => { clearInterval(t) t = null }) return {} }, } </script>
七、torefs
作用:创建一个 ref 对象,其value值指向另一个对象中的某个属性。
语法:const name = toRef(person,'name')
应用: 要将响应式对象中的某个属性单独提供给外部使用时。
扩展:toRefs
与toRef
功能一致,但可以批量创建多个 ref 对象,语法:toRefs(person)
<template> <div className="home"> <h1>首页</h1> {{ name }}---{{ age }} </div> </template> <script> import { reactive, toRefs } from 'vue' export default { name: 'HomeView', setup() { let data = reactive({ name: 'lqz', age: 18 }) return {...toRefs(data)} }, } // 对象的解压 let data = {'name': 'lqz', age: 19} let dict = {...data, hobby: '篮球'} console.log(dict) </script>
补充:
torefs的作用:data里面定义的数据,可以直接引用,而不是data.xx这样
八、vue3 setup写法
# 以后vue3推荐,把setup函数的代码,直接写在script中 <script setup> 定义变量 写函数 不用return,在html中直接使用 </script> # 使用组件,直接导入,不需要配置,直接用即可 import HelloWorld from "../components/HelloWorld.vue"; 在html中直接用:<HelloWorld msg="NB"></HelloWorld> # 自定义属性,在子组件中接收 <script setup> defineProps({ msg: { type: String, required: true } }) </script>