这篇笔记用于自己复习,知识点很散,不适合别人看
Vue 基础
应用实例 const app = Vue.createApp(RootOption)
根组件选项 const RootOption = {}
根组件实例 vm = app.mount('#app')
组件选项:与根组件的配置选项相同
组件实例:每个组件都有一个组件实例,vm 通常代表组件实例
组件选项
inject
将 provide/inject 看做是长距离的 props
默认情况下,provide/inject 绑定并不是响应式的
props
单向下行绑定,父组件中更新 props 属性值,则子组件中的值自动更新,然后自动更新视图
不要在子组件中更改 props 属性值
prop 会在一个组件实例创建之前进行验证,所以实例的 property (如 data、computed 等) 在 default 或 validator 函数中是不可用的
当 prop 验证失败的时候,(开发环境构建版本的) Vue 将会产生一个控制台的警告。
data
data 是个函数,返回一个对象,该对象作为 vm.data.count 一样,可读写
vm.foo 动态添加的属性不具备响应式,该属性也不会保存在 vm.data.foo undefined
相同组件的多个实例拥有各自不同的 $data 属性,类似对象的实例属性
computed
依赖的 data 发生更新,则 computed 自动更新,对应的视图自动更新
computed vs watch
这两个都可以根据一个属性的变化来改变另一个属性,大多数需要用到 computed,因为他可以缓存。
只有在某个属性改变之后需要进行异步操作或者开销较大的复杂操作的时候,需要使用 watch
methods
可以将 methods 方法作为事件的处理函数 v-on:click="increment"
可以从模板中直接调用 methods 中定义的方法 v-bind:title="getTitle()" {{ getMessage() }}
从模板中调用方法,如果方法访问了任何响应式数据,则将其作为渲染依赖项进行跟踪
从模板调用的方法不应该有任何副作用,比如更改数据或触发异步进程
methods 中的方法被相同组件的多个实例共享,类似对象的原型方法
setup
生命周期钩子
beforeCreated:已经通过 vm.$on()
为组件监听了所有事件,包括生命周期钩子
created:可以访问组件的所有注入属性以及响应式属性
beforeMounted: 已经将组件的模板字符串编译成了 render() 函数。
mounted: 组件的模板已经生成 DOM 并且插入到文档中了。
beforeUpdated: 响应式 data 已经发生了变化
updated: 组件的 DOM 视图已经发生了改变
beforeUnmounted: 已经调用了 vm.unmount()
unmounted: 组件 DOM 结构已经从文档中删除,组件响应式数据已经删除,组件事件监听器已经删除
组件实例属性
不管是哪种属性,都能够在该组件作用域的模板中直接访问
组件选项定义的属性
vm.count
内置属性
vm.attr
vm.on
动态添加的属性
vm 实例创建之后动态添加的属性不能够响应式
vm.foo = 100
vm.$data.foo //undefined
组件
全局注册
app.component('my-component', {})
局部注册
{
component: {
'my-component': {}
}
}
prop 特性
非 prop 特性
自定义特性
class
style
事件
都会传递到子组件的根元素上,class style 与根元素的原有 class style 合并到一起。
如果子组件根元素不支持该事件,则无事发生 element.addEventListener('no-suposed-event', function () {}),则不会触发任何监听器。
通过 inheritAttrs: false 配合 v-bind="attrs 包括 html特性、class、style、事件,与 vue2 不同,vue3 listens 属性了
自定义事件
emits: ['myEvent', 'click']
当在 emits 选项中定义了原生事件 (如 click) 时,将使用组件中的自定义事件替代原生事件侦听器。
凡是在子组件中 $emit() 的事件,最好在 emits 属性定义该事件
props属性验证失败,在开发模式下,只是在浏览器控制台警告,不影响程序执行
自定义事件的验证如果失败,在开发模式下,只是在浏览器控制台警告,不影响程序执行,不影响发送事件以及处理事件
v-model
默认情况下,组件上的 v-model 使用 modelValue 作为 prop 和 update:modelValue 作为事件
<MyComponent v-model="user"></MyComponent>
<MyComponent :modelValue="user" @update:modelValue="user=$event"></MyComponent>
可以给 v-model 添加参数,来改变默认值,使用 person 作为 prop,使用 update:person 作为事件
<MyComponent v-model:person="user"></MyComponent>
<MyComponent :person="user" @update:person="user=$event"></MyComponent>
ref
<input ref="foo">
<my-component ref="bar"></my-component>
this.refs.bar 指向子组件实例
Vue Router
路由
<router-link to="/"></router-link>
<router-view></router-view>
router-link 和 router-view 可以放在任何组件的任何位置,不是非要放在根组件里面,这两个甚至可以分开放在不同组件里。
router-link 本质上就是渲染 a 标签,放在哪个组件里都可以
router-view 就是渲染与 path 对应的组件,在哪渲染都可以
routes 是一个数组,每个元素是一个路由记录 RouteRecord 对象,定义路由与组件的映射关系
router 实例,定义了路由的方法
router 同时还是个插件,app.use(router) 可以插入全局实例属性 this.router
vue-router 最核心的工作就是编写 routes 映射关系
URL:
- '/foo/bar'
- { path: '/foo/bar', query: { id: 1 }, hash: '#c=1' }
- { name: 'user', params: { username: 'lee' } }
<router-link :to="URL"></router-link>
<router-link :to="URL" replace></router-link>
router.push(URL)
router.replace(URL)
router.go(n)
{ path: '/:username*', component: User },
{ path: '/:pid(\\d+)+', component: Post },
{ path: '/foo/:bar' },
{ path: '/foo/:bar/baz/:tar' },
{ path: '/foo/:bar+' }, // $route.params.bar []
{ path: '/foo/:bar*' }, // $route.params.bar []
{ path: '/foo/:bar?' },
{ path: '/foo/:bar(\\d+)+' },
{ path: '/foo/:bar(\\d+)*' },
{ path: '/foo/:bar(\\d+)?' }
嵌套路由
const routes = [
{
path: '/user/:username',
component: User,
children: [
{
path: 'profile',
component: UserProfile
},
{
path: 'posts',
component: UserPosts
},
{
path: '',
component: UserHome
}
]
}
]
顶级 <router-view> 匹配顶层 path 渲染,
组件 User 中的 <router-view> 匹配 User Route 的 children 中的 path 渲染
命名视图
一个路由映射一组组件 { path: '', components: {} }
为一个匹配路径提供多个 <router-view>,来渲染多个组件,通过 <router-view name=""> name 属性来指定对应的 <router-view> 应该渲染哪个组件
const routes = [
{
path: '/settings',
component: UserSettings,
children: [
{
path: 'email',
component: UserEmail
},
{
path: 'profile',
components: {
default: UserProfile,
helper: UserProfileView
}
}
]
}
]
重定向和别名
{ path: '/home', redirect: '/' }
重定向改变浏览器中的 url
重定向不需要映射 component
{ path: '/', alias: '/home', component: HomePage }
别名不改变浏览器中的 url
可以在嵌套路由里面提供别名
``` js
{
path: '/users',
component: UsersLayout,
children: [
// 为这 3 个 URL 呈现 UserList
// - /users
// - /users/list
// - /people
{ path: '', component: UserList, alias: ['/people', 'list'] },
],
}
如果路由有参数,绝对路径的别名必须带着参数
{
path: '/users/:id',
component: UsersByIdLayout,
children: [
// 为这 3 个 URL 呈现 UserDetails
// - /users/24
// - /users/24/profile
// - /24
{ path: 'profile', component: UserDetails, alias: ['/:id', ''] },
],
}
路由组件传参
{{ username }} 取代 {{ $route.params.username }}
{ path: '/user/:username', component: User, props: true }
props 为 true,route.params 将被设置为组件 User 的 props
props 可以是对象 { title: 'hello', id: 20 },传递静态 props 给组件 User
导航守卫
路由元信息
{ path: '', component: {}, meta: { foo: 100, bar: 'hello' } }
to.meta
to.matched.some(record => record.meta.foo === 100)
数据获取
导航完成后,在组件的 created 钩子函数中从服务器获取数据
导航完成前,在组件的 beforeRouteEnter 导航守卫中从服务器获取数据
Vue 动画
<Transition> 组件
<Transition> 是一个内置组件,这意味着它在任意别的组件中都可以被使用,无需注册。
<Transition> 仅支持单个元素或组件作为其插槽内容。如果内容是一个组件,这个组件必须仅有一个根元素。
在位于 <Transition></Transition> 之间的单个元素或组件进入或者离开 DOM 时候,会为该元素或组件应用动画
进入或离开可以由以下的条件之一触发:
- 由 v-if 所带来的条件渲染
- 由 v-show 所带来的条件显示
- 由特殊元素 <component :is=''> 切换的动态组件
当一个 <Transition> 组件中的元素被插入或移除时,会发生下面这些事情:
-
Vue 会自动检测目标元素是否应用了 CSS 过渡或动画。如果是,则一些 CSS 过渡 class 会在适当的时机被添加和移除。
-
如果有作为监听器的 JavaScript 钩子,这些钩子函数会在适当时机被调用。
-
如果没有探测到 CSS 过渡或动画、没有提供 JavaScript 钩子,那么 DOM 的插入、删除操作将在浏览器的下一个动画帧上执行。
自动添加 class
.v-enter-from
.v-enter-active
.v-enter-to
.v-leave-from
.v-leave-active
.v-leave-to
<Transition name="fade"></Transition>
.fade-enter-actvie
.fade-leave-active
...
可以配合 Animate.css 使用
<Transition
enter-active-class="animate__animated animate__tada"
leave-active-class="animate__animated animate__bounceOutRight"
>
<p v-if="show">hello</p>
</Transition>
CSS transition
.v-enter-active {
transition: all 0.3s ease-out;
}
.v-leave-active {
transition: all 0.8s cubic-bezier(1, 0.5, 0.8, 1);
}
.v-enter-from,
.v-leave-to {
transform: translateX(20px);
opacity: 0;
}
CSS animation
.v-enter-active {
animation: bounce-in 0.5s;
}
.v-leave-active {
animation: bounce-in 0.5s reverse;
}
@keyframes bounce-in {
0% {
transform: scale(0);
}
50% {
transform: scale(1.25);
}
100% {
transform: scale(1);
}
}
高级
<Transition type="animation"></Transition>
<Transition> 组件会通过监听过渡根元素上的第一个 transitionend 或者 animationend 事件来尝试自动判断过渡何时结束。如果根元素上同时使用了 css 过渡和 css 动画,则通过 type 指定监听哪个事件。duration 属性可以显式指定过渡的持续时间 (以毫秒为单位),而不是通过监听 transitionend 或者 animationend 来决定过渡何时结束。
多用 transform 和 opacity,不要使用 margin height 这类会影响 CSS 布局导致 DOM 重绘的属性。
JavaScript 钩子
<Transition
@before-enter="onBeforeEnter"
@enter="onEnter"
@after-enter="onAfterEnter"
@enter-cancelled="onEnterCancelled"
@before-leave="onBeforeLeave"
@leave="onLeave"
@after-leave="onAfterLeave"
@leave-cancelled="onLeaveCancelled"
>
<!-- ... -->
</Transition>
总结
<Transition
appear
type="animation|transition"
:css="false"
:duration="550"
mode="out-in"
name="fade"
enter-from-class=""
enter-active-class=""
enter-to-class=""
leave-from-class=""
leave-active-class=""
leave-to-class=""
@before-enter="onBeforeEnter"
@enter="onEnter"
@after-enter="onAfterEnter"
@enter-cancelled="onEnterCancelled"
@before-leave="onBeforeLeave"
@leave="onLeave"
@after-leave="onAfterLeave"
@leave-cancelled="onLeaveCancelled"
>
<p v-if="show">hello</p>
</Transition>
动态过渡
对 <Transition> 的 prop 的值进行动态绑定 <Transition :name="transitionName" :duration="transitionDuration">,根据当前组件的 data 的值来决定过渡行为
可重用
<template>
<!-- 包装内置的 Transition 组件 -->
<Transition
name="my-transition"
@enter="onEnter"
@leave="onLeave">
<slot></slot> <!-- 向内传递插槽内容 -->
</Transition>
</template>
<style>
/*
必要的 CSS...
注意:避免在这里使用 <style scoped>
因为那不会应用到插槽内容上
*/
</style>
<MyTransition>
<div v-if="show">Hello</div>
</MyTransition>
<TransitionGroup> 组件
<TransitionGroup> 是一个内置组件,设计用于呈现一个列表中的元素或组件的插入、移除和顺序改变的动画效果。
- 默认情况下,它不会渲染一个包装器元素。但你可以通过传入 tag prop 来指定一个元素作为包装器元素来渲染。
- 过渡模式 mode 属性在这里不可用,因为我们不再是在互斥的元素之间进行切换。
- 其中的元素总是必须有一个独一无二的 key attribute。
- CSS 过渡 class 会被应用在其中的每一个元素上,而不是这个组的容器上。
.v-move {
transition: all 0.5s ease;
}
网友评论