此篇博客为之前使用vue-elementui-webpack-vuecli进行的项目相关知识的总结,即个人的项目实战学习笔记,经查阅相关资料以及自我总结得出此篇文章。(如有错误之处,请大佬指出,共同学习研究)
项目源码地址:点击链接
图片来自:Vue.js生命周期
在数据观测和初始化事件还未开始
完成数据观测,属性和方法的运算,初始化事件,$el属性还没有显示出来
在挂载开始之前被调用,相关的render函数首次被调用。实例已完成以下的配置:编译模板,把data里面的数据和模板生成html。注意此时还没有挂载html到页面上。
在el 被新创建的
vm.$el
替换,并挂载到实例上去之后调用。实例已完成以下的配置:用上面编译好的html内容替换el属性指向的DOM对象。完成模板中的html渲染到html页面中。此过程中进行ajax交互。
在数据更新之前调用,发生在虚拟DOM重新渲染和打补丁之前。可以在该钩子中进一步地更改状态,不会触发附加的重渲染过程。
在由于数据更改导致的虚拟DOM重新渲染和打补丁之后调用。调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作。然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。该钩子在服务器端渲染期间不被调用。
在实例销毁之前调用。实例仍然完全可用。
在实例销毁之后调用。调用后,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务器端渲染期间不被调用。
答: Vue 实例从创建到销毁的过程,就是生命周期。从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、销毁等一系列过程,称之为 Vue 的生命周期。
答:它的生命周期中有多个事件钩子,让我们在控制整个Vue实例的过程时更容易形成好的逻辑。
答:它可以总共分为8个阶段:创建前/后, 载入前/后,更新前/后,销毁前/销毁后。
答:会触发 下面这几个beforeCreate, created, beforeMount, mounted 。
答:DOM 渲染在 mounted 中就已经完成了。
视图(
View
)可以独立于Model
变化和修改,一个ViewModel
可以绑定到不同的"View
"上,当View
变化的时候Model
可以不变,当Model变化的时候View
也可以不变。
你可以把一些视图逻辑放在一个
ViewModel
里面,让很多view
重用这段视图逻辑。
开发人员可以专注于业务逻辑和数据的开发(
ViewModel
),设计人员可以专注于页面设计。
界面素来是比较难于测试的,而现在测试可以针对
ViewModel
来写。
父组件传给子组件:子组件通过props
方法接受数据;
子组件传给父组件:$emit
方法传递参数
eventBus
,就是创建一个事件中心,相当于中转站,可以用它来传递事件和接收事件。项目比较小时,用这个比较合适。
声明式(标签跳转) 编程式( js跳转)
html部分代码
<el-table-column label="创建时间" prop="add_time" width="140px">
<template slot-scope="scope">
{{scope.row.add_time | dateFormat}}
template>
el-table-column>
在此次项目中,html页面中使用element-ui组件和template进行操作,使用|
进行调用过滤器。其中add_time为后台进行传递。
data() {
return {
// 查询参数对象
queryInfo: {
query: '',
pagenum: 1,
pagesize: 10
},
// 商品列表 从后台获得
goodslist: [],
total: 0
}
}
在全局进行过滤器的定义
Vue.filter('dateFormat', function (originVal) {
const dt = new Date(originVal) //获取数据
const y = dt.getFullYear()
const m = (dt.getMonth() + 1 + '').padStart(2, '0') //不足两位,进行补0
const d = (dt.getDate() + '').padStart(2, '0')
const hh = (dt.getHours() + '').padStart(2, '0')
const mm = (dt.getMinutes() + '').padStart(2, '0')
const ss = (dt.getSeconds() + '').padStart(2, '0')
return `${y}-${m}-${d} ${hh}:${mm}:${ss}` //返回结果
})
过滤器接收表达式的值 (scope.row.add_time
) 作为第一个参数。dateFormat
过滤器将会收到 msg的值作为第一个参数。
当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。key的作用主要是为了高效的更新虚拟DOM。
vue-router路由,通俗来讲主要是来实现页面的跳转,通过设置不同的path,向服务器发送的不同的请求,获取不同的资源。
主要组件:router-view
、router-link
在此次项目中,由于使用的是全局定义。
摘取部分(以goods文件夹目录下为例)
import Vue from 'vue'
import VueRouter from 'vue-router'
// import Cate from './components/goods/Cate.vue'
const Cate = () => import(/* webpackChunkName: "Cate_Params" */ './components/goods/Cate.vue')
// import Params from './components/goods/Params.vue'
const Params = () => import(/* webpackChunkName: "Cate_Params" */ './components/goods/Params.vue')
// import GoodsList from './components/goods/List.vue'
const GoodsList = () => import(/* webpackChunkName: "GoodsList_Add" */ './components/goods/List.vue')
// import Add from './components/goods/Add.vue'
const Add = () => import(/* webpackChunkName: "GoodsList_Add" */ './components/goods/Add.vue')
Vue.use(VueRouter)
const router = new VueRouter({
routes: [
{
path: '/',
redirect: '/login'
},
{
path: '/login',
component: Login
},
{
path: '/home',
component: Home,
redirect: '/welcome',
children: [
{
path: '/welcome',
component: Welcome
},
......
export default router
首页可以控制导航跳转,beforeEach
,afterEach
等,一般用于页面title的修改。一些需要登录才能调整页面的重定向功能。
beforeEach主要有3个参数to
,from
,next
:
to
:route
即将进入的目标路由对象,
from
:route
当前导航正要离开的路由
next
:function一定要调用该方法resolve
这个钩子。执行效果依赖next
方法的调用参数。可以控制网页的跳转。
全局的:beforeEach、beforeResolve、afterEach
路由的:beforeEnter
组件的:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave
例如,项目中使用到的:
// 挂载路由导航守卫
router.beforeEach((to, from, next) => {
// to 将要访问的路径
// from 代表从哪个路径跳转而来
// next 是一个函数,表示放行
// next() 放行 next('/login') 强制跳转
if (to.path === '/login' || to.path === '/') return next()
// 如果用户访问非登录路径,则判断有无登录凭证token
const loginToken = sessionStorage.getItem('token')
// 没有token,直接跳转登录页面
if (!loginToken) return next('/login')
// 有token,放行
next()
})
vue实现数据双向绑定主要是:采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()
来劫持各个属性的setter
,getter
,在数据变动时发布消息给订阅者,触发相应监听回调。当把一个普通 Javascript 对象传给 Vue 实例来作为它的 data 选项时,Vue 将遍历它的属性,用 Object.defineProperty
将它们转为getter/setter
。用户看不到 getter/setter
,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。
vue
的数据双向绑定 将MVVM作为数据绑定的入口,整合Observer
,Compile
和Watcher
三者,通过Observer
来监听自己的model
的数据变化,通过Compile
来解析编译模板指令(vue中是用来解析 {{}}),最终利用watcher
搭起observer
和Compile
之间的通信桥梁,达到数据变化 —>视图更新;视图交互变化(input
)—>数据model
变更双向绑定效果。
<body>
<div id="app">
<input type="text" id="txt">
<p id="show">p>
div>
body>
<script type="text/javascript">
var obj = {}
Object.defineProperty(obj, 'txt', {
get: function () {
return obj
},
set: function (newValue) {
document.getElementById('txt').value = newValue
document.getElementById('show').innerHTML = newValue
}
})
document.addEventListener('keyup', function (e) {
obj.txt = e.target.value
})
script>
在此项目中的实例:
html - demo:
<el-dialog title="添加用户信息" :visible.sync="addDialogVisible" width="50%" @close="addDialogClosed">
<el-form :model="addForm" :rules="addFormRules" ref="addFormRef" label-width="70px">
<el-form-item label="用户名" prop="username">
<el-input v-model="addForm.username">el-input>
el-form-item>
<el-form-item label="密码" prop="password">
<el-input v-model="addForm.password" type="password">el-input>
el-form-item>
<el-form-item label="邮箱" prop="email">
<el-input v-model="addForm.email">el-input>
el-form-item>
<el-form-item label="手机号" prop="mobile">
<el-input v-model="addForm.mobile">el-input>
el-form-item>
el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="addDialogVisible = false">取 消el-button>
<el-button type="primary" @click="addUser">确 定el-button>
span>
el-dialog>
model
绑定表单数据通过调用后台接口和数据库,获取数据(editForm
):
const { data: res } = await this.$http.get('users/' + id)
if (res.meta.status !== 200) {
return this.$message.error('查询用户信息失败!')
}
this.editForm = res.data //获取数据
prop
取表单数值如下代码:
<el-table-column label="姓名" prop="username">el-table-column>
<el-table-column label="邮箱" prop="email">el-table-column>
<el-table-column label="电话" prop="mobile">el-table-column>
<el-table-column label="角色" prop="role_name">el-table-column>
ref
进行后台API验证this.$refs.addFormRef.validate(async valid => {
// console.log(valid)
if (!valid) return
// 可以发起添加用户的网络请求
const { data: res } = await this.$http.post('users', this.addForm)
if (res.meta.status !== 201) {
this.$message.error('添加用户信息失败')
} else {
this.$message.success('添加用户信息成功')
}
// 隐藏添加用户的对话框
this.addDialogVisible = false
// 刷新用户列表
this.getUserList()
})
}
rules
进行表单内容验证项目中的rules
为addFormRules
,例如以下代码(其中checkMobile
,checkEmail
为自己编写的验证方法):
// 添加表单验证规则对象
addFormRules: {
username: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{
min: 3,
max: 10,
message: '用户名的长度在3~10个字符之间',
trigger: 'blur'
}
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{
min: 6,
max: 15,
message: '用户名的长度在6~15个字符之间',
trigger: 'blur'
}
],
email: [
{ required: true, message: '请输入邮箱', trigger: 'blur' },
{ validator: checkEmail, trigger: 'blur' }
],
mobile: [
{ required: true, message: '请输入手机号', trigger: 'blur' },
{ validator: checkMobile, trigger: 'blur' }
]
}
export default {
path: '',
name: '',
meta: { //元信息(非必填)
icon: '', //路由图标
title: '', //路由名称
light: '', //高亮显示那个路由name
show: true, //是否显示
},
redirect: {
name: '', //重定向,指向哪个路由的name
},
component: '', //当前路由时要显示的组件
children: [], //嵌套子路由
}
ajax
是最早出现发送后端请求的技术,属于原生js范畴,核心是使用XMLHttpRequest
对象,使用较多并有先后顺序的话,容易产生回调地狱。
fetch
号称可以代替ajax
的技术,是基于ES6中的Promise
对象设计的,参数和jQuery
中的ajax
类似,它并不是对ajax
进一步封装,它属于原生js范畴。没有使用XMLHttpRequest
对象。
axios
不是原生js,使用时需要对其进行安装,客户端和服务器端都可以使用,可以在请求和相应阶段进行拦截,基于Promise
对象。
在style标签中写入scoped即可 例如:
<style lang="less" scoped>style>
Vue面试中,经常会被问到的面试题/Vue知识点整理(来源:简书)
vue 248个知识点(面试题)为你保驾护航(来源:掘金)