目录
五、ref函数_处理基本类型 注意导入的包是vue import {ref} from ’vue‘
1.vue3可以继续使用vue2的生命周期钩子,但有两个被更名:
2.通过组合式Api的生命周期钩子:组件设生命周期钩子里面传递的是回到函数
1.在src下新建hook命名的js文件用use开头,src/hook/usepointe.js
1.shallowReactive 与 shallowRef
1.我们可以更加优雅的组织我们的代码,函数,让相关功能代码有序的组织在一起
1.Fragment:虚拟组件,减少内存占用,与标签层级的减少
2.Teleport:to就是样式选择器,可以配置他展示的地方
一、创建Vue3工程
1.使用vue-cli vue create 名字 选择3版本
2.使用vite npm init vite-app 名字 这个打包起来更快更轻便 npm i(装依赖) npm run dev(启动)
二、关闭语法检查
lint1.在 src/vue.config.js中加入
lintOnSave:false关闭语法检查
三、Vue组件新知识点
1.vue3可以没有div包起来,可以只用template
四、初识setup
1.setup是所有组件的的API表演的舞台。2.组件中所用到的:数据,方法等等均要配置在setup中。
3.setup的两种返回值:(1)若返回一个对象则对象的属性,方法,在模板中均可以使用。(重点关注)。(2)返回一个渲染函数可以自定义渲染内容(了解)4.注意:尽量不要与Vue2配置混用,5.setup函数不能加async函数,因为他的返回值就不是return对象了。
<template>
<h1>一个人的信息</h1>
<h2>姓名:{{ name }}</h2>
<h2>年龄:{{ age }}</h2>
<button @click="sayHello">说话</button>
</template>
<script>
export default {
name: "App",
// 此处只是测试一下setup,暂时不考虑响应式
setup () {
// 数据
let name = "jack"
let age = 18
// 方法
function sayHello () {
alert(`我叫${name},年龄${age}`)
}
return {
name,
age,
sayHello
}
}
}
</script>
<style>
</style>
五、ref函数_处理基本类型 注意导入的包是vue import {ref} from ’vue‘
双向绑定数据啦;响应式数据
1.先导入ref再使用:
<template>
<h1>一个人的信息</h1>
<h2>姓名:{{ name }}</h2>
<h2>年龄:{{ age }}</h2>
<button @click="changeInfo">点我更改数据</button>
</template>
<script>
import { ref } from '@vue/reactivity'
export default {
name: "App",
// 此处只是测试一下setup,暂时不考虑响应式
setup () {
// 数据
let name = ref("jack")
let age = ref(18)
// 方法
function changeInfo () {
name.value = "marry"
age.value = 48
}
return {
name,
age,
changeInfo
}
}
}
</script>
<style>
</style>
六、ref函数_处理对象类型
1.先导入ref再使用:
<template>
<h1>一个人的信息</h1>
<h2>姓名:{{ name }}</h2>
<h2>年龄:{{ age }}</h2>
<h2>工作种类:{{ job.type }}</h2>
<h2>工作薪水:{{ job.salary }}</h2>
<button @click="changeInfo">点我更改数据</button>
</template>
<script>
import { ref } from '@vue/reactivity'
export default {
name: "App",
// 此处只是测试一下setup,暂时不考虑响应式
setup () {
// 数据
let name = ref("jack")
let age = ref(18)
let job = ref({
type: "前端工程师",
salary: "30k"
})
// 方法
function changeInfo () {
// name.value = "marry"
// age.value = 48
job.value.type = "UI设计师"
job.value.salary = "60K"
}
return {
name,
age,
changeInfo,
job
}
}
}
</script>
<style>
</style>
七、reactive函数
reactive只能处理对象,数组 . 不能处理基本类型string number ,但是可以定义一个大的对象
<template>
<h1>一个人的信息</h1>
<h2>姓名:{{ name }}</h2>
<h2>年龄:{{ age }}</h2>
<h2>工作种类:{{ job.type }}</h2>
<h2>工作薪水:{{ job.salary }}</h2>
<button @click="changeInfo">点我更改数据</button>
</template>
<script>
import { reactive, ref } from '@vue/reactivity'
export default {
name: "App",
// 此处只是测试一下setup,暂时不考虑响应式
setup () {
// 数据
let name = ref("jack")
let age = ref(18)
let job = reactive({
type: "前端工程师",
salary: "30k"
})
// 方法
function changeInfo () {
// name.value = "marry"
// age.value = 48
job.type = "UI设计师"
job.salary = "60K"
}
return {
name,
age,
changeInfo,
job
}
}
}
</script>
八、ref与reactive的对比
ref用来定义基本数据。reactive用来定义对象(或数组)类型数据,
从使用角度来说ref需要 .value reactive不需要
reactive相比较来说常用(解决reactive不能定义基本类型数据问题)
<template>
<h1>一个人的信息</h1>
<h2>姓名:{{ person.name }}</h2>
<h2>年龄:{{ person.age }}</h2>
<h2>工作种类:{{ person.job.type }}</h2>
<h2>工作薪水:{{ person.job.salary }}</h2>
<button @click="changeInfo">点我更改数据</button>
</template>
<script>
import { reactive } from '@vue/reactivity'
export default {
name: "App",
// 此处只是测试一下setup,暂时不考虑响应式
setup () {
// 数据
let person = reactive({
name: "jack",
age: 18,
job: {
type: "前端工程师",
salary: "30k"
}
})
// 方法
function changeInfo () {
// name.value = "marry"
// age.value = 48
person.job.type = "UI设计师"
person.job.salary = "60K"
}
return {
changeInfo, person
}
}
}
</script>
<style>
</style>
九、setup的两个注意点
1.setup的执行时机
再beforecreate之前执行一次,this是undefined
2.setup的参数
props:值为对象,包含外部组件传递过来,且内部声明接收的属性。
context:上下文对象:包含:
attrs:值为对象,外部组件传来的,但没有在props里面声明的属性,相当于this.$attrs
slots: 收到的插槽内容,相当于this.$slots
emit:分发自定义事件的函数,相当于this.$emit
3.代码:
// Demo组件的代码
<template>
<h1>一个人的信息</h1>
<h2>姓名:{{ person.name }}</h2>
<h2>年龄:{{ person.age }}</h2>
<h2>学校是{{ school }},信息是{{ msg }}</h2>
<button @click="hi">点我给父亲传递信息</button>
</template>
<script>
import { reactive } from '@vue/reactivity'
export default {
name: "TestDemo",
props: ["msg", "school"],
emits: ["hello"],
setup (props, context) {
let person = reactive({
name: "jack",
age: 18,
})
console.log(props, context)
function hi () {
context.emit("hello", 666)
}
return {
person,
hi
}
}
}
</script>
// App的组件代码
<template>
<Demo msg="nihao" school="atguigu" @hello="showMsg" />
</template>
<script>
import Demo from './components/Demo'
export default {
name: "App",
components: { Demo },
setup () {
function showMsg (value) {
alert(`我接受到的参数是${value}!`)
}
return {
showMsg
}
}
}
</script>
十、计算属性与监听属性
1.计算属性computed
注意:要引入computed属性 注意可以使用v-model属性
<template>
<h1>一个人的信息</h1>
姓:<input type="text" v-model="person.firstName" />
<br />
名:<input type="text" v-model="person.lastName" />
<br />
全名:<input type="text" v-model="person.fullName" />
</template>
<script>
import { reactive, computed } from '@vue/reactivity'
export default {
name: "TestDemo",
setup () {
let person = reactive({
firstName: "张",
lastName: "三",
})
// 计算属性 -简写(没有考虑计算属性被修改的情况)
/* person.fullName = computed(() => {
return person.firstName + "-" + person.lastName
}) */
// 计算属性 -完整写法(考虑读写的情况)
person.fullName = computed({
get () {
return person.firstName + "-" + person.lastName
},
set (value) {
const newArr = value.split('-')
person.firstName = newArr[0]
person.lastName = newArr[1]
}
})
return {
person,
}
}
}
</script>
2.监听属性watch:
<template>
<h1>sum是:{{ sum }}</h1>
<button @click="sum++">点我sum加一</button>
<h1>msg是:{{ msg }}</h1>
<button @click="msg += '!'">点我msg加!</button>
<hr />
<h2>姓名:{{ person.name }}</h2>
<h2>年龄:{{ person.age }}</h2>
<button @click="person.name += '~'">修改姓名</button>
<button @click="person.age += 1">修改年龄</button>
</template>
<script>
import { reactive, ref, watch } from 'vue'
export default {
name: "TestDemo",
setup () {
//数据
let sum = ref(0)
let msg = ref("你好啊")
let person = reactive({
name: '张三',
age: 18,
job: {
j1: {
salary: 20
}
}
})
// 情况一:监听ref所定义的一个响应式数据 (参数第一个监听谁,第二个函数表示处理的,第三个表示配置对象)
/* watch(sum, (newValue, oldValue) => {
console.log('sum变了', newValue, oldValue)
}, { immediate: true }) */
// 情况二:监听ref定义的多个响应式数据
/* watch([sum, msg], (newValue, oldValue) => {
console.log('sum或msg变了', newValue, oldValue)
}, { immediate: true }) */
// 情况三:监听reactive所定义的一个响应式数据:
// 1.注意:此处无法正确的获取oldValue
// 2.注意:强制开启深度监视(deep配置无效)
/* watch(person, (newValue, oldValue) => {
console.log('person变化了', newValue, oldValue)
}) */
// 情况四:监视reactive所定义的一个响应式数据中的某个属性,有oldValue
/* watch(() => person.name, (newValue, oldValue) => {
console.log('person变化了', newValue, oldValue)
}) */
// 情况五:监视reactive所定义的一个响应式数据中的某些属性,有oldValue
/* watch([() => person.name, () => person.age], (newValue, oldValue) => {
console.log('person变化了', newValue, oldValue)
}) */
// 特殊情况
watch(() => person.job, (newValue, oldValue) => {
console.log('person变化了', newValue, oldValue)
}, { deep: true })
return {
sum,
msg,
person
}
}
}
</script>
十一、watchEffect函数
里面参数是一个回到函数,里面用到的参数,只要一变就会再次调用这个函数
watchEffect(() => {
const x = sum //sum一边就调用这个函数
console.log('谁变调用了我', x)
})
十二、Vue的生命周期
1.vue3可以继续使用vue2的生命周期钩子,但有两个被更名:
beforedestroy ---> beforeMount destroy ----> unmount
2.通过组合式Api的生命周期钩子:组件设生命周期钩子里面传递的是回到函数
<template>
<h1>sum是:{{ sum }}</h1>
<button @click="sum++">点我sum加一</button>
</template>
<script>
import { onBeforeMount, ref } from 'vue'
export default {
name: "TestDemo",
setup () {
//数据
let sum = ref(0)
// 通过组合APi来设置生命周期函数
/* beforeCreate===>setup() */
/* create===>setup() */
/* beforeMount===>onBeforeMount */
/* Mounted===>onMounted */
/* beforeUpdated===>onBeforeUpdate */
/* updated===>onUpdated */
/* beforeUnmounted===>onBeforeUnmount */
/* unmounted===>onUnmounted */
onBeforeMount(() => {
console.log(123)
})
return {
sum,
}
}
}
</script>
十三、Vue3自定义hook:类式于Vue2的mixin
1.在src下新建hook命名的js文件用use开头,src/hook/usepointe.js
import { reactive, onMounted, onBeforeUnmount } from "vue"
export default function () {
let point = reactive({
x: 0,
y: 0
})
function savaPoint (event) {
point.x = event.pageX,
point.y = event.pageY
}
onMounted(() => {
window.addEventListener('click', savaPoint)
})
onBeforeUnmount(() => {
window.removeEventListener('click', savaPoint)
})
return point
}
2.Demo.vue的使用
<h2>当前鼠标的坐标,x:{{ point.x }},y:{{ point.y }}</h2>
import usePoint from '../hook/usePoint'
let point = usePoint()
return {point}
十四、toRef
1.作用创建一个ref对象,其value值指向另一个对象中的某个属性。
2.语法 const name = toRef(person,"name")
3.应用:将要响应式对象中的某个属性单独给外部使用。
4.扩展:toRef于toRefs功能一直,但可以创建多个ref对象,语法:toRefs(person)
十五、其他的Composition API
1.shallowReactive 与 shallowRef
shallowReactive: 只处理对象最外层属性的响应式(浅响应式)
shallowRef: 只处理基本数据类型的响应式,不进行对象的响应式处理
什么时候使用?
如果有一个数据,机构比较深,但变化的只是外层属性变化====》shallowreactive
如果有一个数据,后续功能不会修改对象中的属性,而是生新的对象来替换=====》shallowRef
2.readonly 与 shallowReadonly
readonly: 让一个响应式数据变为只读的(深只读)
shallowReadonly: 让一个数据变为只读的(浅只读)、
应用场景:希望数据不被修改
3.toRaw 与 markRaw
toRaw:作用将一个由reactive生成的响应式对象转为普通对象
使用场景:用于读取响应式对象的普通对象,对这个普通对象的所有操作,不会引起页面更新
markRaw:作用:标记一个对象,时期永远不会在成为响应式对象。
应用场景:有些值不应该被设置为响应式的,例如第三方库。2,当有渲染具有不可变数据源时使用
4.customRef自定义Ref对象
<template>
<input type="text" v-model="sum" />
<h1>sum是:{{ sum }}</h1>
</template>
<script>
import { customRef } from 'vue'
export default {
name: "TestDemo",
setup () {
//数据
function myRef (value, delay) {
let timer
return customRef((track, trigger) => {
return {
get () {
console.log('有人从myRef这个容器中读取数据')
track() //通知Vue追踪value的变化(提前和隔天商量一下,让他认为这个Value是有用的)
return value
},
set (newValue) {
console.log('有人修改这个容器')
clearTimeout(timer)
timer = setTimeout(() => {
value = newValue
trigger() //通知Vue重新解析模板
}, delay)
}
}
})
}
let sum = myRef("", 2000)
return {
sum
}
}
}
</script>
5.provide 与 inject 祖孙之间的数据传递:
(1) 爷爷组件提供数据
<template>
<div>
<h1>我是爷爷组件 --- {{ name }} === {{ price }}</h1>
<Child />
</div>
</template>
<script>
import { provide, toRefs } from '@vue/runtime-core'
import Child from './components/Child.vue'
export default {
name: "App",
components: { Child },
setup () {
let car = { name: "奔驰", price: "40w" }
provide("car", car) //第一个参数是标识,第二个参数是值
return {
...toRefs(car)
}
}
}
</script>
<style>
div {
background-color: orange;
}
</style>
(2)孙子及后代组件
<template>
<div style="background-color: red">
<h1>我是儿子组件 --- {{ name }} ==== {{ price }}</h1>
</div>
</template>
<script>
import { inject } from '@vue/runtime-core'
export default {
name: "TestSon",
setup () {
let x = inject('car')
return { ...x }
}
}
</script>
6.响应式数据的判断
isRef:检查一个值是否为ref对象
isReactive:检查一个对象是否是由reactive创建的响应式代理
isReadonly:检查一个对象是否是由readonly创建的只读代理
isProxy:检查一个对象是否是由reactive或者readonly方法创建的代理
十六、组合式API的优势
1.我们可以更加优雅的组织我们的代码,函数,让相关功能代码有序的组织在一起
十七、新的组件
1.Fragment:虚拟组件,减少内存占用,与标签层级的减少
2.Teleport:to就是样式选择器,可以配置他展示的地方
<teleport to="body">
<div v-if="isShow">
<h2>我是内容</h2>
<button @click="isShow = false">点我关闭</button>
</div>
</teleport>
3.Suspense:异步加载组件
import {defineAsyncComponent} from 'vue' //静态映入
const Child = defineAsyncComponent(()=>import('./components/Child.vue')) //动态引入,异步引入
<Suspense>
<template v-slot:default>
// default写的是展示的组件
<h1>我是加载完的</h1>
</template>
<template v-slot:fallback>
//fallback是默认写法
<h1>我是没加载好的时候展示</h1>
</template>
</Suspense>
完结推荐去看一下官网。。。。