Vue3基础

使用脚手架搭建需要确保@vue/cli 版本在 4.5.0 以上 查看@vue/cli 版本 vue --version

如果 vue/cli 版本过低或上方命令报错,需要安装或者升级你的 @vue/cli npm install -g @vue/cli

生命周期

vue2 --------> vue3
beforeCreate --------> setup(()=>{})
created --------> setup(()=>{})
beforeMount --------> onBeforeMount(()=>{})
mounted --------> onMounted(()=>{})
beforeUpdate --------> onBeforeUpdate(()=>{})
updated --------> onUpdated(()=>{})
beforeDestroy --------> onBeforeUnmount(()=>{})
destroyed --------> onUnmounted(()=>{})
activated --------> onActivated(()=>{})
deactivated --------> onDeactivated(()=>{})
errorCaptured --------> onErrorCaptured(()=>{})

setup()

Composition API 将 vue 中的很多功能拆分成了一个一个的 hook

可以理解为 Vue3 中一个新的配置项,值为一个函数 setup()

setup() 是所有 Composition API(组合式 API)的入口

setup() 函数内的 this 指向 undefined

setup 函数是处于生命周期函数 beforeCreateCreated 两个钩子函数之前的函数,也就说在 setup 函数中是无法使用 datamethods 中的数据和方法的

在 setup 函数中定义的变量和方法最后都是需要 return 出去的,不然无法在模板中使用

注意:如果 data 内的变量和 setup 函数内的变量重名,优先使用 setup 里面的变量

setup 可以接受参数 propscontent

setup(props, content){}
# or
setup(props, { attrs, slots, emit }) {}

props

组件外部传递进入或组件内部声明已经接收的属性

// 父组件
<son :name = "obj.name"></son>
// 子组件
<template>
<div>
<h1>我是子组件</h1>
<div>{{ name }}</div>
</div>
</template>
<script>
export default {
props: {
name: { type: String }
},
setup(props, context) {
console.log(props)
}
}
</script>

context

包含 attrsslotsemitcontent 参数可以解构

attrs

是组件外部传递进入组件的值,但组件内部未在 props 内声明,即可使用 context.attrs 得到

