Vue3出了很久了,我之前也体验过,但是没有很好地出过一篇讲解他的用法的文章,昨天我又好好体验了一把,并总结了一些用法,分享给大家
先来说说一些API的用法
这个语法糖真的是太爽了,想想之前vue2的那些写法,真的让人很恼火,自由度非常不够,setup script体验过的都说好~别急,咱们继续~
<script setup lang="ts">
// 在这里写vue的逻辑
</script>
<template>
<div>哈哈</div>
</template>
总结三点:
ref:需要响应式的常量,但是使用或者赋值时需要xxx.value
reactive:需要响应式的对象或者数组,可直接使用或赋值
事件:在setup script中,直接定义事件,不需要像vue2那样在method中定义
<script setup lang="ts">
import { ref, reactive } from 'vue'
const enum Name {
CN = '林三心',
EN = 'Sunshine_Lin'
}
const enum Gender {
MAN = '男',
WOMAN = '女'
}
// 常量
const name = ref(Name.CN)
// 对象、数组
const user = reactive({
name: Name.CN,
gender: Gender.MAN
})
const arr = reactive<{ name: string }[]>([{ name: '嘻嘻嘻' }])
// 事件直接定义
const switchName = () => {
// 赋值需要name.value
name.value = name.value === Name.CN ? Name.EN : Name.CN
}
// 事件直接定义
const switchGender = () => {
// 直接赋值
user.gender = user.gender === Gender.MAN ? Gender.WOMAN : Gender.MAN
}
const handleAdd = () => {
arr.push({ name: '哈哈哈' })
}
</script>
<template>
<button @click="switchName">
我叫 {{name}}
</button>
<button @click="switchGender">
我叫 {{user.name}},我是 {{user.gender}}
</button>
<button @click="handleAdd">新增</button>
<ul>
<li v-for="(item, index) in arr" :key="index">{{ item.name }}-{{ index }}</li>
</ul>
</template>
<script setup lang="ts">
import { ref,
reactive,
computed,
watch,
watchEffect } from 'vue'
const enum Name {
CN = '林三心',
EN = 'Sunshine_Lin'
}
const enum Gender {
MAN = '男',
WOMAN = '女'
}
const name = ref(Name.CN)
const user = reactive({
name: Name.CN,
gender: Gender.MAN
})
const switchName = () => {
name.value = name.value === Name.CN ? Name.EN : Name.CN
}
const switchGender = () => {
user.gender = user.gender === Gender.MAN ? Gender.WOMAN : Gender.MAN
}
// computed计算出userText
const userText = computed(() => {
return `我叫${user.name},我是${user.gender}的`
})
// 监听常量name
watch(name, (next, pre) => {
console.log('name被修改了', next, pre)
})
// 监听user对象
watch(user, (next) => {
console.log('user被修改了', next)
}, {
immediate: false, // 首次执行
deep: true // 深度监听对象
})
// 可监听对象的某个属性,这里监听user.gender
watch(() => user.gender, (next, pre) => {
console.log('user.gender被修改了', next, pre)
})
// 不需要说明监听谁
// 用到user.gender就监听user.gender
watchEffect(() => {
const gender = user.gender
console.log('user.gender被修改了', gender)
})
</script>
<template>
<button @click="switchName">修改name</button>
<button @click="switchGender">修改user.gender</button>
<div>{{ userText }}</div>
</template>
看一下vue2的生命周期在vue3中的表现
<script setup lang="ts">
import {
onBeforeMount,
onMounted,
onUpdated,
onBeforeUpdate,
onBeforeUnmount,
onUnmounted,
onActivated,
onDeactivated,
onErrorCaptured
} from 'vue'
onBeforeMount(() => {
console.log('挂载前')
})
onMounted(() => {
console.log('挂载')
})
onBeforeUpdate(() => {
console.log('更新前')
})
onUpdated(() => {
console.log('更新')
})
onBeforeUnmount(() => {
console.log('销毁前')
})
onUnmounted(() => {
console.log('销毁')
})
onActivated(() => {
console.log('kee-alive激活本组件')
})
onDeactivated(() => {
console.log('kee-alive隐藏本组件')
})
onErrorCaptured(() => {
console.log('错误捕获')
})
</script>
还记得之前vue2的父传子,子改父,的做法吗?使用porps、this.$emit
到了vue3,这种写法改了
我们来看看父组件
<script setup lang="ts">
import { ref } from 'vue'
import Dialog from './Dialog.vue'
const msg = ref('我是msg')
const changeMsg = (val: string) => {
msg.value = val
}
</script>
<template>
// 传进子组件
<Dialog :msg="msg" @changeMsg="changeMsg" />
</template>
再来看看子组件
<script setup lang="ts">
import { defineProps, defineEmits } from 'vue'
// 注册父传子的props
const { msg } = defineProps({
msg: {
type: String,
required: true
}
})
// 注册父传子的事件
const emits = defineEmits(['changeMsg'])
const handleClick = () => {
// 修改父组件的值
emits('changeMsg', '修改msg')
}
</script>
<template>
<div @click="handleClick">{{ msg }}</div>
</template>
这个API主要主要作用是:将子组件的东西暴露给父组件,好让父组件可以使用
<!-- 子组件 -->
<script setup>
import { ref } from 'vue'
const msg = ref('hello vue3!')
function change() {
msg.value = 'hi vue3!'
console.log(msg.value)
}
// 属性或方法必须暴露出去,父组件才能使用
defineExpose({ msg, change })
</script>
<!-- 父组件 -->
<script setup>
import ChildView from './ChildView.vue'
import { ref, onMounted } from 'vue'
const child = ref(null)
onMounted(() => {
console.log(child.value.msg) // hello vue3!
child.value.change() // hi vue3!
})
</script>
<template>
<ChildView ref="child"></ChildView>
</template>
需要注意几个点:
// 全局自定义指令
app.directive('focus', {
mounted(el) {
el.focus()
}
})
// 全局自定义组件
import CustomComp from './components/CustomComp.vue'
app.component('CustomComp', CustomComp)
还记得vue2中的自定义指令吗?
Vue.directive('xxx', {
// 指令绑定到指定节点,只执行一次
bind() {},
// 指定节点插入dom
inserted() { },
// 节点VNode更新时,可能刚更新,没完全更新
update() {},
// VNode完全更新
componentUpdated() {},
// 指令从指定节点解绑,只执行一次
unbind() {}
})
再来看看vue3的,比较贴近vue本身的生命周期
app.directive('xxx', {
// 在绑定元素的 attribute 或事件监听器被应用之前调用, 在指令需要附加须要在普通的 v-on 事件监听器前调用的事件监听器时,这很有用
created() {},
// 当指令第一次绑定到元素并且在挂载父组件之前调用
beforeMount() {},
// 在绑定元素的父组件被挂载后调用
mounted() {},
// 在更新包含组件的 VNode 之前调用
beforeUpdate() {},
// 在包含组件的 VNode 及其子组件的 VNode 更新后调用
updated() {},
// 在卸载绑定元素的父组件之前调用
beforeUnmount() {},
// 当指令与元素解除绑定且父组件已卸载时, 只调用一次
unmounted() {},
});
这个API用来加载异步组件,异步组件的好处我想大家也知道,就是用不到他就不加载,用到了才会加载,这大大降低了首屏加载时间,是优化的重要手段
defineAysncCompoment需配合vue3的内置全局组件Suspense使用,需要用Suspense包住异步组件
const AsyncPopup = defineAsyncComponent({
loader: () => import("./LoginPopup.vue"),
// 加载异步组件时要使用的组件
loadingComponent: LoadingComponent,
// 加载失败时要使用的组件
errorComponent: ErrorComponent,
// 在显示 loadingComponent 之前的延迟 | 默认值:200(单位 ms)
delay: 1000,
// 如果提供了 timeout ,并且加载组件的时间超过了设定值,将显示错误组件
// 默认值:Infinity(即永不超时,单位 ms)
timeout: 3000
})
// 使用时,可控制显隐
<Suspense v-if="show" >
<AsyncPopup />
</Suspense>
我们要知道Hooks的好处,其实它就是一个函数,好处有:
就比如刚刚我们修改user的那个例子,假如很多页面都需要这个逻辑,那岂不是每个地方都需要写一遍?
所以最好的办法就是把这部分逻辑封装成Hook
注意:规范点,hook都要以use开头
// useUser.ts
import { reactive, computed } from 'vue'
const enum Name {
CN = '林三心',
EN = 'Sunshine_Lin',
}
const enum Gender {
MAN = '男',
WOMAN = '女',
}
const useUser = () => {
const user = reactive({
name: Name.CN,
gender: Gender.MAN,
})
const userText = computed(() => `我叫${user.name},我是${user.gender}的`)
const switchGender = () => {
user.gender = user.gender === Gender.MAN ? Gender.WOMAN : Gender.MAN
}
return {
switchGender,
userText,
}
}
export default useUser
现在我们可以在页面中使用这个自定义hook
<script setup lang="ts">
import useUser from './useUser'
const {
userText,
switchGender
} = useUser()
</script>
<template>
<div @click="switchGender">
{{ userText }}
</div>
</template>
这是vue3提供给我们的两个路由hook
<script setup>
import { useRouter } from 'vue-router'
const router = useRouter()
function onClick() {
// 跳转
router.push({
path: '/about',
query: {
msg: 'hello vue3!'
}
})
}
</script>
<script setup>
import { useRoute } from 'vue-router'
const route = useRoute()
console.log(route.query.msg)
// hello vue3!
</script>
介绍一些vue3内置的组件
回想一下,在vue2中,只允许存在一个根节点,但是在vue3中,允许存在多个根节点,其实是因为vue3做了处理:
vue3检测到你有多个根节点时,会为你最外层补上一个Fragment,所以其实根节点还是一个
vue3支持多个根节点,大家要记得哦~
<template>
<div>哈哈</div>
<div>嘻嘻</div>
</template>
Teleport是传送门组件,他可以将你的组件,挂载到任意一个节点之下,只要你指定一个选择器,可以是id、class
例如:将Dialog组件挂载到id为app的节点下
// Dialog.vue
<template>
<div>我是林三心我是林三心我是林三心我是林
三心我是林三心我是林三心我是林三心我是
林三心我是林三心我是林三心我是林三心
我是林三心</div>
</template>
<script setup lang="ts">
import Dialog from './Dialog.vue'
</script>
<template>
// 将Dialog组件挂载到id为app的节点下
<Teleport to="#app">
<Dialog />
</Teleport>
</template>
我们可以看到,Dialog组件被挂到了id为app的节点下
原文来自:前端之神,作者:林三心
Kotlin是JetBrains推出的一款语言, 相比Java有更简洁的语法, 能编译为Java Class, 也能编译为JavaScript Node.js则是可以运行在服务端的JavaScript, 这里把二者结合, 搭建一个用Kotlin编写的服务端应用
网站优化的关键在于制定和实施完整的网站优化方案,若想要做好网站优化就必须要制定出一套适合自己的、可执行的网站优化方案。下面我们就来讲一讲如何制定一套完整的网站优化方案,希望大家能够从中获益。
常见信息;创建新仓库;Git 的配置文件是 .gitconfig,可以放在用户的主目录(全局配置)下或项目目录下(项目配置) ;添加删除文件;代码提交
本教程是针对AutoCAD2019推出的视频教程,总共25小时,57节视频教程,从一份标准图纸各个要素(轮廓线、尺寸线、辅助线、公差粗糙度、明细表技术要求)逐一讲解。学习者要非常有耐心,认真学完全部课程
第一阶段HTML+CSS:JavaScript基础、JS基本特效、JS高级特征、JQuery;HTML5和移动Web开发:跨终端WEB和主流设备简介、视口、流式布局、弹性盒子、rem、移动终端JavaScript事件
选项卡是前端常见的基本功能,它是用多个标签页来区分不同内容,通过选择标签快速切换内容。学习本教程之前,读者需要具备html和css技能,同时需要有简单的javascript基础。
今天,我将跟大家分享网易云课堂的一些编程视频教程,大家可以根据自己的情况,进行合理安排学习。现在,我们就一起来看看这些教程吧。从零玩转JavaScript+ES678精讲,Vue3+Nuxt3实战在线教育SSR网站
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!