1. vue的模板语法用的是哪个web模板引擎?说说你对这模板引擎的理解
答: vue.js使用了基于HTML的模板语法,允许开发者声明式的将DOM绑定至底层Vue实例的数据.所有的vuejs的模板都是合法的HTML,所以能够被遵循规范的浏览器和HTML解析器解析.
在底层的实现上,Vue将模板编译成虚拟DOM渲染函数,结合响应系统,vue能够智能地计算出最少需要重新渲染多少组件,并把DOM操作次数减到最少.
模板引擎:使用户界面与业务数据分离而产生的,可以生成特定的格式的文档,用于网站模板引擎就会生成一个标准的HTML文档.
2. v-model的原理?
答:v-model可实现表单,标签元素的双向数据绑定
双向数据绑定:
** 模板到真实节点的过程: 1.模板解析成AST树;2.AST树生成可执行的render函数;3.render函数转换成Vnode对象;4.根据Vnode对象生成真实的DOM节点
AST树的解析:
模板的编译阶段,会调用var ast = parse(template.trim(),options)生成AST树,parse函数
AST产生阶段对事件指令v-on的处理是为AST树添加events属性.类似的,普通指令会在AST树上添加directives属性, addDirecctive函数
3.如何用vue开发多语言项目?
答: 使用插件vue-i18n
npm i vue-i18n -save
main.js中引入
import VueI18n form ‘vue-i18n’
Vue.use(VueI18n)
const i18n = new VueI18n({
locale:’chs’ //将要切换的语言,可以通过url拼的参数获取,用户行为select选择获取,本地manifest配置获取等,根据场景动态获取
messages:{
‘chs’: require(‘../../assets/languages/chs.json’), //本地资源,配置了2个语言,中文&英文, src下根据个人情况放置
‘en’: require(‘../../assets/languages/en.json’)
}
});
const app = new App({
el: ‘#app’,
i18n
…
})
—-
vue页面中使用
mounted(){
let vm = this;
vm.$t('home.say');
}
4.使用计算属性的时候,函数名和data数据源中的数据可以同名么
答: 不能同名.
计算属性,data,props都会挂在vm实例上,不能同名.
—-实际操作
5.vue中data的属性可以和methods中的方法同名么
答:不能同名.
vue会把methods和data的内容,全部代理到vue生成对象中, 会产生覆盖.
6.如何给vue定义全局的方法
答: 先定义共用组件common.vue
在需要的地方导入
import Common from ‘./common.vue’
——
在main.js中导入
import Common from ‘./common.vue’
Vue.prototype.COMMON = Common,
1.挂载到Vue的prototype上
2. 利用全局混入mixin
7.vue2.0不再支持v-html中使用过滤器了怎么办
答: 1.全局方法
vue.prototype.msg = function(msg){
return msg.replace(‘\n’,’’)
}
2.computed属性
computed:{
content(msg){
return msg.replace(‘\n’,’’)
}
}
3.$options.filters
在定义的vue里面的filter添加方法
var appMain = new Vue({
el:’#appMain’,
filters:{
msg(msg){
return msg.replace(‘\n’,’’)
}
},
data:{
}
})
8.怎么解决vue打包后静态资源图片失效的问题?
答: 找到config ->index.js里面 将assetsPublicPath:’/‘ 改成assetsPublicPath:’./‘
找到build ->utils.js里面 在use: loaders 后面 加一个 publicPath:’../../‘
静态资源图片失效分几种情况。
1、确定线上环境是否在根路径上,配置资源根目录,vue-cli2 和 vue-cli3 字段不一致(assetsPublicPath 和 publicPath ),如果项目是根路径上,用’/‘,’./‘都行,如果是在’/hc’这个路径上,用’./‘ 相对路径(需history模式),也可以用’/hc/‘。 在’/hc’路径上,如果需要本地和线上保持一致,可以用环境做判断设置不同的publicPath值。
2、确定静态文件放置的位置。
①、如果放在public/static,不经过webpack打包, 放在public 又分使用绝对路径和相对路径。
②、如果放在assets, 经过webpack打包, 使用的是相对路径
3、路径是否是动态的,如果是动态,需要用require() 引入。
9.怎么解决vue动态设置img的src不生效的问题
答: 因为添加src被当做静态资源处理了,没有进行编译,所以要加上require
export default {
name:’HelloWorld’,
data(){
return {
logo:require(‘./../assets/logo.png’)
}
}
}
10.使用vue后怎么针对搜索引擎做SEO优化
答:什么是seo : 搜索引擎优化(Search engine optimization SEO) —SSR
使用服务端渲染,vue官方推荐nuxt.js
- ssr,即单页面后台渲染
- vue-meta-info 与prerender-spa-plugin 预渲染
- nuxt
- phantomjs
- 1.SSR服务器渲染;
2.静态化;
3.预渲染prerender-spa-plugin;
4.使用Phantomjs针对爬虫做处理。
11.跟keep-alive有关的生命周期有哪些,描述下这些生命周期
答: activated : 页面第一次进入的时候,钩子触发的顺序是created - mounted —activated
deactivated:页面退出的时候会触发deactivated, 当再次前进或者后退的时候只触发activated
12.让你从vue/react/angular三个中选一个,你会选哪一个,说说你的理由
13.vue2.0兼容IE哪个版本以上
答: 不兼容IE8以下的
vue的响应式原理是基于es5的Object.defineProperty,这个方法不支持ie8以下的.
14.使用vue开发一个todo小应用,说说你的思路
15.vue推荐的风格指南?
答:
- 优先级A的规则:必要的 (规避错误)
- 组件名为多个单词
- 组件数据:组件的 data 必须是一个函数。
- 细致的 Prop 定义
- 总是用
:key配合v-for - 避免
v-if和v-for用在一起 - 为组件样式设置作用域
- 私有属性名:自定义私有属性使用
$_前缀。并附带一个命名空间以回避和其它作者的冲突 (比如$_yourPluginName_)。
- 优先级B的规则:强烈推荐 (增强可读性)
- 组件文件:只要有能够拼接文件的构建系统,就把每个组件单独分成文件。
- 单文件组件文件的大小写:要么始终是单词大写开头 (PascalCase),要么始终是横线连接 (kebab-case)。
- 基础组件名:应用特定样式和约定的基础组件 (也就是展示类的、无逻辑的或无状态的组件) 应该全部以一个特定的前缀开头,比如
Base、App或V。 - 单例组件名:只拥有单个活跃实例(每个页面只使用一次)的组件应该以
The前缀命名,以示其唯一性。 - 紧密耦合的组件名:和父组件紧密耦合的子组件应该以父组件名作为前缀命名。
- 组件名中的单词顺序:组件名应该以高级别的 (通常是一般化描述的) 单词开头,以描述性的修饰词结尾。
- 自闭合组件:在单文件组件、字符串模板和 JSX 中没有内容的组件应该是自闭合的——但在 DOM 模板里永远不要这样做。
- 模版中的组件名大小写:在单文件组件和字符串模板中组件名应该总是 PascalCase 的——但是在 DOM 模板中总是 kebab-case 的。
- JS / JSX 中的组件名大小写:JS/JSX 中的组件名应该始终是 PascalCase 的,在较为简单的应用中只使用
Vue.component进行全局组件注册时,可以使用 kebab-case 字符串。 - 完整单词的组件名
- Prop 名大小写:在声明 prop 的时候,其命名应该始终使用 camelCase,而在模板和 JSX 中应该始终使用 kebab-case。
- 多个特性的元素:多个特性的元素应该分多行撰写,每个特性一行。
- 模板中简单的表达式:组件模板应该只包含简单的表达式,复杂的表达式则应该重构为计算属性或方法。
- 简单的计算属性
- 带引号的特性值:非空 HTML 特性值应该始终带引号 (单引号或双引号,选你 JS 里不用的那个)。
- 指令缩写:指令缩写 (用
:表示v-bind:、用@表示v-on:和用#表示v-slot:) 应该要么都用要么都不用。
- 优先级C的规则:推荐 (将选择和认知成本最小化)
- 组件 / 实例的选项的顺序
- 元素特性的顺序
- 组件 / 实例选项中的空行:在多个属性之间增加一个空行,特别是在这些选项一屏放不下,需要滚动才能都看到的时候。
- 单文件组件的顶级元素的顺序:总是让
<script>、<template>和<style>标签的顺序保持一致。且<style>要放在最后,因为另外两个标签至少要有一个。
- 优先级D的规则:谨慎使用 (有潜在危险的模式)
- 没有在
v-if/v-else-if/v-else中使用key - 元素选择器应该避免在
scoped中出现。 - 隐性的父子组件通信:应该优先通过 prop 和事件进行父子组件之间的通信,而不是
this.$parent或改变 prop。 - 非 Flux 的全局状态管理:应该优先通过 Vuex 管理全局状态,而不是通过
this.$root或一个全局事件总线。16.vue1.x和2.x的区别?
答:17.vue中key的原理?
答:1.主要用在vue的虚拟Dom算法,在新旧VNode 对比时辨识VNode,相当于唯一标识id
2.vue会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染,因此使用
key值可以提高渲染效率,同理,改变某一元素的key值会使该元素重新被渲染.
key的作用主要是为了高效的更新虚拟DOM;
如果没有唯一的key, 数据更新时, 相同节点更新前后无法准确一一对应起来,会导致更新效率降低;
当页面的数据发生变化时,Diff算法只会比较同一层级的节点:
- 如果节点类型不同,直接干掉前面的节点,再创建并插入新的节点,不会再比较这个节点以后的子节点;
- 如果节点类型相同,则会重新设置该节点的属性,从而实现节点的更新;
18.vue中如何重置data?
Object.assign()方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象
答:Object.assign(this.$data,this.$options.data())
vm.$data可以获取当前状态下的data,vm.$options.data可以获取到组件初始化状态下的data,
使用 Object.assign(this.$data,this.$options.data.call(this)) 这样写才有用重置 data 中某个对象或属性:this.params = this.$options.data().params19.vue渲染模板时怎么保留模板中的HTML注释?
答:comments设置为true时,将会保留渲染模板中的HTML注释,默认行为是舍弃他们<template comments> ... </template>20.Vue.observable?
答: Observable API ,通过使用这个api 可以应对一些简单的跨组件状态共享的情况
让一个对象可响应。Vue 内部会用它来处理 data 函数返回的对象。
返回的对象可以直接用于渲染函数和计算属性内,并且会在发生改变时触发相应的更新;也可以作为最小化的跨组件状态存储器。21.style加scoped属性的用途和原理?
答:给HTML的DOM节点加一个不重复属性data-v-hash标志唯一性
在添加scoped属性的组件的每个样式选择器后添加一个等同于’不重复属性’相同的字段,实现类似于
‘作用域的作用,不影响全局
如果组件内部还有组件,,只会给外层的组件里的标签加上唯一属性字段,不影响组件内部引用的组件
在标签上绑定了自定义属性,防止css全局污染
但是很多时候使用ui框架如果加scope就不能覆盖,这个时候一般写sass 会在最外层包裹该组件名的id 就可以不使用scoped 了
是的,不过用/deep/也可以对组件内的样式进行覆盖
用途:防止全局同名CSS污染
原理:在标签加上v-data-something属性,再在选择器时加上对应[v-data-something],即CSS带属性选择器,以此完成类似作用域的选择方式
22.期待vue3.0有什么功能或者改进的地方
答:vue3.0和vue2.0的区别
3.x版本, 只会对‘被用于渲染初始可见部分的数据’创建观察者,3.x的观察者更高效
3.x版本,更精准的变更通知
3.x版本,新加入了TypeScript以及PWA的支持
3.x版本,部分命令发生了变化
23.vue边界情况有哪些?
答:1.访问根实例
1.1 this.$root
1.2 所有的子组件都可以将这个实例作为一个全局的store来访问或者使用
1.3 小型的小项目其实可以直接这样共享数据,大型的项目还是要使用vuex来管理状态
2.访问父组件实例
2.1$parent可以用来从一个子组件访问父组件的实例
2.2只要明确
3.访问子组件实例或子元素
3.1 $refs
4.递归组件
5.控制更新
5.1 this.$forceUpdete()
24.如何在子组件中访问父组件的实例?
答:1,直接在子组件中通过this.parent.event来调用父组件的方法
2.在子组件里面用emit向父组件触发一个事件,父组件监听这个事件
3.父组件把方法传入到子组件中,在子组件里面直接调用这个方法
25.watch的属性用箭头函数定义结果会怎么样?
答:箭头函数绑定了父级作用域的上下文,所以this将不会按照期望指向Vue
实例.
26.在vue项目中如果methonds的方法用箭头函数定义结果会怎么样?
答: 箭头函数绑定了父级作用域的上下文,所以this将不会按照期望指向Vue
实例.
不应该使用箭头函数来定义 watcher 函数 (例如 searchQuery: newValue => this.updateAutocomplete(newValue))。理由是箭头函数绑定了父级作用域的上下文,所以 this 将不会按照期望指向 Vue 实例,this.updateAutocomplete 将是 undefined。
27.vue项目中如何配置favicon图标?
答:vu-cli默认安装了html-webpack-plugin (如果没有,可以npm安装),在html-webpack-plugin插件汇中
添加favicon选项. 在开发环境下配置,在打包后的环境下配置
开发环境配置 webpack-dev.conf.js
new HtmlWebpackPlugin({
filename:’index.html’,
template:’index.html’,
favicon:’src/assets/imgs/favicon.ico’,
inject:true
}),
生成环境(打包后)配置 webpack.prod.conf.js
new HtmlWebpackPlugin({
favicon:’src/assets/img/favicon.ico’,
});
28.有使用过babel-polyfill模块么?用来做什么的?
答:Babel是一个广泛使用的转码器,可以将ES6转码为ES5,从而可以在现有环境执行,
Babel默认只转换新的JavaScript语法(syntax),如箭头函数等,而不转换新的API,比如Iteraror,Generator,Set,Maps,Proxy,Reflect,Symbol
Promise等全局对象。因此需要polyfill;
polyfill(它需要在源代码之前运行),需要让它成为一个dependency(上线时的依赖),
而不是一个devDependency(开发时的依赖)
使用方法:
缺啥补啥; 在package.json添加所需的依赖babel-plugin-transform-xxx
在.babelrc中的plugins项指定使用babel-plugin-transform-xxx插件
代码中不需要显示import/require, .babelrc不需要指定useBuiltIns,webpack.config.js中不需要做额外处理,
一切由babel插件完成转换
29.对vue错误处理的理解?
答:errorCaptured errorHandler
errorCaptured是组件内容钩子,可捕捉本组件与子孙组件抛出的错误,接收error, vm,info三个参数,return false后可以阻止错误继续向上抛出
errorHandler是全局钩子,使用Vue.config.errorHandler配置,接收参数与errorCaptured一致.可用于统一错误处理与错误兜底.
30.在vue事件中传入$event,使用e.target和e.currentTarget有什么区别?
答:event.currentTarget始终指向所绑定的元素,而event.target指向事件发生时的元素.
31.在.vue文件中style是必须的吗?那scripts是必须的么?为什么?
答:都不是必须的,如果是普通组件,那么只能是一个静态html
如果是函数式组件,那么可以使用props等函数式组件属性
32.vue怎么实现强制刷新组件?
答:this.$forceUpdate 强制重新渲染
调用this.$forceUpdate()
使用v-if 指令 — 若刷新某个子组件,则可以通过v-if指令实现.当v-if的值发生变化时,组件都会被重新渲染一遍.可以利用v-fi指令大道强制刷新组件
33.vue自定义事件中父组件怎么接收子组件的多个参数?
答:子组件
this.$emit(‘test’,1,2)
父组件
@test = ‘testFather(arguments,888)’;
methods:{
testFather(vals,userDefined){
console.log(vals[0] * userDefined); //888
}
},
34.你总结的vue最佳实践有哪些?
答:项目目录结构
├── public // index.html
├── src // 业务相关
│ ├── assets // 静态文件(css, images)
│ ├── components // 全局组件
│ ├── layouts // 基础样式布局
│ ├── plugin // 样式及工具引入
│ ├── request // 请求配置
│ ├── router // 路由
│ ├── store // 全局状态管理
│ ├── utils // 工具文件
│ ├── app.vue // 入口文件
│ ├── main.js // 主要配置文件
│ └── views // 页面
├── .eslintrc.js // eslint 检查配置
├── .env.release // 测试环境变量
├── .env.pre-build // 预发环境变量
└── vue.config.js // webpack 打包配置
35.vue给组件绑定自定义事件无效怎么解决?
答:自定义组件无法直接使用@click = ‘function’ 绑定点击事件
需要使用自定义事件 v-on:click.native= ‘function()’
子组件通过this.$emit(‘exchangetab’,t) 注册’exchangetab’事件
父组件在子组件上v-on:exchangetab = ‘function’ 监听 ‘exchangetab’事件,触发事件时执行function
36.vue的属性名称与method的方法名称一样时会发生什么问题?
答:vue会把methods和data的东西,全部代理到vue生成对象中。
会产生覆盖所以最好不要同名
37.vue变量名称如果以_,$开头的属性会发生什么问题?怎么访问到他们的值?
答:实例创建之后,可以通过vm.$data 访问原始数据对象, vue实例也代理了data对象上所有的属性,因此访问vm.a等价于访问vm.$data.a
以_或$开头的属性不会被vue实例代理,因为他们可能和vue内置的属性,api方法冲突,可以使用vm.$data._property的方式访问这些属性
Vue 实例的数据对象。Vue 将会递归将 data 的属性转换为 getter/setter,从而让 data 的属性能够响应数据变化。对象必须是纯粹的
对象 (含有零个或多个的 key/value 对):浏览器 API 创建的原生对象,原型上的属性会被忽略。大概来说,data 应该只能是数据 -
不推荐观察拥有状态行为的对象。
一旦观察过,你就无法在根数据对象上添加响应式属性。因此推荐在创建实例之前,就声明所有的根级响应式属性。
实例创建之后,可以通过 vm.$data 访问原始数据对象。Vue 实例也代理了 data 对象上所有的属性,因此访问 vm.a 等价于访问 vm.$data.a。
当一个组件被定义,data 必须声明为返回一个初始数据对象的函数,因为组件可能被用来创建多个实例。如果 data 仍然是一个纯粹的对象
则所有的实例将共享引用同一个数据对象!通过提供 data 函数,每次创建一个新实例后,我们能够调用 data 函数,从而返回初始数据的
一个全新副本数据对象。
如果需要,可以通过将 vm.$data 传入 JSON.parse(JSON.stringify(…)) 得到深拷贝的原始数据对象。
38.vue使用 v-for遍历对象时,是按什么顺序遍历的?如何保证顺序?
答:1.会先判断是否有iterator接口,如果有循环执行next()方法
2.没有iterator的情况下,会调用Object.keys()方法,在不同的浏览器,JS引擎不能保证输出顺序一致
3.保证对象的输出顺序可以把对象放在数组中,作为数组的元素
39.vue如果想扩展某个现有的组件时,怎么做呢?
答:使用vue.extend 直接扩展
使用vue.mixin全局混入
HOC封装
可以加slot扩展
40.说下inheritAttrs和$attrs和$listeners的使用场景?
答:inheritAttrs
组件传值一般是通过props传值的。inheritAttrs默认值为true,true的意思是将父组件中除了props外的属性添加到子组件的根节点上
(说明,即使设置为true,子组件仍然可以通过$attr获取到props以外的属性)。
$attrs:包含了父作用域中不作为 prop 被识别 (且获取) 的特性绑定 (class 和 style 除外)。当一个组件没有声明任何 prop 时,
这里会包含所有父作用域的绑定 (class和 style 除外),并且可以通过 v-bind=”$attrs” 传入内部组件——在创建高级别的组件时非常有用。
$listener:包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on=”$listeners” 传入内部组件——
在创建更高层次的组件时非常有用。
41.分析下vue项目本地开发完后部署到服务器后报404是什么原因呢?
答:主要问题所在,nginx的配置缺失问题;
1.检查nginx配置,是否正确设置了资源映射条件;
2.检查vue.config.js中是否配置了publicPath,若有则检查是否和项目资源文件在服务器摆放位置一致。
使用了history模式,而后端又没有进行相关资源配置。
42.v-once的使用场景?
43.对vue的表单修饰符.lazy的理解?
答:lazy:使用了这个修饰符将会从“input事件”变成change事件进行同步
44.vue为什么要求组件只能有一个根元素?
答:每一个.Vue的单文件组件本质就是一个vue实例,既然是一个vue实例,它就要有一个入口,如果有多个div,就不无法指定这个vue实例的根入口。
就像一个HTML文档只能有一个根元素一样,多个根元素必将导致无法构成一颗树,所以解释了 <template></template>只有一个<div>根元素。
45.EventsBus注册到全局上时,路由切换时会重复触发事件,如何解决?
答:这是因为我们的事件是全局的,它并不会随着组件的销毁而自动注销,需要我们手动调用注销方法来注销。在组件的 beforeDestroy ,或 destroy 生命周期中执行注销方法,手动注销事件。
beforeDestroy() {
//组件销毁前需要解绑事件。否则会出现重复触发事件的问题
this.bus.$off(this.$route.path);
},
在 beforeDestroy 和 destroy 生命周期中,用 this.$route.path 获取到的其实是下一个页面的 path ,注意这一点,问题即可解决。解决方案也很简单,就是在当前页面用一个变量将当前路由存下来,用这个变量作为事件名注销事件即可。
46.怎么修改vue打包后生成文件路径?
答:1.找到config/index.js文件,在index.js文件中, moudle.exports= {} 中修改assetsSubDirectory的值为路径,如assetsSubDirectoy的默认值是static,而微擎中保存静态文件的路径是/addonc/business/static,则把assetSubDirectory的值改为addonc/buiness/static,则把assetSubDirectory的值改为addonc/buiness/static
2.然后再npm run build打包
3.最后把 index.html 放入微擎的 /template/mobile 文件夹中,当然如果是pc端的话放在 /template 里
4.把上面 static 中的文件放入微擎的 /addonc/business/static 中,这样就完成了模拟路径。
47.你有使用过vue与原生app交互吗?说说vue与原生app交互的方法?
48.使用vue写一个tab切换?
49.vue中什么是递归组件?举个例子
答:Tree View
组件中需要组件调用自身,这就是递归组件,递归组件需要声明name和自己引入自己并声明注册为组件,并且需要使用props进行传参,其还需要一个停止条件,否则会进入死循环。
vue的递归组件和其v-for指令之间的关系和js中的for循环和递归函数一样,一个是有尽头,一个是不知道到底嵌套了多少层级。在vue中我们是数据驱动界面,根据数据来渲染界面,而很多数据我们是从后台获取,事先并不知道它会嵌套多少层,这时候使用v-for指令就不能满足我们的要求了,需要使用递归组件,这就和js中的递归函数一个道理!
50.怎么访问到子组件的实例或者子元素?
答:$refs 只会在组件渲染完成之后生效,并且它们不是响应式的。这仅作为一个用于直接操作子组件的“逃生舱”——你应该避免在模板或计算属性中访问 $refs。
51.在子组件中怎么访问到父组件的实例?
答:this.$prarent.event
在子组件中用$emit向父组件触发一个事件,父组件监听这个事件
父组件把方法传入到子组件中,在子组件里面直接调用这个方法
52.在组件中怎么访问到根实例?
53.说说对Object.defineProperty的理解?
答:可以使用Object.defineProperty定义对象的新属性或修改原有的属性。
Object.defineProperty(obj, prop, descriptor)
obj: 必须 —目标对象
prop:必须 —需定义或修改的属性的名字
descriptor:必须—目标属性所拥有的特性
属性的值是否可以被重写。设置为true可以被重写;设置为false,不能被重写。默认为false。
enumerable:true || false 此属性是否可以被枚举(使用for…in或Object.keys())。设置为true可以被枚举;设置为false,不能被枚举。默认为false。
configurable:true ||false 是否可以删除目标属性或是否可以再次修改属性的特性(writable, configurable, enumerable)。设置为true可以被删除或可以重新设置特性;设置为false,不能被可以被删除或不可以重新设置特性。默认为false。
这个属性起到两个作用:
- 目标属性是否可以使用delete删除
- 目标属性是否可以再次设置特性
**设置的特性总结:
value: 设置属性的值
writable: 值是否可以重写。true | false
enumerable: 目标属性是否可以被枚举。true | false
configurable: 目标属性是否可以被删除或是否可以再次修改特性 true | false
存取器描述:
当使用存取器描述属性的特性的时候,允许设置以下特性属性
var obj = {};
Object.defineProperty(obj,"newKey",{
get:function (){} | undefined,
set:function (value){} | undefined
configurable: true | false
enumerable: true | false
});
注意:当使用了getter或setter方法,不允许使用writable和value这两个属性
54.vue组件里写原生addEventListeners监听事件,要手动去销毁吗?为什么?
答:mounted(){
let drag = document.getElementById(“drag”);
drag.addEventListener(‘mousemove’, this.events, false);
drag.addEventListener(‘mouseup’, this.events, false);
}
methods:{
verify_Success(){
let drag = document.getElementById(“drag”);
drag.removeEventListener(‘mousemove’, this.events, false);
drag.removeEventListener(‘mouseup’, this.events, false);
}
}
是否需要手动销毁?— 销毁与不销毁的区别?
55.vue组件中的定时器要怎么销毁?
答:beforeDestory
定时器很耗性能
方案一:在当前组件的beforeDestroy()生命周期内清除定时器
beforeDestory(){
clearInterval(this.timer);
this.timer = null;
};
方案一有两点不好的地方
1. 需要在这个组件保存这个定时器timer,可以的话最好只有在生命周期可以访问到它.
2.建立代码独立于我们的清理代码,使得我们比较难于程序化的清理我们建立的所有东西
方案二:通过$once事件侦听器在定义完成定时器之后的位置清除定时器
comst timer = setInterval(()=> {
//定时器操作
//
},500)
this.$once(hook:beforeDestory, ()=>{
clearInterval(timer)
})
56.vue组件会在什么时候下被销毁?
答:页面关闭,路由跳转,
手动销毁组件:使用v-if和改变key值来销毁组件
57.使用vue渲染大量数据时应该怎么优化,说下你的思路?
答:1.异步渲染组件:组件渲染太多,影响页面的渲染时间,所以可以延迟组件渲染,可以考虑使用v-if处理
2.可以使用虚拟滚动的组件: 插件 vue-virtual-scroller
58.在vue中使用this应该注意哪些问题?
答:一,axios中this的指向问题
在vue中使用axios做网络请求的时候,会遇到this不指向vue,而为undefined
解决方法:
1.使用箭头函数’=>’ ‘=>’内部的this是词法作用域,由上下文确定(也就是由外层调用者vue来确定)
2.使用hack写法:定义变量绑定this至vue对象
59.有使用过JSX么?说说对JSX的理解?
答:JSX:JavaScript XML,一种在React组建内部构建标签的类XML语法(增强React程序组件的可读性)
JSX可以看作是javascript的拓展,看起来像XML,使用react,可以进行JSX语法到javascript的转换
例子: const element =
Hello, world
60.说说组件的命名规范?
答:驼峰?
单文件组件的文件名要么PascalCase这类,要么pascal-case这类
组件内容书写顺序:
- components
- props
- data
- created
- mounted
- activited
- update
- beforeRouteUpdate
- metods
- filter
- computed
- watch
61.怎么配置vue2.0+ 支持TypeScript写法?
答:1.安装插件
npm i vue-class-component vue-property-decorator —save // 安装vue的官方插件
npm i ts-loader@3.1.1 typescript@2.7.2 —save-dev //(此处安装已经指定版本了的)
npm i tslint tslint-loader tslint-config-standard —save-dev // 此处可以先不安装,但是以后也还是会装上的
2.到build文件夹下的webpack.base.conf.js文件将里面的部分代码替换
entry:’./src/main.js’
extensions:[‘.js’,’.ts’,’.tsx’,’.vue’,’.json’]
在module里面的rules加上
{
test:/.tsx?$/,
loader:’ts-loader’,
exclude:/node_modules/,
options:{
appendTsSuffixTo:[/.vue$/]
}
}
3.在项目根路径(.babelrc统计目录)下添加tsconfig.json
{
“include”: [ “src/*/“ ],
“exclude”: [ “node_modules” ],
// 编译选项
“compilerOptions”: {
// 是否以严格模式解析
// “strict”: true,
// 解析非相对模块名的基准目录
// “baseUrl”: “.”,
// 输出目录
// “outDir”: “./output”,
// 移除注释
// “removeComments”: true,
// 指定特殊模块的路径,如jQuery
// “paths”: {
// “jquery”: [
// “node_modules/jquery/dist/jquery”
// ]
// },
// 运行从没有设置默认到处的模块中默认导入
“allowSyntheticDefaultImports”: true,
// 启用装饰器
“experimentalDecorators”: true,
// 运行便于JavaScript文件
“allowJs”: true,
// 采用的模块系统
“module”: “commonjs”,
// 编译输出目标es版本
“target”: “es5”,
// 如何处理模块
“moduleResolution”: “node”,
// 将每个文件作为单独的模块
“isolatedModules”: true,
// 编译过程中需要引入的库文件的列表
“lib”: [
“dom”,
“es5”,
“es6”,
“es7”,
“es2015.promise”
],
// 是否包含可以用于 debug 的 sourceMap
“sourceMap”: true,
“pretty”: true
}
}
4.若是安装了tslint-loader则必须在根目录下配置tslint.json(引入ts的规范)文件
{
“extends”: “tslint-config-standard”,
“globals”: {
“require”: true
}
}
5.在src目录下新建shims-vue.d.ts(告诉typescript .vue文件交给Vue模块处理),因为typescript默认不支持.vue文件
declare module “.vue” {
import Vue from “vue”;
export default Vue;
}
代码中导入.vue文件时一定要加上.vue后缀!!!如:
import HelloWorld from ‘@/components/HelloWorld.vue’
6.改写 .vue文件
先将main.js改为main.ts
import App from ‘./App.vue’
所有的.vue文件中的script标签加上lang=’ts’;
7.使用mixins
在main.ts中引入后,在组件里面中的HTML中可以使用: {{ toDecimal(number, 2) }} ;也可this.toDecimal(number, 2)
8.axios拦截器
9.统一管理api地址
62.<template></template>有什么用?
答:包裹嵌套其它元素,使元素具有区域性,自身具有三个特点:
隐藏性:不会显示在页面中
任意性:可以写在页面的任意地方
*无效性: 没有一个根元素包裹,任何HTML内容都是无效的
63.vue的is特性有使用过么?主要用在哪些方面?
vue中is的属性引入是为了解决dom结构中对放入html的元素有限制的问题
答:有些HTML元素,诸如
- ref获取
101.vue项目做过单元测试么?
答:收藏夹102.vue项目有使用过npm run build —report么?
答:可以通过npm run build —report来调用webpack-bundle-analyzer插件103.如何解决vue打包vendor过大的问题?
答:1.cdn引入各种包
index.html中cdn的方式引入vue、vuex、axios、element-ui、vue-router等包
2. 在使用vue等包的时候,注释掉import引入
在所有使用vue的地方注释掉引入的vue等包,但是Vue.use(axios)、Vue.use(VueRoter)、
Vue.use(vuex)等依然要使用,除了Vue.use(ElementUI), 如果加上这句话,还是会
打包element-ui到vendor.js文件中在main.js
3.打包忽视掉vue等包
在webpack.base.conf.js
4.采用路由懒加载的方式加载路由104.webpack打包vue速度太慢怎么办?
答:
1.使用happyPack,多进程构建
2.把公共文件拆分到webpack的external里面去,没必要每次都去编译
3.开启tree-shaking和对进程压缩.105.vue在开发过程中同时跟N个不同的后端人员联调接口(请求的url不一样)时你该怎么办?
答:为避免联调时重复修改IP,将各位开发人员的地址进行配置,只需启动不同配置即可106.vue要做权限管理该怎么做?如果控制到按钮级别的权限怎么做?
答:1.当前用户的权限列表储存在store里,也可以是其他地方
2.采用自定义指令来实现107.说下你的vue项目结构,如果是大型项目你该怎么划分结构和划分组件呢?
108.在移动端使用vue,你觉得最佳实践有哪些
109.你们项目为什么会选vue而不选择其他的框架
答:Vue.js是一个轻巧、高性能、可组件化的MVVM库,同时拥有非常容易上手的API;
我们都知道单页面应用:页面切换快 ,首屏时间稍慢,SEO差,js 渲染
(多页面应用首屏时间快SEO好,切换慢,htttp 请求)110.对于即将到来的vue3.0特性你有什么了解的吗?
111.vue开发过程中你有使用过什么辅助工具吗?
112.vue和微信小程序写法上有什么区别
答:1.小程序的钩子函数要简单得多
2.VUE:vue动态绑定一个变量的值为元素的某个属性的时候,会在变量前面加上冒号:,例:
小程序:绑定某个变量的值为元素属性时,会用两个大括号括起来,如果不加括号,为被认为是字符串。例:
3.vue中,使用v-if 和v-show控制元素的显示和隐藏
小程序中,使用wx-if和hidden控制元素的显示和隐藏
4.vue:使用v-on:event绑定事件,或者使用@event绑定事件,例如:
//阻止事件冒泡
小程序中,全用bindtap(bind+event),或者catchtap(catch+event)绑定事件,例如:
//阻止事件冒泡
5.113.怎么缓存当前的组件,缓存后怎么更新
答:keep-alive114.你了解什么是高阶组件吗?可否举例说明
答:高阶组件就是一个函数,且该函数接受一个组件作为参数,并返回一个新的组件115.为什么我们写组件的时候可以写在.vue里呢?可以是别的文件名后缀么
116.v-loader是什么?他有什么作用?
答:v-loader会解析文件,提取每个语言块,如有必要会通过其它loader处理,最后将他们组装成一个ComonJS模块,module.exports 出一个Vue.js 组件对象
v-loader支持使用非默认语言,比如CSS预处理器,预编译的HTML模板语言,通过设置语言块的lang属性,
语言块:
4.内联模板
Vue.component(‘my-checkbox’, {
data() {
return { checked: false, title: ‘Check me’ }
},
methods: {
check() { this.checked = !this.checked; }
}
});
5.render函数
Vue.component(‘my-checkbox’, {
data() {
return { checked: false, title: ‘Check me’ }
},
methods: {
check() { this.checked = !this.checked; }
},
render(createElement) {
return createElement(
‘div’,
{
attrs: {
‘class’: ‘checkbox-wrapper’
},
on: {
click: this.check
}
},
[
createElement(
‘div’,
{
‘class’: {
checkbox: true,
checked: this.checked
}
}
),
createElement(
‘div’,
{
attrs: {
‘class’: ‘title’
}
},
[ this.title ]
)
]
);
}
});
6.JSX
Vue.component(‘my-checkbox’, {
data() {
return { checked: false, title: ‘Check me’ }
},
methods: {
check() { this.checked = !this.checked; }
},
render() {
return
{ this.title }
}
});
7.单文件组件
123.SPA单页面的实现方式有哪些
答:hash
全局监听hash的变化 进行切换124.说说你对SPA单页面的理解,它的优缺点分别是什么
答:
首先:SPA的英文是single-page application ,整个项目中
只有一个页面。其次,单页面的实现思路:就是在 Web 页面
初始化时加载所有的 HTML、JavaScript 和 CSS,页面的内容
的变化,靠动态创建dom。也就是一旦页面加载完成,SPA 不会
因为用户的操作而进行页面的重新请求(加载)或跳转;取而代之
的是利用路由机制实现 HTML 内容的动态变换,UI 与用户的交互,
避免页面的重新加载。
优点:
第一点:用户体验好、快,内容的改变不需要重新加载整个页面,避免了不必要的跳转和重复渲染;
第二点:基于上面一点,SPA 对服务器的压力小;
第三点:前后端职责分离,架构清晰,前端进行交互逻辑,后端负责数据处理;
缺点:
第一点:初次加载耗时多,为实现单页 Web 应用功能及显示效果,需要在加载页面的时候将
JavaScript、CSS 统一加载,部分页面按需加载;
第二点:前进后退路由管理,由于单页应用在一个页面中显示所有的内容,所以不能使用
浏览器的前进后退功能,所有的页面切换需要自己建立堆栈管理;
第三点:SEO 难度较大,由于所有的内容都在一个页面中动态替换显示,所以在
SEO 上其有着天然的弱势。125.说说你都用过vue做过哪些类型的项目
答: 商品中心
CRM
移动端—
4个 —
5个 —126.在vue项目中,如何引入第三方库(比如jQuery)?有哪些方法可以做到?
答:1.直接在main.js文件中通过import引入即可全局使用
import $ form ‘./lib/jquery-1.1-.2.min’
2. 使用 npm install jquery —save 安装jquery
修改配置文件 webpack.base.conf.js 在module.exports中加入
externals:{
jqeury:’window.$’
}
在需要的组件中通过以下方式引入:
var $ = require(‘jqeury’)127.使用vue手写一个过滤器
答:vue.filters
{{ message | capitalize}}
在一个组件的选项中定义本地的过滤器
filters"{
capitalize:function (value){
if (!value) return ‘’
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
}
}
或者在创建Vue实例之前全局定义过滤器
Vue.filter(‘capitalize’, function (value) {
if (!value) return ‘’
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
})
new Vue({
// …
})128.有使用过render函数吗?有什么好处
答:
Vue.component(‘anchored-heading’,{
render:function (creatElemnt){
return creatElement(
‘h’ + this.level,
this.$slots.default
)
},
props:{
level: {
type: Number,
required:true
}
})129.写出你常用的指令有哪些
答: v-model v-on v-bind v-if v-else v-for130.手写一个自定义指令及写出如何调用
131.组件进来请求接口时你是放在哪个生命周期?为什么?
答:mounted阶段132.你有使用过事件总线(EventsBus)吗?说说你的理解?
答: EventBus 事件总线
在Vue中可以使用EventBus来作为沟通桥梁的概念,就像是所有组件共同相同的事件中心,可以向该中心注册发送
事件或接收事件,所以组件都可以上下平行地通知其他组件,但也就是太方便所以若使用不慎,就会造成难以维护
的灾难,因此才需要更完善的Vuex作为状态管理中心,将通知的概念上升到共享层次.
如何使用EventBus:
1.初始化: 创建事件总线并将其导出,以便其他模块可以使用或者监听它.可以通过两种方式来处理:
第一种: 新创建一个.js文件 比如 evnet-bus.js
import Vue form ‘vue’
export const EventBus = new Vue()
第二种: 直接在项目的main.js初始化EventBus
Vue.prototype.$EventBus = new Vue() —这种初始化EventBus是一个全局的事件总线.
现在我们已经创建了 EventBus ,接下来你需要做到的就是在你的组件中加载它,并且调用同一个方法,就如你在父子组件中互相传递消息一样。
2.发送事件:
假设你有两个子组件: DecreaseCount 和 IncrementCount ,分别在按钮中绑定了 decrease()和 increment() 方法。
这两个方法做的事情很简单,就是数值递减(增) 1 ,以及角度值递减(增) 180 。在这两个方法中,通过
EventBus.$emit(channel: string, callback(payload1,…)) 监听 decreased (和 incremented )频道。
上面的示例,在 DecreaseCount 和 IncrementCount 分别发送出了 decreased 和 incremented频道。
接下来,我们需要在另一个组件中接收这两个事件,保持数据在各组件之间的通讯。
3.接收事件
现在我们可以在组件 App.vue 中使用 EventBus.$on(channel: string, callback(payload1,…))监听
DecreaseCount 和 IncrementCount 分别发送出了 decreased 和 incremented 频道。
{{fontCount}}
{{backCount}}
如果你只想监听一次事件的发生,可以使用 EventBus.$once(channel: string, callback(payload1,…))
4.移除事件监听者
import { eventBus } from ‘./event-bus.js’
EventBus.$off(‘decreased’, {})
你也可以使用 EventBus.$off(‘decreased’) 来移除应用内所有对此事件的监听。或者直接调用
EventBus.$off() 来移除所有事件频道, 注意不需要添加任何参数 。
===
全局EventBus
全局EventBus,虽然在某些示例中不提倡使用,但它是一种非常漂亮且简单的方法,可以跨组件之间共享数据。
它的工作原理是发布/订阅方法,通常称为 Pub/Sub 。
这整个方法可以看作是一种设计模式,因为如果你查看它周围的东西,你会发现它更像是一种体系结构解决方案。
我们将使用普通的JavaScript,并创建两个组件,并演示EventBus的工作方式。
创建全局EventBus
全局事件总线只不过是一个简单的 vue 组件。代码如下:
var EventBus = new Vue();
Object.defineProperties(Vue.prototype, {
$bus: {
get: function () {
return EventBus
}
}
})
现在,这个特定的总线使用两个方法 $on 和 $emit 。一个用于创建发出的事件,它就是$emit ;另一个用于订阅 $on :
var EventBus = new Vue();
this.$bus.$emit(‘nameOfEvent’,{ … pass some event data …});
this.$bus.$on(‘nameOfEvent’,($event) => {
// …
})
接下来的这个示例中,我们创建了一个 ShowMessage 的组件用来显示信息,另外创建一个 UpdateMessage 的组件,用来更新信息。
在 UpdateMessage 组件中触发需要的事件。在这个示例中,将触发一个 updateMessage 事件,这个事件发送了 updateMessage 的频道:
同时在 ShowMessage 组件中监听该事件:
<
最终的效果如下:
从上面的代码中,我们可以看到 ShowMessage 组件侦听一个名为 updateMessage 的特定事件,
这个事件在组件实例化时被触发,或者你可以在创建组件时触发。另一方面,我们有另一个组件
UpdateMessage ,它有一个按钮,当有人点击它时会发出一个事件。这导致订阅组件侦听发出的
事件。这产生了 Pub/Sub 模型,该模型在兄弟姐妹之间持续存在并且非常容易实现。
总结;133.说说vue的优缺点分别是什么?
答:
单页面应用(SPA):通俗一点说就是指只有一个主页面的应用,浏览器一开始要加载所有必须的
html, js, css。所有的页面内容都包含在这个所谓的主页面中。
多页面(MPA): 就是指一个应用中有多个页面,页面跳转时是整页刷新。
单页面的优点:
1、用户体验好,快,内容的改变不需要重新加载整个页面,对服务器压力较小。
2、前后端分离,比如vue项目
3、完全的前端组件化,前端开发不再以页面为单位,更多地采用组件化的思想,代码结构和组织方式更加规范化,便于修改和调整;
单页面的缺点:
1、首次加载页面的时候需要加载大量的静态资源,这个加载时间相对比较长。
2、不利于 SEO优化,单页页面,数据在前端渲染,就意味着没有 SEO。
3、页面导航不可用,如果一定要导航需要自行实现前进、后退。(由于是单页面不能用浏览器的前进后退功能,所以需要自己建立堆栈管理)134.DOM渲染在哪个周期中就已经完成了?
答:mounted中135.第一次加载页面时会触发哪几个钩子?
答:第一次页面加载时会触发 beforeCreate, created, beforeMount, mounted 这几个钩子136.vue生命周期总共有几个阶段?
答:
beforeCreate()
created()
beforeMount()
mounted()
beforeUpdate()
updated()
beforeDestroy()
destored()137.vue生命周期的作用是什么?
答:每个Vue实例在被创建时都要经过一系列的初始化过程—例如,需要设置数据监听,编译模板,将实例挂在到DOM
并在数据变化时更新DOM等.同时在这个过程中也会运行一些叫做生命周期钩子函数,这给了用户在不同阶段添加自己
的代码的机会.例如要通过某些插件操作DOM节点,如想在页面渲染完后弹出广告窗,那我们最早可在mounted中进行138.vue和angluar的异同处?
答: 相同点: 都有双向绑定机制和指令
不同点: ng是一个完整的mvvm框架,vue主要是view层展示
ng双向绑定基于模板编译规则(脏检查),vue是采用es5的get和set机制139.如何引入scss,引入后如何使用?
答:npm下载
npm install -D sass-loader node-sass
在style中
这个自定义组件
可以使用特殊的is特性
64.vue的:class 和:style有几种表达方式
答:1.绑定变量 :class ={clasA:a,classB:b}
2.绑定对象 :class = ‘test’
test:{
color;’red’,
background:’yellow’
}3.绑定数组 :class=”[test1,test2]”
4.绑定三元表达式 :class=’[A>B?’signSpanChange’:’signSpan’]’
65.什么是函数式组件?
答:函数式组件需要将functional设置为true,它没有状态,没有上下文
单文件中函数式组件的实现:
注册组件中函数式组件的实现:
Vue.component(‘my-component’,{
functional:true,
props:{
},
render:functon (createElement,context){
}
})
函数式组件最大的用途就是用它做中间件来实现render方法
//my-components.js
export default {
functional: true,
props: {
render: {
type: Function
},
params: {}
},
render: (h, ctx) => {
//ctx相当于该函数式组件的上下文,相关取值可用ctx.props
//这里可以做相关逻辑处理
return ctx.props.render(h, params)
}
}
将该函数式组件注册为全局组件(在使用组件内部引入的时候,总数注册不上,用全局注册后解决),再在需要的组件中使用
这样不但节省了开销,而且复用性高
66.vue怎么改变插入模板的分隔符?
答:var vm = new Vue({
el:’#app’,
delimiters:[‘${‘,’}’], //修改定界符”{{}}”
date:{
}
})
分隔符就成了 ‘${}’
67.组件中写的name选项有什么作用?
答:1.当项目使用keep-alive时,可搭配组件name进行缓存过滤
举例:有个组件命名为detail,其中dom加载完毕后我们在钩子函数mounted中进行数据加载
因为我们在App.vue中使用了keep-alive导致我们第二次进入的时候页面不会重新请求,即触发mounted函数。
有两个解决方案,一个增加activated()函数,每次进入新页面的时候再获取一次数据。
还有个方案就是在keep-alive中增加一个过滤,如下图所示:
2.DOM做递归组件时
比如说detail.vue组件里有个list.vue子组件,递归迭代时需要调用自身name
{{item.title}}
list数据:
const list = [{
“title”: “A”,
“children”: [{
“title”: “A-A”,
“children”: [{
“title”: “A-A-A”
}]
},{
“title”: “A-B”
}]
}, {
“title”: “B”
}, {
“title”: “C”
}, {
“title”: “D”
}]
3.当你用vue-tool时
vue-devtolls调式工具里显示的组件名称是由vue组件name决定的
68.说说对provide和inject的理解?
答: provide:Object | () => Object
inject:Array | { [key: string]: string | Symbol | Object }
provide 和 inject 主要为高阶插件/组件库提供用例。并不推荐直接用于应用程序代码中。是2.2.0版本 新增的。
这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。
provide 选项应该是一个对象或返回一个对象的函数。该对象包含可注入其子孙的属性。在该对象中你可以使用 ES2015 Symbols 作为 key,但是只在原生支持 Symbol 和 Reflect.ownKeys 的环境下可工作。
inject 选项应该是:
一个字符串数组,或
一个对象,对象的 key 是本地的绑定名,value 是:
在可用的注入内容中搜索用的 key (字符串或 Symbol),或
一个对象,该对象的:
from 属性是在可用的注入内容中搜索用的 key (字符串或 Symbol)
default 属性是降级情况下使用的 value
使用场景:由于vue有$parent属性可以让子组件访问父组件。但孙组件想要访问祖先组件
就比较困难。通过provide/inject可以轻松实现跨级访问祖先组件的数据
提示:provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了
一个可监听的对象,那么其对象的属性还是可响应的。
69.开发过程有使用过devtools吗?
70.说说对slot的理解?slot的使用场景有哪些?
答:插槽 —官网+例子 占用占坑的以上,先占坑后面有其他具体的内容来替换代替。
分为匿名slot和具名slot
71.使用过动态组件么?说说你的理解?
72.prop验证的type类型有哪几种?
答:如果是 prop 是静态传值,则必须是 String 类型
如果是 prop 是动态传值,则可以验证任意类型
示例,如果必须要传一个Number,就必须使用 bind
73.prop是怎么做验证的?可以设置默认值么?
答:type 还可以是一个自定义的构造函数,并且通过 instanceof 来进行检查确认
设置默认值default.
74.怎么缓存当前打开的路由组件?缓存后想更新当前组件怎么办?
答:使用keep-alive ,
定义cached
然后操作cached数据,进行删除
75.说说你对vue组件的设计原则的理解?
答:页面上把每个独立可以交互的区域视为一个组件
每个组件对应一个工程目录,组件所需要的各种资源在这个目录下就近维护
页面不过是组件的容器,组件可以嵌套自由组合形成完整的页面
76.了解vue的diff算法吗?
答:1.当数据发送变化时,vue是怎么更新节点的
先根据真实DOM生成一颗virtual DOM 当virtual DOM的某个节点的数据改变后会生成一个新的VNode,
然后VNode和oldNode作对比,发现有不一样的地方就直接修改在真实的DOM上,然后使oldNode的值为VNode
diff的过程就是调用名为patch的函数,比较新旧节点,一边比较一边给真实的DOM打补丁
2.virtual DOM 和真实DOM的区别?
virtual DOM是将真实的DOM的数据抽取出来,以对象的形式模拟树结构。
3.diff的比较方式
在采取diff算法比较新旧节点的时候,比较只会同层级进行,不会跨层级比较.
4.diff流程图
当数据发生改变时,set方法会让调用Dep.notify通知所有订阅者的Watcher,订阅者就会调用patch给真实的
DOM打补丁,更新相应的视图
77.vue如何优化首页的加载速度?
答;
1.减小入口文件体积:
常用手段是路由懒加载,开启路由懒加载之后,待请求的页面会单独打包js文件,使得入口文件index.js变小,
开启懒加载之后,js是如何请求加载的?
2.静态资源本地缓存:
HTTP缓存,设置Cache-Control,Last-Modified ,Etag等响应头,
Service Worker离线缓存,缺点:需要在HTTPS站点下
3.开启GZip压缩
4.使用SSR
我们可以把页面需要的请求放到Vue-Router的守卫中执行,意思是在路由beforeEnter之前就可以请求待加载
页面中所有组件需要的数据,此时待加载页面的Vue组件还没开始渲染,而Vue组件开始渲染的时候我们就可以用Vuex里面的数据了。
78.vue打包最终的文件有哪些?
79.ajax,fetch,axios三者有什么区别?
答: axios是一个基于promise的HTTP库,可以用在浏览器和nodejs中
1.特点:
从浏览器中创建 XMLHttpRequests
从nodejs创建http请求
支持Promise的API
拦截请求和响应
转换请求I数据和响应数据
取消请求
自动转换JSON数据
客户端支持防御XSRF
—-
2.安装 npm i axios -D
—-
3.axios 的简单示例
3.1 get请求
let vueobj =this;
axios.get(‘api/goodslists’,{
params:{‘goodsid’:’01003’}
})
.then(function(response){
console.log(response.data);
vueobj.goodslist =response.data
})
.catcha(function(error){
console.log(error)
});
4.axios的API
5.axios的请求配置和响应数据格式
6.axios的拦截器
—-
ajax,jquery ajax,axios,fetch的区别
ajax: 最早出现的发送后端请求技术,隶属于原始js中,核心使用XMLHttpRequest对象,多个请求之间如果有先后顺序的话,就会出现回调地狱.
jquery ajax: 是jquery框架中的发送后端请求技术,由于jquery是基于原始的基础上做的封装,所以,jquery ajax自然也是原始ajax的封装
fetch: fetch号称是AJAX的替代品,是在ES6出现的,使用了ES6中的promise对象。Fetch是基于promise设计的。Fetch的代码结构比起ajax简单多了,参数有点像jQuery ajax。但是,一定记住fetch不是ajax的进一步封装,而是原生js。Fetch函数就是原生js,没有使用XMLHttpRequest对象。
axios: axios不是原生JS的,需要进行安装,它不光可以在客户端使用,也可以在nodejs端使用。Axios也可以在请求和响应阶段进行拦截, 同样也是基于promise对象的。
80.vue能监听到数组变化的方法有哪些?为什么这些方法能监听到呢?
答: comupted()
watch()
methods()
81.vue中是如何使用event对象的?
答:
v-on 不简单是 addEventListener 的语法糖。在 jquery 中,我们传入到
bind 方法中的回调,只能是一个函数表类型的变量或者一个匿名函数,传递
的时候,还不能执行它(在后面加上一堆圆括号),否则就变成了取这一个
函数的返回值作为事件回调。而我们知道,vue 的 v-on 指令接受的值可以是
函数执行的形式,比如 v-on:click=”click(233)” 。这里我们可以传递任何
需要传递的参数,甚至可以不传递参数
var app = new Vue({
el: ‘#app’,
methods: {
click(event, val) {
console.log(typeof event); // object
}
}
});
1.使用不带圆括号的形式,event 对象将被自动当做实参传入;
2.使用带圆括号的形式,我们需要使用 $event 变量显式传入 event 对象。
82.vue首页白屏是什么问题引起的?如何解决?
答:vue项目是单页面应用,需要将所有需要的资源都下载到浏览器端并解析
原因:首页需要加载比较大的js文件,解决方法:在路由返回前添加loading
解决方法:
优化webpack 减少模块打包体积,code-split按需加载
服务端渲染,在服务端实现拼装好首页所需的html
首页加载loading或骨架屏
服务端开启gzip压缩
打包文件分包,提取公共文件包
双向数据绑定:
(ng里面的ng-model和vue里面的v-model)
value的单向绑定+ onchange事件侦听 的一个语法糖
83.说说对单向数据流和双向数据流的理解?
答:简单的单向数据流(unidirectional data flow)是指用户访问View,
View发出用户交互的Action,在Action里对state进行相应更新。state更新
后会触发View更新页面的过程。这样数据总是清晰的单向进行流动,便于
维护并且可以预测。
84.移动端ui你用的哪个ui库?有遇到过什么问题么?
答;
1.vonic
2.vux
3.Mint UI
4.Muse-UI
5.Vant
6.Cube-UI
7.vue-ydui
8.Mand-Mobile
9.v-charts
10.Vue Carbon
11.Quasar
12.Vue-recyclerview
13.Vue.js modal
14.Vue Baidu Map
15. Onsen UI
85.nextTick的原理?
答:在下次DOM更新循环结束之后执行延迟回调,在修改数据之后立即使用这个
方法,获取更新后的DOM
vue是用MutationObserver监听DOM更新完毕的!
事件循环(Event Loop)
86.v-clock和v-pre的理解?
答: v-pre 原样输出
v-clock 渲染完之后才显示,防止将{{message}}类似的输出到页面
87.写出你知道的表单修饰符和事件修饰符?
答:
表单修饰符: v-model.lazy 、v-model.number 、v-model.trim
事件修饰符: @click.stop 、@submit.prevent 、 @click.self 、@click.once 、 @click.capture
@:scroll.passive 、 @click.native
88.对proxy的理解?
答:Proxy:用于修改某些操作的默认行为,可以理解成,在目标对象之前假设一层‘拦截’,外界对该对象的访问,
都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写. —Proxy对象就是可以让你
对javascript中的一切合法对象的基本操作进行自定义,然后用你自定义的操作去覆盖其对象的基本操作,—
—重写其所属类或构造函数中的基本操作.
let proxy =new Proxy(target,handler)
target — 你要对其基本操作进行自定义的对象,可以是javascript中的任何合法对象
handler — 你要自定义操作方法的一个对象
proxy —是一个被代理后的新对象,拥有target的一切属性和方法,只不过其行为和结果是在handler中自定义的.
—-在一定程度上可以看成是对target的引用.
1、通过对某一操作进行拦截,能实现自己想要的效果,而且这种拦截属于一种不公开的操作,具备很好的安全性。
2、通过对proxy对象的操作,来达到对目标对象的操作,很好的隐藏了目标对象,降低目标对象的曝光度,实现了对目标对象的保护效果。
3、相比较Object.defineProperty()而言,proxy功能更强大,不仅能拦截对象的属性,还能对整个对象,如数组和函数进行拦截。而且proxy的拦截种类更多。
proxy的拦截方法:
get(target, propKey,receiver): 拦截某个属性的读取操作,可以接受三个参数,依次为目标对象、属性名和 proxy 实例本身
(严格地说,代表原始的读操作所在的那个对象),其中最后一个参数可选,一般情况下指向的是proxy对象,但是如果proxy作为
其他对象的原型时,则指向读取该属性的对象了。
set(target, propKey, value,receiver): 用来拦截某个属性的赋值操作,可以接受四个参数,依次为目标对象、属性名、属性值
和 Proxy 实例本身,其中最后一个参数可选。返回一个布尔值。
运用: 利用set方法,可以数据绑定,即每当对象发生变化时,会自动更新 DOM。结合get和set方法,就可以定义私有属性。
注意: 如果目标对象自身的某个属性,不可写且不可配置(即configurable和writable都为false),那么set方法将不起作用。
has(target, propKey): 用来拦截HasProperty操作,用来判断对象是否具有某个属性。典型的操作就是in运算符。has方法
可以接受两个参数,分别是目标对象、需查询的属性名。返回一个布尔值。就算你自定义返回的不是布尔值,也会转换布尔值。
注意: 1、如果某个属性的configurable被设置为false或者整个对象被设置为禁止扩展的话。使用in运算符时,被has方法
拦截时,必须返回target[key]所对应的值,否则会报错。
2、has拦截的不是hasProperty()方法,也不会拦截has…in操作。
deleteProperty(target, propKey): 用于拦截delete操作。返回一个布尔值。
该方法主要是拦截delete操作,并在deleteProperty执行真正想做的操作,同时对proxy的属性执行delete操作,
并不会真正将该属性删除。 不可以删除目标对象自身的不可配置(configurable)的属性,否则报错。
ownKeys(target): 拦截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、
for…in循环等操作。该方法返回目标对象所有自身的属性的属性名。
注意:1、使用Object.keys方法时,有三类属性会被ownKeys方法自动过滤 a、目标对象上不存在的属性 b、属性名为 Symbol 值
c、不可遍历(enumerable)的属性
2、ownKeys()的返回必须是一个数组,不然会报错。且返回的数组成员必须是字符串或者Symbol值(即可以为对象属性的值)。
3、obj对象的某属性如果不可配置的,这时ownKeys方法返回的数组之中,必须包含该属性,否则会报错。 4、如果目标对象是
不可扩展的(non-extensible),这时ownKeys方法返回的数组之中,必须包含原对象中所有可被返回的属性(如Symbol属性、
不可枚举属性以及不存在的属性都不能被返回,),且不能包含多余的属性,否则报错。
getOwnPropertyDescriptor(target, propKey): 拦截Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象。
defineProperty(target, propKey, propDesc): 拦截Object.defineProperty(proxy, propKey, propDesc)、
Object.defineProperties(proxy, propDescs)以及set操作,返回一个布尔值。该方法的作用在于拦截这些操作,
然后自定义操作,被拦截的操作并不能生效。
preventExtensions(target): 拦截Object.preventExtensions(proxy),返回一个布尔值。该方法必须返回一个布尔值,
否则会被自动转为布尔值。该方法有一个强制,只有目标对象不可扩展时,才能返回true,否则会报错
getPrototypeOf(target): 拦截获取对象原型的操作。具体来说,拦截下面这些操作。
注意: 1、该方法必须返回一个对象或者null,否则会报错。
2、另外,如果目标对象不可扩展(non-extensible), getPrototypeOf方法必须返回目标对象的原型对象。
isExtensible(target): 拦截Object.isExtensible(proxy),返回一个布尔值。该方法只能返回布尔值,
跟前面那些只能返回布尔值方法一样,否则返回值会被自动转为布尔值。同时它的返回值必须与目标对象的
isExtensible属性保持一致,否则就会抛出错误。
setPrototypeOf(target, proto): 拦截Object.setPrototypeOf(proxy, proto),返回一个布尔值。如果目标
对象是函数,那么还有两种额外操作可以拦截。
apply(target, object, args): 拦截函数的调用、以及call、apply和bind操作,比如proxy(…args)、
proxy.call(object, …args)、proxy.apply(…),proxy.bind(…)()。
construct(target, args): 拦截 Proxy 实例作为构造函数调用的操作,比如new proxy(…args)。
construct方法返回的必须是一个对象,否则会报错。同时拦截对象target也必须是一个可以被new的对象
89.有自己用vue写过UI组件库么?
90.vue怎么实现一个换肤功能?
91.vue中使用过echarts吗?踩过哪些坑?如何解决的?
92.教一个2-3年经验前端经验的同事使用vue,你该怎么教
93.vue性能优化的方法有哪些?
94.SSR解决了什么问题?有做过SSR吗?你是怎么做的?
95.你觉得认为的vue开发规范有哪些?
96.vue部署上线前需要做哪些准备工作?
97.vue过渡动画实现的方式有哪些?
98.vue在crented和mounted这两个生命周期中请求数据有什么区别?
99.vue父子组件双向绑定的方法有哪些?
100.vue怎么获取DOM节点?
答: 1.选择器获取 let canvas = doucument.querySeletor(‘#cvs’);
