Skip to content

基础

组件化和mvvm

MVVM

Model

模型,JavaScript对象

View

视图,文档模型Dom,即UI界面

ViewModel

Vue实例对象

![image.png](1.1.1 vue思想-1626877975992-50d53724-f631-4671-9a29-093028fdbd9a.png)

视图当中的Dom是可以监听到模型当中属性的变化, 反之,模型当中的属性更新也会对绑定到视图中的Dom做一个更新。

生命周期

  • 钩子函数(Hook)在Vue中是一种事件劫持机制。
  • 它会比定义的事件更早进行执行出来,而且还可以自定义去配置。
钩子描述
beforeCreate实例创建前状态,el和data均为undefined
created实例创建完成,el为undefined,data有数据
beforeMount挂载前状态,el为undefined,data有数据
mounted挂载完成,el和data均有对应数据
beforeUpdate数据更新前,data里面属性值改变(更新后的数据)
updated数据更新后,data里面属性值改变(更新后的数据)
beforeDestroy销毁前
destroyed销毁完成

![image.png](1.1.5 vue生命周期-1627114219891-3cca9a54-6a9f-4a47-a7ee-89caae4ca93c.png)
图片来自vue官网

嵌套组件的生命周期

子组件先插入,先完成patch及insert,父组件后插入

father
beforeCreate father created father beforeMount child beforeCreatechild createdchild beforeMountchild mounted father mounted

watch和computed的区别

自动调用相关的函数去实现数据的变动。

  • watch

类似于监听机制 + 事件机制

vue
watch: {
	fullName: function (val) {
		this.firstName + val
	}
}
  • computed

计算属性,是data对象里的数据属性使用方式是一致的。

vue
computed: {
	fullName: function () {
			return this.firstName + this.lastName
	}
}

watch和computed的使用

  • watch

用于观察和监听页面上的Vue实例。
如果说要在数据变化时,去进行异步操作,或者是进行大开销数据操作,就可以使用watch操作。

  • computed

当页面中某些数据依赖其他数据进行变动的时候,可以使用计算属性。

存在缓存问题,当computed里面不依赖其他数据的时候,computed里面的数据只会记录第一次记录的值。

组件

创建组件

组件注册

组件传值

  • props
  • $emit,$on
  • provide,inject
  • $children,$parent,$refs
  • $attrs,$listeners
  • slot
  • eventBus
  • Vuex

修饰符

事件修饰符

修饰符用法
.stop阻止事件冒泡
.capture捕获型事件执行
.once只出发一次
.self只在该元素本身执行(并非子元素)触发时触发回调
.prevent阻止默认事件,比如表单提交的页面重载
vue
<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>

<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>

<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>

<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>

<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div>

<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>

<!-- 点击事件将只会触发一次 -->
<a v-on:click.once="doThis"></a>

对于项目中,嵌套事件出现同时触发的情况,可以通过下面两种方式来解决:

  • 1.给父元素添加.self修饰符,也就是说只有自己触发的才有效:
  • 2.给子元素添加.stop修饰符,阻止事件冒泡,也就不会触发父元素的事件回调。

按键修饰符

在监听键盘事件时,我们经常需要检查详细的按键。
Vue 允许为v-on在监听键盘事件时添加按键修饰符:

