2018-09-21 vue面试题
计算属性如何使用
一般我们在写vue的时候,在模板内写的表达式非常便利,它运用于简单的运算,但是他也有一些复杂的逻辑,包括运算、函数调用等,那么就用到了计算属性,他依赖于data中数据变化的 data 中数据变化的时候 计算属性就会重新执行,视图也会更新。
计算属性的 set get 如何使用
每一个计算属性都包含一个getter 和一个setter ;
绝大多数情况下,我们只会用默认的getter 方法来读取一个计算属性,在业务中很少用到setter,所以在声明一个计算属性时,可以直接使用默认的写法,不必将getter 和setter 都声明。
但在你需要时,也可以提供一个setter 函数, 当手动修改计算属性的值就像修改一个普通数据那样时,就会触发setter 函数,
watch 如何使用
之前做一个H5的项目。需求是当用户在输入完了手机号和验证码之后,登录按钮才可以点击。
在没有使用vue之前,我们可能是通过input的change事件来判断,用户是否输入了内容,然后修改按钮的状态。现在有了vue,就省事了很多,我们只需要在watch中,监听数据模型的值改变即可。
在input 上绑定一个v-mode="pass"绑定一个数据名, 在data里写入绑定的事件名,通过watch来监听输入内容的改变,但是如果,监听的是一个对象 里面有一个deep属性可以在选项参数中指定deep:true.也叫深度监听
<input v-model="passw2" placeholder="请再次输入密码" />
计算属性和watch的区别
在我们运用vue的时候一定少不了用计算属性computed和watch
computed计算属性是用来声明式的描述一个值依赖了其它的值。当你在模板里把数据绑定到一个计算属性上时,Vue 会在其依赖的任何值导致该计算属性改变时更新 DOM。这个功能非常强大,它可以让你的代码更加声明式、数据驱动并且易于维护。
watch监听的是你定义的变量,当你定义的变量的值发生变化时,调用对应的方法。
就好在div写一个表达式name,data里写入num和lastname,firstname,在watch里当num的值发生变化时,就会调用num的方法,方法里面的形参对应的是num的新值和旧值,
而计算属性computed,计算的是Name依赖的值,它不能计算在data中已经定义过的变量。
prop 验证,和默认值
我们在父组件给子组件传值得时候,为了避免不必要的错误,可以给prop的值进行类型设定,让父组件给子组件传值得时候,更加准确,prop可以传一个数字,一个布尔值,一个数组,一个对象,以及一个对象的所有属性。
组件可以为 props 指定验证要求。如果未指定验证要求,Vue 会发出警告
比如传一个number类型的数据,用defalt设置它的默认值,如果验证失败的话就会发出警告。
prop 如何传一个对象的所有属性
方法一:使用不带参数的v-bind写法
v-bind中没有参数,而组件中的props需要声明对象的每个属性
方法二:使用带参数的v-bind写法
v-bind后跟随参数todo,组件中的props需要声明该参数,也就是v-bind后跟随参数todo,
组件就可以通过todo来访问对象的属性
插槽,具名插槽,插槽默认内容
单个插槽;在父组件写一个标签,在子组件通过slot来接受标签里的内容,他只能用一个slot。单个插槽可以放置在组件的任意位置,但是就像它的名字一样,一个组件中只能有一个该类插槽。
具名插槽:在父组件标签写入slot,子组件里面写name名字,他们两个名字要相对应,才能通过名字在找到对应的位置。相对应的,具名插槽就可以有很多个,只要名字(name属性)不同就可以了。
作用域插槽
举个例子,比如我写了一个可以实现条纹相间的列表组件,发布后,使用者可以自定义每一行的内容或样式(普通的slot就可以完成这个工作)。而作用域插槽的关键之处就在于,父组件能接收来自子组件的slot传递过来的参数,子组件与父组件的数据动态交互的一种常见案例
父组件中必须要有template元素,且必须有scope特性,scope特性中是临时变量名,
接收从子组件中传递上来的属性,属性可以是任意定义的。
动态组件
在我们平时使用vue中的模板的时候,许多时候都是直接定义成一个固定的模板,但是,vue中提供了一个动态模板,可以在任意模板中切换,就是用vue中<component>用:is来挂载不同的组件。
我们在components中注册了三个模板,当我们点击当前按钮的时候,就会将模板切换模板,可以说是非常方便了。如果要把组件切换过程中的将状态保留在内存中,可以添加一个 keep- alive 指令参数,防止重复渲染DOM。
动态组件上使用keep-alive
<keep-alive>是Vue的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM。
11子组件访问父组件实例子 $parent
this.$parent
在子组件中判断this.$parent获取的实例是不是父组件的实例
在子组件中console.log(this.$parent) 打印出this.$parent
在父组件中console.log(this) 打印出this
看看打印出来的两个实例是不是同一个
如果是同一个 就可以在子组件中通过this.$parent.属性名和方法名,来调用父组件中的数据或者方法
12 父组件访问子组件变量 this.$refs.usernameInput
给子组件添加ref属性然后,通过vm.$refs来调用子组件的methods中的方法或者获得data
父组件: 在子组件中加上ref即可通过this.$refs.ref.method调用
13 vue双向数据绑定原理
view更新data其实可以通过事件监听即可,比如input标签监听 'input' 事件就可以实现了。所以我们着重来分析下,当数据改变,如何更新视图的。
数据更新视图的重点是如何知道数据变了,只要知道数据变了,那么接下去的事都好处理。如何知道数据变了,就是通过Object.defineProperty( )对属性设置一个set函数,当数据改变了就会来触发这个函数,所以我们只要将一些需要更新的方法放在这里面就可以实现data更新view了。
视图view到data :可以通过事件监听即可,比如input标签监听 'onchange' 事件就可以实现了
data到view:通过Object.defineProperty( )对属性设置一个set函数,当数据改变了就会来触发这个函数,所以我们只要将一些需要更新的方法放在这个set函数里面就可以实现data更新view了。
14 vue 组件通信
1) 父传递子
父:自定义属性名 + 数据(要传递)=> :value="数据"
子:props ["父组件上的自定义属性名“] =>进行数据接收
1) 子传递父
子:this.$emit('自定义事件名称', 数据) 子组件标签上绑定@自定义事件名称='回调函数'
父:methods: { 回调函数() { //逻辑处理 } }
1) 兄弟组件
通过中央通信 let bus = new Vue()
A:methods :{ 函数{bus.$emit(‘自定义事件名’,数据)} 发送
B:created (){bus.$on(‘A发送过来的自定义事件名’,函数)} 进行数据接受
15 vue 生命周期
vue实例从被创建到销毁的一系列过程就叫vue生命周期.也就是从开始创建、初始化数据、编译模版、挂载DOM→渲染、更新、渲染、卸载等一系列过程。
BeforeCreate 实例创建之前调用
Created 实例创建成功,此时data中的数据已经初始化
beforeMount 挂载之前的状态
Mounted 已经挂载的状态
BeforeUpdate 数据更新前的状态
Updated 数据更 新完成时的状态
beforeDestory 在vue实例销毁之前调用,
Destoryed 在vue实例销毁之后调用,vue实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
16 vue webpack打包项目修改哪些配置
Config文件夹下面的index.js 设置里面的assetsPublicpath属性值为./
如果图片太大的话,可以设置bulid文件夹下面的webpack.base.conf.js,设置图片的limit将它的值设大点,
Utils.js添加publicpath为../../
17 vue路由传参数
使用query方法传入的参数使用this.$router.query接受
使用params方式传入的参数使用this.$router.params接受
一、用name传递参数
在路由文件src/router/index.js里配置name属性。
routes: [
{
path: '/',
name: 'Hello',
component: Hello
}
]
模板里(src/App.vue)用$router.name的形势接收,比如直接在模板中显示:
<p>{{ $route.name}}</p>
二、通过<router-link> 标签中的to传参
<router-link>标签中的to属性进行传参,需要注意的是这里的to要进行一个绑定,写成:to。
<router-link :to="{name:xxx,params:{key:value}}">valueString</router-link>
18 路由导航守卫
全局钩子函数 : beforeEach() 每次每一个路由改变的时候都得执行一遍
组件内的钩子函数 :
to: (Route路由对象) 即将要进入的目标 路由对象
from: (Route路由对象) 当前导航正要离开的路由
next: (Function函数) 一定要调用该方法来 resolve 这个钩子
beforeRouteEnter 路由之前调用
beforeRouteUpdate 复用时调用
beforeRouteLeave 离开路由时调用
19 什么是vuex,使用vuex的好处
Vuex是一个专为 Vue.js 应用程序开发的状态管理模式。
好处:
可以做状态管理 采用localstorage保存信息,数据便一直存储在用户的客户端中
使用场景:适合在巨大后复杂的项目中使用,
20 state,getter,mutation,action,module,plugins 各自的用途,和用法
State:{ count: 0 } 保存着所有的全局变量
Getter: 对state中的数据派生出一些状态,例如对数据进行过滤。(可以认为是store中的计算属性),会对state中的变量进行过滤再保存,只要state中的变量发生了改变,它也会发生变化,不变化的时候,读的缓存。
Mutation:更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。
一条重要的原则就是要记住 mutation 必须是同步函数。
Action: Action 类似于 mutation, 不同点在于,Action 提交的是 mutation,而不是直接变更状态。Action 可以包含任意异步操作,mutation只能是同步。
有点不同的是Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。
Module: //模块,可以写很多模块,最后都引入到一个文件。分散管理。
生成实例的时候 都放在Store的modules中
plugins:插件(Plugins)是用来拓展webpack功能的,它们会在整个构建过程中生效,执行相关的任务。
21 vuex中使用persistedstate 插件进行长久储存 (需要自己写代码测试)
安装 npm install vuex-persistedstate --save
store.js引入
import VuexPersistence from "vuex-persist";
创建一个对象:
const vuexLocal = new VuexPersistence({
storage:window.localStorage
})
安装进vuex插件:
export default new Vuex.Store({
state:{
info:{}
},
mutations:{
setInfo(state,info){
state.info=info;
}
},
plugins:[VuexPersistence()]
})
默认存储到localStorage
想要存储到sessionStorage,配置如下
import createPersistedState from "vuex-persistedstate"const store = new Vuex.Store({
plugins: [createPersistedState({
storage: window.sessionStorage
})]
})
22 vue开发中遇到的问题
1、setInterval路由跳转继续运行并没有及时进行销毁
比如一些弹幕,走马灯文字,这类需要定时调用的,路由跳转之后,因为组件已经销毁了,但是setInterval还没有销毁,还在继续后台调用,控制台会不断报错,如果运算量大的话,无法及时清除,会导致严重的页面卡顿。
解决方案:在组件生命周期beforeDestroy停止setInterval
beforeDestory() {
clearInterval(this.timer);
MessageBox.close()
}
2、vuejs循环插入图片
在写循环的时候,写入如下代码:
<div class="bio-slide" v-for="item in items">
<img src="{{item.image}}"></div>
此时在控制台会出现警告
[Vue Warn]: src=”{{item.image}}”: interpolation in “src” attribute will cause a 404 request. Use v-bind:src instead.这里意思是在“src”属性插值将导致404请求。使用v-bind:src代替。
所以替换成如下:
<div class="bio-slide" v-for="item in items">
<img v-bind:src="item.image">
</div>
这里需要主要,v-bind在写的时候不能再用{{}},
3、组件的异步加载(按需加载组件)
在平时的demo中,你可能不会遇见这个需求,当页面很多,组件很多的时候,你会发现你的页面在首次加载的时候,异常的慢,这个是因为vue首次加载的时候把可能一开始看不见的组件也一次加载了,这个时候就需要对页面优化了,就需要异步组件了。如何去写异步组件呢,实际上很简单,只需要在你的路由index,js里加上require就可以了,像下面这样,这也是所谓的按需加载组件的实现原理。
4、vuex组件中访问state报错
TypeError: Cannot read property ‘state’ of undefined”
在组件中使用this.$store.state.test访问state的属性报错,是因为store的实例并未注入到所有的子组件,需修改main.js
new Vue({
el: '#app',
store, //将store注入到子组件
router,
components: { App },
template: '<App/>'
})