vue面试题总结
这些是在最近面试中问到的一些问题
Vue 双向绑定的实现
v-model的双向绑定使用Object.defineProperty()
实现双向绑定,这个方法重新定义了对象属性的 set、get方法,以此实现监听数据改变视图。
需要注意的是vue3.0使用了proxy
对象实现双向绑定。
两者的区别在于,前者只能劫持对象的属性值进行操作。后者proxy是劫持整个对象,并返回一个新的对象进行操作
//Object.defineProperty的用法
let obj = {};
let name = '';
Object.defineProperty(obj, 'name', {
set: function (value) {
name = value;
console.log('name' + value);
},
get: function () {
return '《' + name + '》'
}
})
obj.name = 'ZJINH'; // 设置为ZJINH
console.log(obj.name); // 《ZJINH》
//proxy的用法
let obj1 = {};
let handler = {
get(target, property) {
console.log(`${property} 被读取`);
return property in target ? target[property] : 3;
},
set(target, property, value) {
console.log(`${property} 被设置为 ${value}`);
target[property] = value;
}
}
let p = new Proxy(obj1, handler);
p.name = 'ZJINH'; //name 被设置为 ZJINH
p.age; //age 被读取 3
Vue路由有哪些模式,有什么不同,用什么监听改变
vue的路由一共有两种模式history
和hash
hisoty
模式需要服务器配合,明显的特征是浏览器地址栏没有/#/
,vue路由使用popstate
监听实现路由功能,这种模式充分利用 history.pushState API 来完成 URL 跳转
hash
模式则是使用哈希,明显的特征是浏览器地址栏有/#/
,vue路由使用onhashchange
监听实现路由功能,使用URL的 hash来模拟一个完整的URL,于是当URL改变时,页面不会重新加载
Vue路由跳转的几种方式
router-link
跳转组件,to参数为跳转地址
this.$router.push
该方法内部传去对象,对象内path为路由,但这个方法会向history栈添加一个记录,点击后退会返回到上一个页面。
this.$router.replace()
该方法内部传去对象,对象内path为路由,跳转到指定的url,但是这个方法不会向history里面添加新的记录,点击返回,会跳转到上上一个页面。上一个记录是不存在的。
this.$router.go(n)
该方法和history.go用法类似,可以前进后退n个页面。
this.$router.reslove()
该方法返回一个地址,可以使用window.open打开新标签。
Vue router-link的用法
// 字符串
<router-link to="apple"> to apple</router-link>
// 对象
<router-link :to="{path:'apple'}"> to apple</router-link>
// 命名路由
<router-link :to="{name: 'applename'}"> to apple</router-link>
//直接路由带查询参数query,地址栏变成 /apple?color=red
<router-link :to="{path: 'apple', query: {color: 'red' }}"> to apple</router-link>
// 命名路由带查询参数query,地址栏变成/apple?color=red
<router-link :to="{name: 'applename', query: {color: 'red' }}"> to apple</router-link>
//直接路由带路由参数params,params 不生效,如果提供了 path,params 会被忽略
<router-link :to="{path: 'apple', params: { color: 'red' }}"> to apple</router-link>
// 命名路由带路由参数params,地址栏是/apple/red
<router-link :to="{name: 'applename', params: { color: 'red' }}"> to apple</router-link>
tag属性
<router-link :to="{name:'schedule',query:{aa:'dsd'}}" tag="li">跳转</router-link>
event属性
<router-link to="/document" event="mouseover">document</router-link>
基本属性有to 、replace、 append、 tag、 active-class、 exact 、 event、 exact-active-class
router-link标签会自动渲染成a标签,如果不想渲染为a标签,只需要使用tag属性例如 tag='button',那么就会渲染为button。
和a标签一样加上target属性为"_blank",依然可以打开一个新的页面。
event属性,那么默认情况下是当我们点击document的时候,跳转到相应的页面,但当我们加上event的时候,就可以改变触发导航的事件,比如鼠标移入事件。
append属性 类型: boolean 默认值: false 设置 append 属性后,则在当前 (相对) 路径前添加基路径。
active-class 类型: string 默认值: "router-link-active",选中的classname,默认值可以通过路由的构造选项 linkActiveClass 来全局配置。
exact-active-class 类型: string 默认值: "router-link-exact-active",配置当链接被精确匹配的时候应该激活的 class,默认值也是可以通过路由构造函数选项 linkExactActiveClass 进行全局配置的。
路由的构造选项全局配置示例
export default new Router({
mode:'history',
linkActiveClass:'is-active-route',
routes: [
{
path:'/about',
component:about
}
]
})
Vue修改数组某一对象能否触发视图更新
答案是不能的,vue只对数组的push、splice等进行hack实现视图改变,针对这种arr[0].name='ZJINH'
是无法监听的。
前面提到了Object.defineProperty()
实现双向绑定,这个方法只能监听对象的某一个key,未来使用proxy
实现的双向绑定,由于是监听一整个对象,所以可以触发视图更新
v-if v-show的区别 什么时候使用
v-if是通过vue底层实现的,效果类似于注释和取消注释
v-show是通过改变display实现元素显示隐藏
在v-for的时候不推荐使用v-if,每次循环都会在v-if里再次循环,有事件绑定的不推荐使用v-if。
vue的生命周期顺序
beforeCreate
创建之前初始化 事件和生命周期
created
创建完成
beforeMount
渲染
mounted
dom结构渲染完成
beforeUpdate
视图更新前
updated
视图更新后
actived
这个只在使用了 keep-alive会出现,组件被激活
deactived
这个只在使用了 keep-alive会出现,组件取消激活(不可见)
beforeDestroy
组件销毁前,期间注销监听等
destroyed
组件销毁完毕
如何在created生命周期里获取组件的dom
上面提到了在mounted之前dom结构不会渲染出来,自然无法获取到。 但我们可以用以下两种方法获取。
一种使用子组件,在mounted的时候发送消息给父组件,父组件接受消息获取dom 当子组件已经渲染完成,便可发送消息事件通知父组件获取dom
method:{
getElm(){
document.getElementById()
}
}
另外一种使用this.nextTick()
的回调函数获取
created(){
this.nextTick(()=>{
document.getElementById()
})
}
Sync修饰符是什么作用
这个修饰符在vue里其实是允许子组件修改传入的props参数
,但这是不推荐使用的,修改参数还是建议使用emit
对父组件发送消息进行参数修改。
Vue的 mixins 作用及用法
mixins
选项接收一个混入对象的数组。这些混入对象可以像正常的实例对象一样包含实例选项,这些选项将会被合并到最终的选项中,使用的是和 Vue.extend()
一样的选项合并逻辑。也就是说,如果你的混入包含一个created
钩子,而创建组件本身也有一个,那么两个函数都会被调用。
以上是vue的官方文档
简单来说类似于Object.assign
,但在vue使用的时候,这个混入的对象,会和该组件内的方法合并执行
如何使用原生JS实现变量只允许改变一次
这个问题的前提是不存在ES6语法,实现var name=123
只可以被修改一次
这里我使用的是Object.defineProperty
实现的,原理很简单,修改的时候记录次数,如果是第一次修改则允许。
var name=123;
var temp=""
var count=0
Object.defineProperty(window, 'name',{
get:function(){
return temp;
},
set:function(val) {
if(count===0){
temp=val;
count++;
}else{
throw Error('只能赋值一次')
}
}
})
for foreach map 区别 如何停止跳出
这道题我的解答是,foreach map都是用回调进行,无法跳出,map会返回新对象。for循环可以用break跳出
跨域的解决方法
jsonp
利用了script标签无跨域,实现参数返回。
nginx
使用nginx反向代理到同域下
跨域头
在后端服务配置加上允许跨域请求头
如何对一个对象的key按字母排序并返回排序后的对象
var obj = {name: "ZJINH", age: 18, ace: 5};//要排序的对象
function objKeySort(obj) {//排序的函数
var newkey = Object.keys(obj).sort();
//先用Object内置类的keys方法获取要排序对象的属性名,再利用Array原型上的sort方法对获取的属性名进行排序,newkey是一个数组
var newObj = {};//创建一个新的对象,用于存放排好序的键值对
for (var i = 0; i < newkey.length; i++) {//遍历newkey数组
newObj[newkey[i]] = obj[newkey[i]];//向新创建的对象中按照排好的顺序依次增加键值对
}
return newObj;//返回排好序的新对象
}
objKeySort(obj)
原创不易,如果可以就打赏下吧~

