v-if
与v-for
优先级2.x版本中 v-for
> v-if
3.x版本中 v-for
< v-if
v-for
中的ref
数组2.x版本中 会自动把ref填充内容
3.x版本中 需要手动添加
<ur>
<li v-for='item in 5' :key='item' :ref="setItemRef">{{ item }}li>
ul>
<script>
methods: {
setItemRef(el){
this.arr.push(el)
}
}
script>
2.x版本中 访问前实例的子组件
3.x版本中 在3.x中,$children 已被移除,且不再支持。可以用以下方式所代替:
设置:
如果需要解构 prop,可以在 setup
函数中使用 toRefs
函数来完成此操作:
<script setup>
import { reactive, toRefs } from 'vue'
let obj = reactive({
name: '张三',
age: 20
})
let target = toRefs(obj)
target.name.value = '李四'
console.log(`姓名:${target.name},年龄:${target.age}`) //控制台 姓名:李四,年龄:20
script>
接受一个 getter 函数,并根据 getter 的返回值返回一个不可变的响应式 ref 对象。
const count = ref(1)
const plusOne = computed(() => count.value + 1)
console.log(plusOne.value) // 2
plusOne.value++ // 错误
或者,接受一个具有 get
和 set
函数的对象,用来创建可写的 ref 对象。
const count = ref(1)
const plusOne = computed({
get: () => count.value + 1,
set: val => {
count.value = val - 1
}
})
plusOne.value = 1
console.log(count.value) // 0
let obj = reactive({
name: '张三',
age: '20',
sex: computed(() => {
return '男'
})
})
2.x版本中,watch的使用:
watch: {
obj: {
handler(newVal, oldVal) {
console.log(newVal, oldVal)
},
immediate: true // 当刷新页面时会立即执行一次handler函数
deep: true // 深度侦听
}
}
3.x版本中,watch的使用:
let msg = ref('Hello vue!')
watch(msg, (newVal, oldVal) => {
console.log(newVal, oldVal)
},{
immediate: true,
})
return {
msg
}
let msg = ref('Hello vue!')
let str= ref('Hello world!')
let obj = reactive({
name: '张三',
hobby: ['篮球','游泳','射击']
})
watch([msg, str, ()=>obj.hobby], (newVal, oldVal) => {
console.log(newVal, oldVal)
},{
immediate: true,
})
return {
msg,str
}
let obj = reactive({
name: '张三',
hobby: ['篮球','游泳','射击']
})
watch(()=>obj.hobby, (newVal, oldVal) => {
console.log(newVal, oldVal)
})
watchEffect
立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数。
let msg = ref('Hello vue!')
watchEffect(() => {
console.log(msg.value)
})
Vue2.x | Vue3.x |
---|---|
this.$route | useRoute |
this.$router | useRouter |
导航守卫
动态路由
父组件:
<template>
<List :msg='msg' />
template>
<script setup>
import List from '@/components/List'
let msg = ref('父传子')
script>
子组件:(defineProps自定义属性)
<template>
<div>这是子组件 ===> {{ msg }}div>
template>
<script setup>
defineProps({
msg:{
type: String,
default: ''
}
})
script>
子组件:
<template>
<div>这是子组件 ===> {{ num }}div>
template>
<script setup>
let num = ref(200)
const emit = defineEmits(['getData'])
const backData = () => {
emits('getData', num)
}
script>
父组件:
<template>
<List @getData='getData' />
template>
<script setup>
import List from '@/components/List'
const getData = val => {
console.log(val)
}
script>
父组件:
<template>
<List v-model:num="num" />
template>
<script setup>
import List from '@/components/List'
const getData = val => {
console.log(val)
}
script>
子组件:
<template>
<div>这是子组件 ===> {{ num }}div>
<button @click='btn'>按钮button>
template>
<script setup>
const props = defineProps({
num:{
type: Number,
default: 0
}
})
const emit = defineEmits(['update:num'])
const btn = ()=>{
emit('update:num', 200)
}
script>
父组件:
<template>
<A @fn='changeFn'/>
<B/>
template>
<script>
import 'A' from '@/components/A'
import 'B' from '@/components/B'
let str = ref('')
let changeFn = val => {
str.value = val.value
}
script>
兄弟组件A(发送数据)
<template>
<h1>组件Ah1>
<button @click='btn'>按钮button>
template>
<script setup>
let str = ref('组件A中的数据')
const emit = defineEmits(['fn'])
const btn = () => {
emit('fn', str)
}
script>
兄弟组件B(接收数据)
<template>
<h1>组件B ===> {{ str }}h1>
<button @click='btn'>按钮button>
template>
<script setup>
const props = defineProps({
str: {
type: String,
default: '123'
}
})
script>
兄弟组件使用mitt传值
下载mitt
npm i mitt -S
配置文件(Bus.js)
import mitt from 'mitt'
const emmiter = mitt()
export default emmiter
兄弟组件A(发送数据)
<template>
<h1>A组件h1>
<button @click='btn'>按钮button>
template>
<script setup>
import emitter from '@/utils/Bus.js'
let str = ref('A组件传数据')
const btn = () => {
emitter.emit('fn', str)
}
script>
兄弟组件B(接收数据)
<template>
<h1>B组件 ===> {{ msg }}h1>
template>
<script setup>
import emitter from '@/utils/Bus.js'
let msg = ref('')
onBeforeMount(() => {
emitter.on('fn', e => {
msg.value = e.value
})
})
script>
选项式 API | Hook inside setup |
---|---|
beforeCreate | Not needed* |
created | Not needed* |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeUpdate | onBeforeUpdate |
updated | onUpdated |
beforeUnmount | onBeforeUnmount |
unmounted | onUnmounted |
errorCaptured | onErrorCaptured |
renderTracked | onRenderTracked |
renderTriggered | onRenderTriggered |
activated | onActivated |
deactivated | onDeactivated |
父组件:
<template>
<A>
<template>这是xxxx数据template>
<template>这是yyyy数据template>
A>
template>
子组件:
<template>
<header>
<div>头部div>
<slot>slot>
header>
<footer>
<div>底部div>
<slot>slot>
footer>
template>
父组件:
<template>
<A>
<template #xxx>这是xxxx数据template>
<template #yyy>这是yyyy数据template>
A>
template>
子组件:
<template>
<header>
<div>头部div>
<slot name='xxx'>slot>
header>
<footer>
<div>底部div>
<slot name='yyy'>slot>
footer>
template>
父组件:
<template>
<A>
<template #default='{data}'>
{{ data.name }} --->{{ data.age }}
template>
A>
template>
子组件:
<template>
<div v-for='item in list' :key='item.id'>
<slot :data='item'>slot>
div>
template>
<script setup>
let list = ref({
{id: 1, name: '张三', age: 20},
{id: 2, name: '李四', age: 25},
{id: 3, name: '王五', age: 20},
{id: 4, name: '赵六', age: 18}
})
script>
通过数据进行切换
<template>
<template #[hw]>Hello world!template>
template>
<script setup>
let hw = ref('hw')
script>
传送给id选择器
传递给class选择器
传递给标签选择器
传送之前,必须要声明出对应的选择器
<keep-alive>
<component :is="currentTabComponent">component>
keep-alive>
组件按需引入:当用户访问到了组件再去加载该组件
下载vueuse插件npm i @vueuse/core -S
<template>
<div ref='target'>
<C v-if='targetIsVisible'>C>
div>
template>
<script setup>
import { useIntersectionObserver } from '@vueuse/core'
const C = defineAsyncComponent(() =>
import('@/components/C.vue')
)
const target = ref(null)
const targetIsVisible = ref(false)
const { stop } = useIntersectionObserver(
target,
([{ isIntersecting }] => {
if( isIntersecting ) {
targetIsVisible.value = isIntersecting
}
})
)
script>
异步组件在默认情况下是可挂起的。这意味着如果它在父链中有一个
,它将被视为该
的异步依赖。在这种情况下,加载状态将由
控制,组件自身的加载、错误、延迟和超时选项都将被忽略。通过在其选项中指定
suspensible: false
,异步组件可以退出Suspense
控制,并始终控制自己的加载状态
<template>
<Suspense>
<template #default><A/>template>
<template #fallback>加载中template>
Suspense>
template>
<script setup>
const A = defineAsyncComponent(() =>
import('@/components/A.vue')
)
script>
npm run build打包完成后,异步组件有单独的js文件,是从主体js包中分离出来的。
是什么?来分发Vue组件中的可复用功能
mixin.js
import { ref } from 'vue'
export default function() {
let num = ref(1)
let fav = ref(false)
let favBtn = () => {
num.value += 1
fav.value = true
setTimeout(() => {
fav.value = false
},2000)
}
return {num, fav, favBtn}
}
组件A:
<template>
<div>
<h1>A组件h1>
{{ num }}
<button @click='favBtn'>{{ fav ? '收藏中...' : '收藏' }}button>
div>
template>
<script setup>
import mixin from '@/mixin/mixin.js'
let {num, fav, favBtn} = mixin()
script>
组件B:
<template>
<div>
<h1>B组件h1>
{{ num }}
<button @click='favBtn'>{{ fav ? '收藏中...' : '收藏' }}button>
div>
template>
<script setup>
import mixin from '@/mixin/mixin.js'
let {num, fav, favBtn} = mixin()
script>
mixin.js
export const fav = {
data() {
return {
num: 1
}
},
methods: {
favBtn(params) {
this.num += params
}
}
}
A组件:
<template>
<div>
<h1>A组件h1>
{{ num }}
<button @click='favBtn(2)'>按钮button>
div>
template>
<script>
import mixin from '@/mixin/mixin.js'
export const fav = {
data() {
return {
str: 'Hello vue!'
}
},
mixin: [fav]
}
script>
B组件:
<template>
<div>
<h1>B组件h1>
{{ num }}
<button @click='favBtn(1)'>按钮button>
div>
template>
<script>
import mixin from '@/mixin/mixin.js'
export const fav = {
data() {
return {
str: 'Hello vue!'
}
},
mixin: [fav]
}
script>
通常,当我们需要从父组件向子组件传递数据时,我们使用 props。想象一下这样的结构:有一些深度嵌套的组件,而深层的子组件只需要父组件的部分内容。在这种情况下,如果仍然将 prop 沿着组件链逐级传递下去,可能会很麻烦。
对于这种情况,我们可以使用一对
provide
和inject
。无论组件层次结构有多深,父组件都可以作为其所有子组件的依赖提供者。这个特性有两个部分:父组件有一个provide
选项来提供数据,子组件有一个inject
选项来开始使用这些数据。
provide:
<script setup>
provide('changeNum', num)
script>
inject:
<template>
<h1>{{num}}h1>
template>
<script setup>
const num = inject('changeNum')
script>