Yovvis`s Blog

Yovvis`s Blog

Vue3朝花夕拾(一)

45
2024-05-05
Vue3朝花夕拾(一)

vue3

setup语法糖

  • setup()在beforeCreate()之前,因为setup中读取不到vue2的组合式API的内容但是vue2中的可以读到setup中的数据

ref和reactive

  • ref在ts中需要.value操作数据 如果是 a= ref() 然后让 a = b,失效

  • reactive无法定义基本类型,如果 a = reactive() 然后让 a = b,失效

上述两种都是破坏了响应式,a指向的地址都变了,但是页面上读取的是之前的所以,如果是ref定义的响应式对象,直接.value改变是可以的,

而reactive需要用 Object.assign(a,xxx)这样才可以生效

  • toRefs是把reactive中每个属性变成响应式对象
  • 泛型的使用 const data = reactive<a> 不要写成 const a:xxx =reactive()

computed

  • computed()返回的是一个响应式对象computedRef

  • computed()默认返回直接是返回他的get,如果需要修改需要手动定义

watch

四种类型可以被监视

  1. ref定义的数据
  2. reactive定义的数据
  3. getter函数
  4. 包含上面内容的数组

但是要注意

  • reactive定义的响应式对象(默认开始深层监视,且无法取消)

  • getter()或者就是()=>{return xxx}即返回了响应式对象的地址

  • 数组,需要合理用数组解构使用

ref属性

就是给节点打标识,获取dom解决id混乱问题

  • h5标签上就是直接获取
  • 组件上的ref属性,这样需要用 defineExpose 把子组件的data抛出去

props

  • defineProps可以只接受数据
defineProps(["aaa"])
  • defineProps接收数据 + 类型
defineProps<{aaa:type}>(["aaa"])
  • defineProps接收数据 + 类型 + 限制必要性 + 默认值(withDefaluts)
withDefaluts(defineProps<{aaa?:type}>(["aaa"]),{getter(默认值)})

生命周期(*)

Vue2

8个vue的生命周期钩子

时刻调用函数
创建创建前(beforeCreat) 创建后(created)
挂载挂载前(beforeMount) 挂载后(mounted)
更新更新前(beforeUpdate) 更新后(updated)
销毁销毁前(beforeDestory) 销毁后(destoryed)

v-if 进行销毁 v-show保留dom

Vue3

setup()在beforeCreated()和Created()之前

时刻调用函数
创建setup
挂载挂载前(onBeforeMount) 挂载完毕(onMounted)
更新更新前(onBeforeUpdate) 更新后(onUpdated)
卸载销毁前(onBeforeUnMount) 销毁后(onUnMounted)

v-if 进行销毁 v-show保留dom

父子生命周期

子先挂载——父挂载,即APP则是最后挂载

自定义hooks

  • hooks就是封装 data 和 method 对比的是 vue2 的mixin

  • 例如:useUser.ts中要 export 方法,且函数中要 return 暴露的 data 和 method

  • hooks里面可以写钩子

路由

工作模式

history:url不带 # 但是要配合服务端处理路径 否则 404

hash:兼容性好,带 # 不太美观,且在 SEO 优化叫差

<RouterLink to="/home" active-class="active"></RouterLink>
<RouterLink :to="{path:'/home'}" active-class="active"></RouterLink>
<RouterLink :to="{name:'zhuye'}" active-class="active"></RouterLink>

query参数

要用模板字符串

<RouterLink :to="{path:`'/news?id=${news.id}&name=${news.name}'}`" active-class="active"></RouterLink>
<RouterLink 
    :to="{
         path:'/news',
         query:{
         	id:xxx,
         	name:xxx
         }
}" active-class="active"></RouterLink>

params参数

不能用 path 只能用 name 且 to的参数要11对应或者+ ?

