1. 什么是单向绑定?什么是双向绑定?
- 单向绑定:修改data中初始化的数据,则Vue管理的页面的模板中的数据随之发生改动,这就叫单向绑定,也被称之为数据实现了可响应式,大虎子表达式和指令语法中的指令都支持单向绑定(数据可响应式)
- 双向绑定:修改Vue管理的模板中的数据,则data初始化的值随之发生改动,这就叫双向绑定,v-model天生支持双向绑定,其它数据如果想支持双向绑定则必须使用计算属性
2. 什么MVVM思想
MVVM主打口号: 数据驱动视图!
- 根据技术的特点将其分为三层
- M:model(模型层):就是指data中封装的各种数据
- V:view(视图层):就是指页面的模板
- VM:viewmodel(视图模型):就是指我们创建的Vue实例
- Vue提供了一种MVVM绑定思想,当我们修改M层中的数据时,通过VM层可以同时修改绑定在V层上的数据(单向绑定,数据的可响应式),当我们修改V层中的数据时,则通过VM层可以同时修改M层中的数据(双向绑定)
- 如下图:
3. 在Vue2中函数 计算属性 侦听器的不同,使用场合?
- 函数
- 多绑定激发事件,也可以绑定v-model直接调用,或者调用在大胡子表达式中,只有单向绑定功能无法实现双向绑定,函数没有缓存机制,只要被调用不管数据是否发生更改都会执行,注意平时我们如果绑定事件,没有参数,则函数没有括号 @click=“demo”
- 计算属性
- 依赖现有的属性(初始化的值)通过计算返回一个新的属性,这个属性是最终计算得来的也会被看做一个属性初始化在Vue实例根属性中,只要依赖的属性发生了更改,则计算属性重新执行,计算属性存在缓存机制,只要依赖属性没有发生变化,则不会再次执行,仅仅读取缓存中已经计算出的值,在页面中如果存在多个相同的计算属性,则效率大大高于多个相同的函数,计算属性可以同时支持单双向绑定功能,getter函数代表单向,setter函数代表双向功能
- 侦听器
- 一般不考虑单双向绑定问题,用来侦听某个值的变换,只要这个值发生更改,则侦听器执行,如果设置了immediate属性,则可以立即执行侦听器,侦听器默认只能侦听基本数据类型,如果要侦听复杂类型,则必须添加 deep:true 开启深度侦听功能
- 计算属性能做的事,侦听器都能做,侦听器能做的事,计算属性不一定能做,由于计算属性在书写单向绑定时必须书写return,所以无法书写异步代码
4. Vue如何进行样式渲染?
- :class=“test1” :class=“初始化的值”
- :class=“{box2:flag2,box3:flag3}” :class=“{类名:初始化的值,类名:初始化的值…}”
- :class=“[‘box4’,‘box5’]” :class=“[类名1,类名2]”
- :style=“{backgroundColor:val1,color:val2}” 行内式 :style=“{样式名:绑定的值,样式名:绑定的值}”
5. Vue条件渲染中 v-if与v-show的区别
- v-if:如果后面绑定的值是真值,则元素显示,如果是假值,则底层不渲染,页面不显示可以取反,由于切换时会导致元素底层的切换,所以一般适用于切换不频繁的场合,因为切换时消耗较大,另外v-if还可以搭配v-else-if 与 v-else使用,通过template标签可以实现复杂逻辑的流程控制
- v-show:如果后面绑定的值是真值,则元素显示,如果是假值,则底层依然渲染,页面不显示,只不过是添加了一个行内式 display:none; 来隐藏元素,可以取反,初始载入消耗较大,之后切换消耗较少,适用于切换频繁的场合,不能与 v-else-if v-else连用
6. Vue2中事件原型如何使用,如何获取元素节点
- 无值的情况下=> @click=‘方法’ | methods:{方法(event){…}}
- 有值的情况下=> @click=‘方法(name,$event)’ | methods:{方法(name,event){…}}
- event.target.value 取元素对象的值
7. 请列举Vue2中的常用事件修饰符
- @click.stop=“dothis” 防止事件冒泡 @click套@click会一起执行
- @click.prevent=“mySub” 去掉元素原本属性 src href action 链接跳转等
- @click.once=“count++” 点击执行一次
8. Vue2中如何实现对象的可响应式,数组的可响应式
- 对象:
- 增 this.$set(this.person,‘location’,‘璃月’)
- 删 this.$delete(this.person,‘name’)
- 数组
- 增 this.arr.push(‘敲代码’)
- 删 this.arr.splice(下标索引,1)
- 改 this.arr.splice(下标索引,1,替换成什么)
9. 请简单介绍下Vue2中的数据劫持 与 数据代理
- 数据劫持:data=>_data 实现可相应
- 数据代理:_data=>根属性 操作另一个对象来对这个对象进行读/写操作
10. Object.defineProperty()如何给一个对象添加属性值
-
/* 给对象添加属性 */ Object.defineProperty(person,'gender',{ value:'女', enumerable:true, /* 设置可枚举,默认是false */ writable:true, /* 设置可写,默认false */ configurable:true, /* 设置可删,默认false */ })
11. 请简述所有你用过的 指令元素
- v-bind = :value
- v-html
- v-model
- v-text
- v-on = @click
- v-show
- v-if
- v-for
- v-pre
- v-cloak
12. v-for会出现什么问题?
- 当使用v-for迭代数组时,如果出现从数组头部插入数据,并且插入之后 存在输入功能时,则有可能引入 diff算法中的就近策略导致的bug出现选择错误为了杜绝这个bug的出现,则绑定一个属性 key 这个key后面绑定的是主键
13. 请说出如何使用Vue创建自定义指令
- 全局自定义指令
局部自定义指令Vue.directive('etoak',{ /* 设置自定义指令的样式 */ bind(el){ /* el:element的简写就表示书写我们自定义指令得元素节点 */ el.style.backgroundColor = 'coral' }, /* 设置自定义指令的动作 */ inserted(el,binding){ /* binding:就表示我们得自定义指令 v-etoak binding.value:就表示我们自定义指令v-etoak后面绑定的值 el:同上 */ el.innerHTML = binding.value.toUpperCase() } })
new Vue({ data:{ content:'thisisetoak', }, /* 2:局部自定义指令,只能书写在某一个特定的Vue实例中,并且只能管理 这个实例管理的模板 */ directives:{ /* 指令名 */ focus:{ bind(el){ //渲染样式 }, inserted(el,binding){ //渲染动作 /* focus():强制激活获取焦点事件 */ el.focus() }, } } }).$mount('#app2')
14. 请说出如何使用Vue对数据进行过滤,应该注意什么?
- 过滤器当中不能使用this,this指向undefined,我们无法使用 this获取整个Vue实例中的数据
- 过滤器不能与v-model连用,因为不支持双向过滤器
- Vue3完全删除了过滤器
15. 组件传值
1,2,3 只能父类传值/方法给子类,子类只能调用不能修改,不能隔代传递
- 1.父传子 <子组件 :自定义属性=“传递的值” />
-
- props:[‘自定义属性’]
-
- props:{ 传递过来的值:数据类型 }
-
- 父组件传递的数据:{
type:数据类型,
required:是否指定数据类型,
default:是否设置默认值,
}
- 父组件传递的数据:{
-
- 2.子传父
- e m i t 子 父 传 值 : t h i s . emit子父传值: this. emit子父传值:this.emit(‘父组件的自定义事件’,要给父组件传递的值)
- this.$emit(‘etoak’,index)
- @etoak=“deleteHobby” 函数 deleteHobby(index){…}
- 3.插值语法
- slot 插槽 父子传值
<h1 class="page-header" slot="etoak1">{{ title1 }}</h1>
父组件
<子组件>
<要传递的元素 slot="插槽名">
</子组件>
子组件
插入到子组件
<slot name="插槽名" />
<slot name="etoak1"></slot>
16. vue生命周期?
- beforeCreate 刚创建vue实例
- created data和函数创建加载完毕,最早获取数据的时期 (发送异步请求)
(?el ?$mount ?template 选择你的模板 template: 有就覆盖以前定义的模板)
- beforeMount el模板加载完毕,但是页面没解析(插值语法和指令语法未解析)
- mounted 页面解析完成 (渲染ECharts图表)
- beforeUpdate data变才会执行,页面和data未同步 diff算法?变得数据变,
- updated 页面和data同步
- beforeDestroy vue实例马上就要销毁,但是还能用函数等,一般是资源释放 (组件释放资源)
- destroyed vue实例销毁 所有指令都被解绑
17. Vue中不能使用箭头函数的情况?
- 不应该使用箭头函数来定义一个生命周期方法
- 不应该使用箭头函数来定义
method
函数 - 不应该使用箭头函数来定义计算属性函数
- 不应该对
data
属性使用箭头函数 - 不应该使用箭头函数来定义
watcher
函数
原因:
箭头函数绑定了父级作用域的上下文,this 将不会按照期望指向 Vue 实例。也就是说,你不能使用this来访问你组件中的data数据以及method方法了。this将会指向undefined。
18. Promise的作用 (axios)? 异步发送
原因:vue 无异步
Promise是ES6中新增的一个对象,中文称之为承诺对象,它的诞生是为了解决异步回调地狱问题,也就是在书写异步时,外界根本无法获取内部异步成功或者失败,更无法获得服务器返回的数据,因此外界无法进行进一步的业务逻辑,例如 如果异步发送成功,外界获取服务器返回的值这种逻辑无法执行,如果异步嵌套过多,则代码永远无法跳出上一级
在使用Promise之后如果异步发送成功,则底层调用 resolve(response) 函数外界可以通过resolve执行then函数,在then中可以直接使用服务器返回的response,如果异步发送失败,则底层调用 reject(error),则外界可以通过catch函数知道内部出现错误,其中catch也可以获取error进行异常的解析,同时外界还可以直接调用 finally 不管异步成功失败与否都可以执行
- axios.get(url).then().catch().finally()
19. JOSN数据转换
- data=>json字符串 JSON.stringify(data)
- json字符串=>data JSON.parse(Json_data)
20. 持久化数据 (存网页中)
//把数据保存到浏览器中
- localStorage.setItem(KEY,data)
//从浏览器中获取数据
- let data = localStorage.getItem(KEY)
21. 普通组件和路由组件的区别?
- 普通组件和路由组件官方并没有明确划分
- 普通组件 在 components包下,路由组件在 views 包下
22. 为什么使用async函数?
/* 是 Promise的语法糖 */
async function run(){
/* 可以将异步操作按照同步的顺序执行 */
console.log(await one())
console.log(await two())
console.log(await three())
}
run()
23.什么是深拷贝与浅拷贝?有那些方法?
(用于:修改时弹窗数据回显通过表格页面获取,不经过id查询接口获取使用深拷贝数据)
浅拷贝: 拷贝后,依然指向原先的内存地址,只复制的是引用的地址,
(B拷贝A的数据,如果B改变,则A也会随之改变,也就所谓的你变我也变)
深拷贝:拷贝后开辟一块新的内存地址,是独立的个体,与原数据不在存在关联,
(A拷贝B的数据,如果B改变,则A不会有任何影响,也就是所谓的你变我不变)
基本数据类型:基本上都可以完成深拷贝
复杂数据类型:= 以下的方法才可以完成深拷贝
复杂数据类型嵌套: 只有JSON.parse(JSON.stringify())能完成
- = 等号
- … 分离运算符
- Object.assign() 深浅拷贝
- JSON.parse(JSON.stringify()) * 一定是深拷贝
- .slice()方法 深浅拷贝
- .concat() 深浅拷贝 (合并:sql里面用于拼接字符串)
- Array.from() 深浅拷贝
24.如何获取表格中其中一列的对象中的数据?
(表格中修改和删除其中一条获取id的方法/数据要被加工不是单纯显示)
<!-- 如果数据要被加工,而不是简单的展示在页面中,则需要开启template模板 -->
<template slot-scope="scope">
<!--
通过 scope.row可以拿取这一行的对象
scope.row.属性名 拿取某个属性
-->
{{ scope.row.gender===0?'男':'女' }}
</template>
<template slot-scope="scope">
<el-button type="primary" round size="mini"
@click="handleUpdate(scope.row.id)">修改</el-button>
<el-button type="danger" round size="mini"
@click="del(scope.row.id)">删除</el-button>
</template>
25.跳转路由的方法?通过路由的跳转传值?
this.$router.push('/index') //路由强制跳转(不传值)
this.$router.push(`/layout/info?id=${scope.row.id}`) //路由传值
let id = this.$route.query.id //路由跳转传递接受 (this.$route.query.key)