// 父组件
<son :name = "obj.name" :age = "obj.age"></son>
// 子组件
<script>
export default {
props: {
name: { type: String }
},
setup(props, context) {
console.log(props)
console.log(context.attrs.age)// 此时未在props声明age
}
</script>

emit

用于分发自定义函数,等同于 this.$emit,可用于子向父传值

// 子组件
<button @click = "son">子组件</button>
<script>
export default {
setup(props, context) {
const son = () => {
context.emit('change', 50)
}
return { son }
}
}
</script>
// 父组件
<template>
<div>
<h1>我是父组件</h1>
<div>子组件可以改变我的值{{ sonval }}</div>
<div>---------------------------------------</div>
<son :name = "obj.name" :age = "obj.age" @change = "formSon"></son>
</div>
</template>
<script>
import son from '../components/son.vue'
import { ref } from 'vue'
export default {
name: 'Father',
components: { son },
setup() {
let sonval = ref(0)
const formSon = val => {
sonval.value = val
}
return { formSon, sonval }
}
}
</script>

slots

可以获取插槽的内容,相当于 this.$slots

// 子组件
<template>
<div>
<h1>我是子组件</h1>
<slot name="son">
<div>默认插槽</div>
</slot>
</div>
</template>
<script>
export default {
props: {
name: { type: String }
},
setup(props, context) {
console.log(context.slots.son()[0])// 获取slot的信息
}
}
</script>
// 父组件
<son>
<template v-slot:son>
<p>我是父组件呵呵哈哈哈</p>
</template>
</son>

setup 语法糖

vue3.2 开始,在 script 脚本上声明 setup 会自动将所有顶级函数和变量自动暴露给模板使用

<template>
<div>
{{ name }}
<button @click = "changeName">改变名字</button>
</div>
</template>
<script setup>
import { ref } from 'vue'
const name = ref('user')
const changeName = () => {
name.value = 'newUser'
}
</script>

因为没有了 setup 函数,如果需要使用 propsemitattrs 等参数,需要调用相关函数

defineProps用来接收父组件传来的 props

defineEmits 用来声明触发的事件

useAttrs 用来接收父组件传递但子组件未使用 props 接收的变量

useSlots 用来获取插槽相关信息

const emit = defineEmits(['change'])
const props = defineProps(['age'])
const slots = useSlots()
const attrs = useAttrs()

数据定义

ref

使用 ref 可以定义一个响应式数据 const xxx=ref(initValue)

使用前需要按需导入,ref 定义的响应式数据修改数据时必需要.value取值

<script setup>
import { ref } from 'vue'
// 括号内的为初始值
// 基本数据类型 number,string,boolean
let name=ref('张三');
let age=ref(18);
let isMarry=ref(false);
// 使用ref定义数组
let hobby=ref(['吃饭','睡觉','打豆豆']);
// 使用ref定义对象
let user=ref({
idCard:'身份证',
nation:['中国','美国','英国','俄罗斯']
})
const changeName = () => {
name.value = '李四'// name.value修改数据
}
</script>

reactive 函数

使用 reactive 可以定义一个响应式数据 const 代理对象=reactive(被代理的对象) 接收一个对象(或数组),返回一个代理器对象(Proxy 的实例对象,简称 Proxy 对象)

使用前需要按需导入reactive

<script setup>
import { reactive } from 'vue'
let student=reactive({
name:'张三',
age:19,
hobbies:['吃饭','睡觉','打豆豆']
});
console.log(student)
const changeName = () => {
student.name = '李四' // 直接修改数据
}
</script>

reactive 与 ref

ref 多用来定义:基本类型数据

reactive 多用来定义:对象(或数组)类型数据

注意:ref 也可以用来定义对象(或数组)类型的数据,它内部会自动通过 reactive 转为代理对象

两者原理

ref 通过 Object.defineProperty()的 get 和 set 实现(响应式)数据劫持

reactive 通过使用 Proxy 来实现响应式(数据劫持),并通过 Reflect 操作源对象内部的数据 从使用角度

所以 ref 操作数据需要.value,但 reactive 定义的数据可以直接修改

toRef、toRefs

使用 toRef 创建一个 ref 对象,其 value 值指向另一个对象中的某个属性值

<template>
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
</template>
<script>
import {reactive,toRef} from 'vue'
export default {
setup(){
let person=reactive({
name:'user',
age:18
})
return{
name: toRef(person, 'name'),
age: toRef(person, 'age'),
}
}
}
</script>

toRefs 与 toRef 功能一致,但可以批量创建多个 ref 对象

<template>
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
</template>
<script>
import {reactive,toRef} from 'vue'
export default {
setup(){
let person=reactive({
name:'user',
age:18
})
return{
...toRefs(person)
}
}
}
</script>

数据处理

shallowRef 和 shallowReactive

shallowReactive:只处理对象最外层属性的响应式(浅响应式),对深层次的数据不会改变视图但会改变数据

const state = shallowReactive({
foo: 1,
nested: {
bar: 2
}
})
// 改变 state 本身的性质是响应式的
state.foo++
// ...但是不转换嵌套对象
isReactive(state.nested) // false
state.nested.bar++ // 非响应式

如果有一个对象数据,结构比较深,但变化时只是外层属性变化用 shallowReactive

shallowRef: 只处理基本数据类型的响应式,不进行对象的响应式处理

const a = shallowRef({ b: 1 })
a.value.b = 2 //视图不会更新
console.log(a.value) //{b : 2} 但是能追踪到值得变化
a.value = { b: 2 } //一整个替换时,视图会变化

如果有一个对象数据,后续功能不会修改该对象中的属性,而是生新的对象来替换用 shallowRef

readonly 和 shallowReadonly

readonly:让一个响应式数据变为只读的(深只读),所有的数据将无法被修改

shallowReadonly:让一个响应式变为只读的(浅只读),基本数据类型无法被修改,对象可以被修改

<template>
<div>{{ sum }}</div>
<button @click = "sum++">sum按钮</button>
<div>{{ name }}</div>
<button @click = "name += '~'">按钮name</button>
<div>{{ job.j1.salary }}</div>
<button @click = "job.j1.salary++">按钮salary</button>
</template>
<script>
import { reactive, ref, toRefs, shallowReadonly } from 'vue'
export default {
name: 'DemoComponent',
setup() {
let sum = ref(0);
let person = reactive({
name: '张三',
job: {
j1: {
salary: 20
}
}
})
// 深只读,对象层次深也能检测不能改变数据
person = readonly(person);
// 浅只读,只能控制第一层
person = shallowReadonly(person);
return {
sum,
...toRefs(person),
}
}
}
</script>

toRaw 和 markRaw

toRaw 将一个由 reactive 生成的响应式对象转为普通对象对这个普通对象的所有操作,不会引起页面更新,对 ref 定义的响应式数据无效!

markRow 标记一个对象,使其永远不会再成为响应式对象。有些值不应该被设置为响应式的,例如复杂的第三方类库,当渲染具有不可变的数据源的大列表时,跳过响应式转换可以提高性能

响应式数据的判断

isRef:检查一个值是否为 ref 对象

isReactive:检查一个对象是否由 reactive 创建的响应式代理

isReadonly:检查一个对象是否由 readonly 创建的只读代理

isProxy:检查一个对象是否由 reactive 或者 readonly 方法创建的代理

provide 和 inject

用于实现祖与后代组件间通信

<template>
<h2>我是祖组件</h2>
<h3>汽车信息</h3>
<p>名称:{{name}}</p>
<p>价格:{{price}}</p>
<inject_component></inject_component>
</template>
<script>
import {reactive,toRefs,provide} from 'vue'
export default {
name: "provide_component",
setup(){
let car=reactive({
name:'宝马',
price:'40w'
})
provide('car',car) // 提供provide
return{
...toRefs(car)
}
}
}
</script>
<template>
<h2>我是孙组件</h2>
<h3>汽车信息</h3>
<p>名称:{{name}}</p>
<p>价格:{{price}}</p>
</template>
<script>
import {inject,toRefs,ref} from 'vue'
export default {
name: "inject_component",
setup(){
let car=inject("car"); //使用inject接收
return{
...toRefs(car)
}
}
}
</script>

过滤器

vue3 建议使用计算属性代替过滤器,如果需要全局过滤器可以自定义全局属性

// 定义全局属性

app.config.globalProperties.$filters = {
currencyUSD(value) {
return '$' + value
}
}
posted @   有些东西学不会  阅读(285)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
// 侧边栏目录 // https://blog-static.cnblogs.com/files/douzujun/marvin.nav.my1502.css
点击右上角即可分享
微信分享提示