1、<RouterLink :to="{path:`'/news/detail/${xxx}/${xxx}'`}" active-class="active"></RouterLink>
{
	name:'xiang'
	path:'/news/detail/:id/:name?'
	component:Detail
}
2、<RouterLink 
    :to="{
         name:'xiang',
         params:{
         	id:xxx,
         	name:xxx
         }
}" active-class="active"></RouterLink>

路由props

  1. 第一种 所有params参数作为props
{
	name:'xiang'
	path:'/news/detail/:id/:name?'
	component:Detail
	props:true
}
对应的组件直接用defineProps(['id'])
  1. 第二种 自定义相传的参数(推荐query)
{
	name:'xiang'
	path:'/news/detail/:id/:name?'
	component:Detail
	props(route){
		return route.query/params
	}
}
  1. 第三种 对象写法
{
	name:'xiang'
	path:'/news/detail/:id/:name?'
	component:Detail
	props:{
		a:xxx
		b:xxx
	}
}

pinia

修改

  1. 符合直觉的修改

    store.sum ++ 生效

  2. 批量修改

    store.$patch(count:111,name:xxx)
    
  3. action

    store.add(value);
    
    store{
    	actions{
    		add(val){
    			this.num += val
    		}
    	}
    }
    

storeToRefs

const {sum,name,count} = countstore

这样就此丢失了响应式

不用toRefs原因是代价太大,把store里面所有的属性都转成了ref

subscrible

类似 watchEffect

store.$subscrible((mutated,state)=>{
	// mutated 本次修改信息,state本次修改的数据
	localStorage.setItem(key,JSON.stringify(obj))
})

组件通信

props

parent

<Child :car="car" :sendToy="getToyCallBack"></Child>
<scripts>
	function getToyCallBack(value)
</scripts>

child

<button @click="sendToy(xxx)"></button>
defineProps(['car','sendToy'])
<scripts>
	function getToyCallBack(value)
</scripts>

自定义事件

会使用到$event事件对象

<button @click="onClick">
    
</button>
<scripts>
    function onClick(x){
    	console.log(x)
    }
</scripts>

没有传参,这里的 x 就是 PointerEvent

parent

<Child @abc:"mmm" ></Child>
<scripts>
    function mmm(value){
    	console.log(value)
    }
</scripts>

child

<button @click="sendToy(xxx)"></button>
<scripts>
	const emit = defineEmits(['abc'])
    onMounted(()=>{
    	emit('abc',123)
    })
</scripts>

mitt

pubsub $bus mitt

父:接收数据 绑定事件(接收回调) .on

子:提供数据 触发事件 .emit

*在onUnMounted 解绑事件 .off

v-model

常用UI组件库

v-model的实质是

<input v-model = "username" />
<input :value = "username" @input="(<HTMLInputElement>$event.target).value" />

现在Vue3中如果是组件上实质上

<CusInput v-model="username" />
<CusInput :modelValue="username" @update:modelValue="$event" />

子组件
<scripts>
    <input :value="modelValue" @input="emit('update:modelValue',(<HTMLInputElement>$event.target).value)" >
	defineProps(['modelValue'])
    const emit = defineEmits(['update:modelValue'])
</scripts>

$attrs

适用于 祖——>孙,但是要借助父

收到的是props,没有收到的就是$attrs

$refs 和 $parents

$refs父传子

$parents 子传父

父:@Click=change($refs)

父:@Click=change($parents)

子组件主要还是要defineExpose(['xxx','xx'])

provide 和 inject

祖孙传递数据

祖:

provide("name",xxx)

孙:

const name = inject("name",xxx默认值)

插槽

默认插槽

要在子组件的地方放<slot></slot>

具名插槽

在组件标签上添加<template v-slot:"xxx"></template>

<slot name="xxx"></slot>

作用域插槽

在子组件中给slot

<slot :games:games></slot>

父组件中

<Games>
	<template v-slot="params">
		<ol>
            <li v-for="item in params.game" ></li>
        </ol>
    </template>
</Games>