vue面试题
vue优点
- 轻量级框架,只关注视图层
- 简单易学,有中文开发文档
- 双向数据绑定
- 组件化
- 视图、数据、结构分离
vue父组件向子组件传递数据
-
通过props:父组件向子组件传值就是通过在父组件中让子组件标签绑定父组件的数据,子组件的props接收父组件穿过来的值即可。
-
<body> <div id="app"> <my-child msg="hhhhh"></my-child> </div> </body> <template id="child"> <!-- 子组件有且仅有一个最外层元素 --> <div>{{msg}}</div> </template> </body>
-
<script> new Vue({ el: "#app", components: { 'my-child': { template: '#child', props: ['msg'] } } }) </script>
子组件向父组件传递事件
-
$emit方法:子传父的实现方式就是用了
this.e m i t
来 遍 历g e t D a t a
事 件 , 首 先 用 按 钮 来 触 发s e t D a t a
事 件 , 在s e t D a t a
中 用t h i s . emit
来遍历 getData 事件,首先用按钮来触发 setData 事件,在 setData 中 用 this.emit来遍历getData事件,首先用按钮来触发setData事件,在setData中用this.emit 来遍历 getData 事件,最后返回 this.msg -
<body> <div id="app"> <!-- 第一步 : 父组件在调用了子组件的地方,绑定一个自定义事件(myevent) 事件的定义由父组件实现。在实现的拥有默认的参数(val),值就是子组件 传递给父组件的值 --> <my-child @myevent='getData'></my-child> </div> </body> <template id="child"> <!-- 在子组件的某一个事件内部,通过this.$emit('自定义的事件',传递的参数) 传递值给父组件。 --> <div>子组件<input type="button" value="发送数据" @click='sendData'></div> </template> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> let app = new Vue({ el: '#app', // 挂载点 components: { // 组件 ---> 需要注册的组件 'my-child': { // 子组件的名字 template: '#child', // 模板 ---> 可以是html结构 也可以是挂载点 methods: { // 子组件内触发这个方法 sendData() { this.$emit('myevent', '这个数据是有子组件传递的') } } } }, methods: { getData(val) { // 事件的定义由父组件实现 console.log(val); } } }) </script>
v-show和v-if指令的共同点和不同点
- 共同点(效果相同)
- 都能控制元素的显示和隐藏
- 不同点(实现方式不同)
- v-show是通过控制css中的display属性设置为none来控制隐藏,只会编译一次
- v-if是动态地向DOM树内添加或者删除DOM元素
- 总结
- v-show(切换开销较小,初始开销较大)
- v-if(初始渲染开销较小,切换开销较大)
v-if和v-for的优先级
- 当 v-if 与 v-for 一起使用时,v-for 具有比 v-if 更高的优先级
- 不推荐同时使用
如何让CSS只在当前组件中起作用?
-
在组件中的style前面加上scoped
-
<style scoped> </style>
keep-alive标签的作用是什么?
- keep-alive是Vue内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染
如何获取dom?
-
ref=“domName”
-
用法:this.$refs.domName
-
//如果想要获取到DOM对象或者组件对象,可以给对应的标签添加ref属性,并自定义名字 //这是子组件 <child ref="child"></child> this.$refs.child //获取的是一个组件对象 //这是个普通的标签 <div ref="div"></div> this.$refs.div //获取到的是一个DOM对象
-
可结合nextTick使用:
-
//如果想要在vue中使用DOM对象,可以使用该方法 this.$nextTick(() => { //这个函数会等待DOM执行完成后执行 }) this.$nextTick().then(() => { //这个函数会等待DOM执行完成后执行 })
说出几种vue当中的指令和它的用法?
- v-mode:双向数据绑定
- v-for:循环
- v-if和v-show:显示隐藏
- v-on:事件绑定
- v-onve:只绑定一次
vue-loader是什么?使用它的用途有哪些?
- 介绍:解析和转换.vue文件,从中提取出其中的逻辑代码 javascript、样式代码style,以及HTML 模板template,再将他们分别交给对应的loader去处理(vue文件的一个加载器,将template/js/style转换成js模块)
- 用途:js可以写成es6、style样式可以scss或less、template可以加jade等
为什么在v-for中使用key?
-
需要使用key来给每个节点做一个唯一标识,Diff算法就可以正确的识别此节点。
-
作用主要是为了高效的更新虚拟DOM
-
//不使用key <ul> <li v-for="(item, index) in lists"> <input type="checkbox" :value="item.text"/> {{item.text}} </li> </ul> //使用key <ul> <li v-for="(item, index) in lists" :key="item.id"> <input type="checkbox" :value="item.text"/> {{item.text}} </li> </ul> <script> var vm = new Vue({ el: '#app', data: { lists: [ { id: 1, text: '张' }, { id: 2, text: '吕' }, { id: 3, text: '王' } ] }, methods: { remove() { //注意这里是shift this.lists.shift() } } }) </script>
-
注意:key的取值必须是number 或 string,不能是对象,而且使用 v-for 循环的每一项的值,都要保证唯一性 。
axios及安装?
- 请求后台资源的模块。输入
npm install axios --save
装好 - js中使用import进来,然后.get或.post。返回在.then函数中如果成功,失败则是在.catch函数中
请说出vue.cli项目中src目录每个文件夹和文件的用法?
- assets文件夹是放静态资源
- components是放组件
- router是定义路由相关的配置;
- app.vue是一个应用主组件
- main.js是入口文件
- view视图
v-modal的使用
-
用于表单数据的双向绑定
-
v-bind绑定一个value属性
-
v-on指令给当前元素绑定input事件
<input v-model="sth" /> <input v-bind:value="sth" v-on:input="sth = $event.target.value" />
分别简述computed和watch的使用场景
- computed:
- 当一个属性受多个属性影响影响的时候就需要用到computed(最典型的例子:购物车商品结算的时候)
- watch:
- 当一条数据影响多条数据的时候就需要用watch(例子:搜索数据)
v-on可以监听多个方法吗?
-
可以
<input type="text" v-on="{input:onInput,focus:onFocus,blur:onBlur}">
$nextTick的使用
- 当你修改了data的值之后想要马上获取这个dom元素的值,是不能获取到更新后的值。
- 你需要使用$nextTick这个回调,让修改后的data值渲染更新到dom元素之后再获取,才能成功
vue组件中data为什么必须是一个函数?
- 这是因为JavaScript的特征所致,在component中,data必须以函数的形式存在,不可以是对象
- 组件中的data写成一个函数,数据以函数返回值的形式定义,这样每次复用组件的时候,都会返回一份新的data,相当于每个组件实例都有自己私有的数据空间,它们只负责各自维护的数据,不会造成混乱。而单纯地写成对象形式,就是所有的组件实例共用了一个data,这样改一个全都改了
单页面应用和多页面应用区别及优缺点
- 单页面应用(SPA):通俗一点说指的是只有一个主页面的应用,浏览器一开始要加载所有必须的html、js、css。所有的页面内容都包含在这个所谓的主页面中,但在写的时候,还是会分开写(页面片段),然后在交互的时候由路由程序动态载入,单页面的页面跳转,仅刷新局部资源,多应用于pc端。
- 多页面(MPA):指的是一个应用中有多个页面,页面跳转时是整页刷新的
- 单页面优点:
- 用户体验好,快,内容的改变不需要重新加载整个页面,基于这一点spa对服务器压力较小
- 前后端分离
- 页面效果会比较炫酷(举例:切换页面内容时的转场动画)
- 单页面缺点:
- 不利于seo
- 导航不可用,如果一定要使用导航,需要自行实现前进、后退。(由于是单页面不能用浏览器的前进和后退功能,所以需要自己建立堆栈管理)
- 初次加载时耗时多
- 页面复杂度提高很多
渐进式框架的理解
- 主张最少,可以根据不同的需求选择不同的层级
Vue中双向数据绑定是如何实现的?
- vue 双向数据绑定是通过 数据劫持 结合 发布订阅模式的方式来实现的
- 数据和视图同步,数据发生变化,视图随之变化
- 核心:Object.defineProperty()方法
assets和static的区别
- 相同点:
- assets和static两个都是存放静态资源文件
- 项目中所需要的资源文件图片,字体图标,样式文件等都可以放在这两个文件下,这是相同点
- 不相同点:
- assts中存放的静态资源文件在项目打包时,也就是运行npm run build时会将assets中放置的静态资源文件进行打包上传,所谓打包简单点可以理解为压缩体积,代码格式化。而压缩后的静态资源文件最终也都会放置在static文件中跟着index.html一同上传至服务器。
- static中放置的静态资源文件就不需要打包压缩格式化等流程,而是直接进行打包好的目录,直接上传至服务器。因为避免了压缩直接进行上传,在打包时会提高一定的效率,但是static中的资源文件由于没有进行压缩等操作,所以文件的体积也就相对于assets中打包后的文件提交较大。在服务器中就会占据更大的空间。
- 建议:将项目中template需要的样式文件,比如说js文件等都可以放置在assets中,打包这一流程,减少体积。而项目中引入的第三方的资源文件,比如说iconfont.css等文件可以放置在static中,因为这些映入的第三方文件已经经过处理,我们不再需要处理,直接上传。
vue常用的修饰符
- .stop:等同于JavaScript中的event.stopPropagation(),防止事件冒泡
- .prevent:等同于JavaScript中的event.preventDefault(),防止执行预设的行为(如果事件可取消,则取消该事件,而不停止事件的进一步传播)
- .capture:与事件冒泡的方向相反,事件捕获由外到内
- .self:只会触发自己范围内的事件,不包含子元素
- .once:只会出发一次
vue和jQuery的区别
- jQuery是==使用选择器( ) 选 取 D O M 对 象 = = , 对 其 进 行 赋 值 、 取 值 、 事 件 绑 定 等 操 作 , 其 实 和 原 生 的 H T M L 的 区 别 只 在 于 可 以 更 方 便 的 选 取 和 操 作 D O M 对 象 , 而 数 据 和 界 面 是 在 一 起 的 。 比 如 需 要 获 取 l a b e l 标 签 的 内 容 : ‘ )选取DOM对象==,对其进行赋值、取值、事件绑定等操作,其实和原生的HTML的区别只在于可以更方便的选取和操作DOM对象,而数据和界面是在一起的。比如需要获取label标签的内容:` )选取DOM对象==,对其进行赋值、取值、事件绑定等操作,其实和原生的HTML的区别只在于可以更方便的选取和操作DOM对象,而数据和界面是在一起的。比如需要获取label标签的内容:‘(“lable”).val();`它还是依赖DOM元素的值。
- Vue则是通过Vue对象将数据和View完全分离开来了。对数据进行操作不再需要引用相应的DOM对象,可以说数据和View是分离的,他们通过Vue对象这个vm实现相互的绑定,这就是传说中的MVVM。
引进组件的步骤
- 在template中引入组件
- 在script的第一行用import引入路径
- 用component中写上组件名称
delete和Vue.deletes删除数组的区别
- delete只是被删除的元素变成了empty/undefined其他的元素的键值还是不变
- Vue.delete是直接删除了数组,改变了数组的键值
SPA首屏加载慢如何解决
- 安装动态懒加载所需插件;使用CDN资源
Vue-router跳转和location.href有什么区别
- 使用
location.href='/url'
来跳转,简单方便,但是会刷新页面 - 使用
history.pushState('/url')
,无刷新页面,静态跳转 - 引进router,然后使用
router.push('/url')
来跳转,使用了diff算法,从而实现了按需加载,并减少了dom的消耗。- 其实使用router跳转和使用
history.pushState('/url')
没什么差别,因为vue-router就是用了history.pushState(),尤其是在history模式下
- 其实使用router跳转和使用
vue slot
- 简单来说,假如父组件需要在子组件内放一些DOM,那么这些DOM是显示、不显示、在那个地方显示、如何显示,就是slot分发负责的工作
你们vue项目是打包了一个js文件,一个css文件,还是有多个文件?
- 根据vue-cli脚手架规范,一个js文件,一个css文件即可
Vue里面router-link在电脑上有用,在安卓上没反应怎么解决?
- Vue路由在Android机上有问题,babel问题,安装
babel polypill
插件解决
Vue2中注册在router-link上事件无效解决方法
-
使用@click.native
<li > <router-link to="/two" @click.native="change('color1')" :class="{'bgred':fff['color1']}">页面一</router-link> </li>
-
Because:router-link会阻止click事件,.native指的是直接监听一个原生事件
如何解决RouterLink在IE和Firefox中不起作用(路由不跳转)的问题
- 方法一:只用a标签,不适用button标签
- 方法二:使用button标签和Router.navigate方法
axios的特点有哪些
- 从浏览器中创建XMLHttpRequest
- node.js创建http请求
- 支持Promise API
- 拦截请求和响应
- 转换请求数据和响应数据
- 取消请求
- 自动换成json
- axios中的发送字段的参数是data和params,两者的区别在于params是跟请求地址一起发送的,data作为一个请求体进行发送
- params一般适用于get请求,data一般适用于post put请求
请说下封装vue组件的过程
- 建立组件的模板,先把架子搭起来,写写样式,考虑好组件的基本逻辑
- 准备好组件的数据输入。即分析好逻辑,定好props里面的数据、类型
- 准备好组件的数据输出。即根据组件逻辑,做好要暴露出来的方法
- 封装完毕了,直接调用即可
params和query的区别
- 用法:
- query要用path来引入,接收参数是
this.$route.query.name
- params要用name来引入,接收参数是
this.$route.params.name
- query要用path来引入,接收参数是
- url地址显示:
- query类似于我们ajax中get传参
- params类似于post
- 说的通俗一点,前者在浏览器中显示参数,而后者则不显示
- 注意点:
- query刷新不会丢失query里面的数据
- params刷新会丢失params里面的数据
vue初始化页面闪动问题
- 分析:使用vue开发时,由于在vue初始化之前,div是不归vue管的,所以我们写的diamagnetic在还没有解析的情况下会容易出现花屏现象,看到蕾仕于{{message}}的字样。虽然持续时间很短,但是我们还是有必要解决这个问题
- 方法:
- 在css里加上[v-cloak]{display:none;}
- 如果还没有彻底解决问题,则在根元素加上style=“display:none;” :style="{display:‘block’}"
vue更新数组时触发视图更新的方法
-
push()
-
pop()
-
shift()
-
unshift()
-
splice()
-
sort()
-
reverse()
<template> <div class="hello"> <h1>{{ msg }}</h1> <div > <ul> <li v-for="(item,index) in items" :key="index"> {{item.name}} </li> </ul> <button @click="update">修改</button> <br> <p v-for="(item,index) in items2" :key="index" >{{item}}</p> <button @click="btn()">添加</button> <button @click="dele()">删除</button> <br> <div>{{obj}}</div> <button @click="btn2()">修改</button> <button @click="updateMethod()">方法更新</button> </div> </div> </template> <script> import Vue from 'vue' export default { name: 'HelloWorld', data () { return { msg: 'Welcome to Your Vue.js App', testMsg: '原始值', items: [ {name: 'lili', age: 29}, {name: 'nana', age: 25} ], items2: ['a', 'b', 'c'], obj: { name: 'xiaoli', sex: '女' } } }, methods: { update () { this.items[1].name = 'dada' console.log(this.items[1].name) }, btn () { // 发现修改失败。 // this.items2[1] = 'd' // console.log(this.items2) // Vue.set() 方法 // 参数1: 要修改的对象 // 参数2: 属性 // 参数3: 属性的值是啥 // 返回值:已经修改好的值 // 有三种方法可以实现,分别是Vue.set, vm.$set, replace Vue.set(this.items2, 1, 'e') }, btn2 () { this.obj = Object.assign({}, this.obj, {jiaxi: 'jx'}) }, // Vue. delete 删除对象或数组中元素,通过 key 或数组索引,可以触发视图更新 dele () { Vue.delete(this.items2, 1) }, updateMethod () { this.items2.push('f') // Vue 提供了如下的数组的变异方法,可以触发视图更新 // push() // pop() // shift() // unshift() // splice() // sort() // reverse() } } } </script>
vue常用的UI组件库
- Mint UI
- element
- VUX
vue修改打包后静态资源路径的修改
-
cli2版本:将config/index.js里的assetsPublicPath的值改为’./’
build: {
…
assetsPublicPath: ‘./’,
…
} -
cli3版本:在根目录下新建vue.config.js文件,然后加上以下内容(如果已经有此文件就直接修改):
module.exports = {
publicPath: ‘’, // 相对于 HTML 页面(目录相同) }