vue
<!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` -->
<input v-on:keyup.enter="submit">

使用 keyCode attribute 也是允许的:

vue
<input v-on:keyup.13="submit">

为了在必要的情况下支持旧浏览器,Vue 提供了绝大多数常用的按键码的别名:

  • .enter
  • .tab
  • .delete (捕获“删除”和“退格”键)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

v-model修饰符

vue
<!-- 在“change”时而非“input”时更新 -->
<input v-model.lazy="msg">

<!-- 输入值转为数值类型 -->
<input v-model.number="age" type="number">

<!-- 过滤用户输入的首尾空白字符 -->
<input v-model.trim="msg">

Vue过度动画

Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果。包括以下工具:

  • 在 CSS 过渡和动画中自动应用 class

  • 可以配合使用第三方 CSS 动画库,如 Animate.css

  • 在过渡钩子函数中使用 JavaScript 直接操作 DOM

  • 可以配合使用第三方 JavaScript 动画库,如 Velocity.js

  • Vue在插入、更新或者删除Dom时,提供多种不同方式的应用过度效果。

  • Vue提供了内置的过度封装组件,该组件用于包裹要实现过度效果的组件。

过度的类名

在进入/离开的过渡中,会有 6 个 class 切换。

1、v-enter:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。

2、v-enter-active:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。
这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。

3、v-enter-to:2.1.8 版及以上定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时 v-enter 被移除),在过渡/动画完成之后移除。

4、v-leave:定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。

5、v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。
这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。

5、v-leave-to:2.1.8 版及以上定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 v-leave 被删除),在过渡/动画完成之后移除。

钩子函数

vue
<transition
  v-on:before-enter="beforeEnter"
  v-on:enter="enter"
  v-on:after-enter="afterEnter"
  v-on:enter-cancelled="enterCancelled"

  v-on:before-leave="beforeLeave"
  v-on:leave="leave"
  v-on:after-leave="afterLeave"
  v-on:leave-cancelled="leaveCancelled"
>
  <!-- ... -->
</transition>

这些钩子函数可以结合 CSS transitions/animations 使用,也可以单独使用。

当只用 JavaScript 过渡的时候,enterleave 中必须使用 done 进行回调。否则,它们将被同步调用,过渡会立即完成。

推荐对于仅使用 JavaScript 过渡的元素添加 v-bind:css="false",Vue 会跳过 CSS 的检测。这也可以避免过渡过程中 CSS 的影响。

路由

Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。包含的功能有:

  • 嵌套的路由/视图表
  • 模块化的、基于组件的路由配置
  • 路由参数、查询、通配符
  • 基于 Vue.js 过渡系统的视图过渡效果
  • 细粒度的导航控制
  • 带有自动激活的 CSS class 的链接
  • HTML5 历史模式或 hash 模式,在 IE9 中自动降级
  • 自定义的滚动条行为
js
const User = {
    // 获取参数
    template: '<div>User {{$route.params.id}}</div>'
}

const router = new VueRouter({
    routes: [
        // 动态路径参数 以冒号开头
        {path: '/user/:id', component: User}
    ]
})

路由传参

  • $route.params
vue
  { path: '/user/:id', component: User }
  • $route.query
vue
router.push({ path: 'register', query: { plan: 'private' }})

模式

js
const router = new VueRouter({
    mode: 'hash', // history
    routes: [
        // ...
    ]
})
  • hash

vue-router 默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。

  • history

如果不想要很丑的 hash,我们可以用路由的 history 模式,这种模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面。

需要服务端配置

nginx
location / {
    try_files $uri $uri/ /index.html;
}

编程式导航

除了使用 <router-link> 创建 a 标签来定义导航链接,我们还可以借助 router 的实例方法,通过编写代码来实现。

router.push(location, onComplete?, onAbort?)

声明式编程式
<router-link :to="...">router.replace(...)
vue
// 字符串
router.push('home')

// 对象
router.push({ path: 'home' })

// 命名的路由
router.push({ name: 'user', params: { userId: '123' }})

// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})

router.replace(location, onComplete?, onAbort?)

声明式编程式
<router-link :to="..." replace>router.replace(...)
vue
// 跟 router.push 很像,唯一的不同就是,它不会向 history 添加新记录,
// 而是跟它的方法名一样 —— 替换掉当前的 history 记录。
router.replace(location, onComplete?, onAbort?)

// 在浏览器记录中前进一步,等同于 history.forward()
router.go(1)

// 后退一步记录,等同于 history.back()
router.go(-1)

router.go(n)

vue
// 前进 3 步记录
router.go(3)

路由守卫

全局守卫

前置守卫

vue
router.beforeEach((to, from, next) => {
    if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
    else next()
})

后置守卫

js
router.afterEach((to, from) => {
    // ...
})

路由独享的守卫

js
const router = new VueRouter({
    routes: [
        {
            path: '/foo',
            component: Foo,
            beforeEnter: (to, from, next) => {
                // ...
            }
        }
    ]
})

这些守卫与全局前置守卫的方法参数是一样的。

组件内的守卫

最后,你可以在路由组件内直接定义以下路由导航守卫:

  • beforeRouteEnter
  • beforeRouteUpdate (2.2 新增)
  • beforeRouteLeave
js
const Foo = {
    template: `...`,
    beforeRouteEnter(to, from, next) {
        // 在渲染该组件的对应路由被 confirm 前调用
        // 不!能!获取组件实例 `this`
        // 因为当守卫执行前,组件实例还没被创建
    },
    beforeRouteUpdate(to, from, next) {
        // 在当前路由改变,但是该组件被复用时调用
        // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
        // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
        // 可以访问组件实例 `this`
    },
    beforeRouteLeave(to, from, next) {
        // 导航离开该组件的对应路由时调用
        // 可以访问组件实例 `this`
    }
}

Vuex介绍

image.png

提供状态管理

提供组件通信

使用

Module

Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:

js
const moduleA = {
    namespaced: true, // 命名空间
    state: {...},
    mutations: {...},
    actions: {...},
    getters: {...}
}

const moduleB = {
    state: {...},
    mutations: {...},
    actions: {...}
}

const store = new Vuex.Store({
    modules: {
        a: moduleA,
        b: moduleB
    }
})

store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态

mapState

vue
import { mapState } from 'vuex';
computed: {
    ...mapState('router', [
        'routers'
    ])
},

mapActions

vue
import { mapActions } from "vuex";

methods: { 
    ...mapActions('router', [
        'setRouters'
    ]),
},