vue知识点总结
- 生命周期
- 数据绑定
- 指令事件
- 修饰符
- 路由
- 组件传值
- vuex
生命周期
beforeCreate:function(){ ... },
//实例创建前调用该函数,此时el和data均为undefined
created:function(){ ... },
//当一个实例被创建完毕执行该函数,此时el还是为undefined,一般在这里做数据的请求
beforeMount:function(){ ... },
//有el选项,挂载DOM节点前执行该函数,此时el有对应的DOM节点数据,但DOM结构的数据绑还没有执行;定若没有el选项,生命周期结束
mounted:function(){ ... },
//el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。如果 root 实例挂载了一个文档内元素,当 mounted 被调用时 vm.$el 也在文档内。一般在这里写自定义事件
beforeUpdate:function(){ .. },
//数据发现变化时先执行beforeUpdate,后执行updated,此时数据更新未完成。
updated:function(){ ... },
//数据发现变化时先执行beforeUpdate,后执行updated,此时数据更新完成。
beforeDestroy:function(){ ... },
//函数在实例销毁前调用,此时实例还可以调用
destroyed:function(){ ... },
//在实例销毁后调用,此时Vue实例所有东西会解除绑定,事件监听器会被移除,所有子实例都被销毁
生命周期也是面试常问的问题,它可以理解为前端的ViewModel,它包含它包含了页面中的业务逻辑处理、数据模型等,它也有自己的一系列的生命周期的函数钩子,辅助我们进行对整个Vue实例生成、编译、挂着、销毁等过程进行js控制。
数据绑定
vue使用的是MVVM思想,数据变化导致视图变化,视图变化导致数据变化
数据的双向绑定
数据与视图的绑定与同步,最终体现在对数据的读写处理过程中,也就是 Object.defineProperty() 定义的数据 set、get 函数中。
function defineReactive(obj, key, value){
var dep = new Dep();
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function reactGetter(){
if(Dep.target){
dep.depend();
}
return value;
},
set: function reactSetter(newVal){
if (value === newVal) {
return;
} else {
value = newVal;
//如果数据发生改变,则通知所有的 watcher(借助 dep.notify())
dep.notify();
}
}
})
}
在对数据进行读取时,如果当前有 Watcher(对数据的观察者,watcher 会负责将获取的新数据发送给视图),那将该 Watcher 绑定到当前的数据上(dep.depend(),dep 关联当前数据和所有的 watcher 的依赖关系),是一个检查并记录依赖的过程。而在对数据进行赋值时,如果数据发生改变,则通知所有的 watcher(借助 dep.notify())。这样,即便是我们手动改变了数据,框架也能够自动将数据同步到视图。
指令事件
- v-text 更新元素文本内容
- v-html 绑定html文本
- v-if 真假条件渲染元素
- v-show 切换元素display属性,效果和v-if相似,但原理不同
- v-else 与v-if一起使用来渲染元素
- v-for 循环渲染元素
- v-on 事件监听器
- v-bind 动态的绑定一个或多个特性,或一个组件的prop到表达式
- v-model 在表单元素里实现数据的双向绑定
- v-once 只渲染一次,不再动态变化
- 等等等
修饰符
事件修饰符
-
.prevent 修饰符告诉 v-on 指令对于触发的事件调用 event.preventDefault()
-
.stop 阻止事件冒泡
-
.prevent 阻止默认事件执行
-
.capture 事件采用捕获模式
-
.self 只有event.target是当前元素自身时才触发处理函数,即事件不是从内部元素触发
-
.once 事件只触发一次
按键修饰符 -
.enter
-
.tab
-
.delete 捕获 “删除” 和 “退格” 键
-
.esc
-
.space
-
.up
-
.down
-
.left
-
.right
-
.ctrl
-
.alt
-
.shift
-
.meta
路由
用 Vue.js + Vue Router 创建单页应用,是非常简单的。
基础路由
routes: [
{
path: '/login.html',
name: 'login',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "login" */ '@/views/login/index.vue') // 每个路由应该映射一个组件。
},
{
path: '*',
redirect: { path: '/404.html' }
},
{
path: '/404.html',
name: '404',
component: (resolve) => require(['@/views/404.vue'], resolve)
}
]
动态路由
const router = new VueRouter({
routes: [
// 动态路径参数 以冒号开头
{ path: '/user/:id', component: User }
]//携带自己想用的数据跳转,通过this.$route.params获取
})
嵌套路由
/user/foo/profile /user/foo/posts
+------------------+ +-----------------+
| User | | User |
| +--------------+ | | +-------------+ |
| | Profile | | +------------> | | Posts | |
| | | | | | | |
| +--------------+ | | +-------------+ |
+------------------+ +-----------------+
const router = new VueRouter({
routes: [
{ path: '/user/:id', component: User,
children: [
{
// 当 /user/:id/profile 匹配成功,
// UserProfile 会被渲染在 User 的 <router-view> 中
path: 'profile',
component: UserProfile
},
{
// 当 /user/:id/posts 匹配成功
// UserPosts 会被渲染在 User 的 <router-view> 中
path: 'posts',
component: UserPosts
}
]
}
]
})
编程式导航
const userId = '123'
router.push({ name: 'user', params: { userId }}) // -> /user/123
router.push({ path: `/user/${userId}` }) // -> /user/123
// 这里的 params 不生效
router.push({ path: '/user', params: { userId }}) // -> /user
命名路由
<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>等价于router.push({ name: 'user', params: { userId: 123 }})
导航守卫
const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
// ...
})
当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于 等待中。
每个守卫方法接收三个参数:
to: Route: 即将要进入的目标 路由对象
from: Route: 当前导航正要离开的路由
next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
next(false): 中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
next(’/’) 或者 next({ path: ‘/’ }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。你可以向 next 传递任意位置对象,且允许设置诸如 replace: true、name: ‘home’ 之类的选项以及任何用在 router-link 的 to prop 或 router.push 中的选项。
next(error): (2.4.0+) 如果传入 next 的参数是一个 Error 实例,则导航会被终止且该错误会被传递给 router.onError() 注册过的回调。
组件传值
父子传值
//子组件
<template>
<div id="container">
{{msg}}
</div>
</template>
<script>
export default {
data() {
return {};
},
props:{
msg: String
}
};
</script>
<style scoped>
#container{
color: red;
margin-top: 50px;
}
//父组件
<template>
<div id="container">
<input type="text" v-model="text" @change="dataChange">
<Child :msg="text"></Child>
</div>
</template>
<script>
import Child from "@/components/Child";
export default {
data() {
return {
text: "父组件的值"
};
},
methods: {
dataChange(data){
this.msg = data
}
},
components: {
Child
}
};
</script>
<style scoped>
子传父
//子组件代码
<template>
<div id="container">
<input type="text" v-model="msg">
<button @click="setData">传递到父组件</button>
</div>
</template>
<script>
export default {
data() {
return {
msg: "传递给父组件的值"
};
},
methods: {
setData() {
this.$emit("getData", this.msg);
}
}
};
</script>
<style scoped>
#container {
color: red;
margin-top: 50px;
}
//父组件代码
<template>
<div id="container">
<Child @getData="getData"></Child>
<p>{{msg}}</p>
</div>
</template>
<script>
import Child from "@/components/Child";
export default {
data() {
return {
msg: "父组件默认值"
};
},
methods: {
getData(data) {
this.msg = data;
}
},
components: {
Child
}
};
</script>
<style scoped>
</style>
子对子传
请使用状态管理vuex
vuex
Vuex 使用单一状态树,用一个对象就包含了全部的应用层级状态。至此它便作为一个“唯一数据源 (SSOT)”而存在。这也意味着,每个应用将仅仅包含一个 store 实例。单一状态树让我们能够直接地定位任一特定的状态片段,在调试的过程中也能轻易地取得整个当前应用状态的快照。
这段话说的是一个 Vuex 只能包含一个store(存储数据的库),这样你在访问数据的时候好找些。
import Vue from 'vue'
import Vuex from 'vuex'
import common from '@/api/common'//数据获取方法
import { getCookie, setCache, getCache } from '@/util'//这里是自定义方法
Vue.use(Vuex)
export default new Vuex.Store({
state: {
token: '',
bodyHeight: 0,
academyData: [],
dormData: [],
roleData: []
},//这里是需要监控的数据
mutations: {
resize (state, val) {
state.bodyHeight = val
},
setAcademy (state, val) {
state.academyData = val[0].children
setCache('academyData', val)
},
setDorm (state, val) {
state.dormData = val
},
setRole (state, val) {
state.roleData = val
setCache('roleData', val)
},
setToken (state) {
state.token = getCookie()
}
},//这里是更新数据的方法
actions: {//这里是触发mutations来改变数据
// 获取院校信息
async setAcademy ({commit}) {
if(!getCache('academyData')) {
try {
let res: any = await common.academyList()
if (res.code === 'SUCCESS') {
commit('setAcademy', res.data)
}
} catch (error) {
return error.status
}
} else {
let data: any = getCache('academyData')
commit('setAcademy', data)
}
},
// 获取宿舍楼
async setDorm ({commit}) {
if (!getCache('dorm_data')) {
try {
let res: any = await common.allDorm()
if (res.code === 'SUCCESS') {
commit('setDorm', res.data)
}
} catch (error) {
return error.status
}
} else {
let data: any = getCache('dorm_data')
commit('setDorm', data)
}
},
// 获取角色
async setRole ({commit}) {
let res: any
if (!getCache('roleData')) {
res = await common.role()
if (res.code === 'SUCCESS') {
commit('setRole', res.data)
}
} else {
let data: any = getCache('roleData')
commit('setRole', data)
}
},
},
})
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数
想在组件中改变store的数据你需要以相应的 type 调用 store.commit 方法:this.$store.commit(‘方法’,data);