vue组织架构图插件_VUE常见面试题(三)

1、你知道vue的模板语法用的是哪个web模板引擎的吗?说说你对这模板引擎的理解。

使用的Mustache模版。
模板引擎:
负责组装数据,以另外一种形式或外观展现数据。
优点:

  1. 可维护性(后期改起来方便);

  2. 可扩展性(想要增加功能,增加需求方便);

  3. 开发效率提高(程序逻辑组织更好,调试方便);

  4. 看起来舒服(不容易写错)

2、你知道v-model的原理吗?

v-model只是一个语法糖,其内部实现原理就是使用v-bindinput事件监听值的改变。

changeValue(e){
value = e.target.value
}

3、使用过vue开发过多语言项目吗?说说你的做法

使用vue-i18n。具体使用请参考vue-i18n。

  1. 安装:npm install vue-i18n –save-dev

  2. 创建语言文件:language-zh.js和language-en.js 分别对应中文和英文。

  3. 在main.js中引入。

  4. 切换语言。

language-zh.js:

export const lang = {
home:'首页‘,
name:'姓名'
}

language-en.js:

export const lang = {
home:'home‘,
name:'name'
}

main.js:

import VueI18n from 'vue-i18n'
Vue.use(VueI18n) // 通过插件的形式挂载,通过全局方法 Vue.use() 使用插件const i18n = new VueI18n({
locale: 'zh', // 语言标识 //this.$i18n.locale // 通过切换locale的值来实现语言切换
messages: {
'zh': require('./VueI18n/language-zh'), //
'en': require('./VueI18n/language-en')
}
})
Vue.config.productionTip = false

new Vue({
el: '#app',
router,
i18n,
components: { App },
template: ''
})

切换语言:

changeLaguages () {
console.log(this.$i18n.locale)
let lang = this.$i18n.locale === 'zh' ? 'en' : 'zh'
this.$i18n.locale = lang
}

4、在使用计算属性时,函数名可以和data数据源中的属性同名吗?为什么?

不可以。因为无论是计算属性、data、还是props,最终都会挂载到vm实例上,因此三者不可以同名。
src/core/instance/state.js#L202这里,会做一个检查。3b421b45740a2cda63d8a9893c697ee1.png
而且在初始化vm的时候,会依次初始化props、mehtods、data,computed等。这是初始化的源码:

export function initState (vm: Component) {
vm._watchers = []
const opts = vm.$options
if (opts.props) initProps(vm, opts.props)
if (opts.methods) initMethods(vm, opts.methods)
if (opts.data) {
initData(vm)
} else {
observe(vm._data = {}, true /* asRootData */)
}
if (opts.computed) initComputed(vm, opts.computed)
if (opts.watch && opts.watch !== nativeWatch) {
initWatch(vm, opts.watch)
}
}

5、vue中data数据源中的属性可以和methods中的方法名重名吗?为什么?

不可以。
在初始化data的时候,程序会进行检查,src/core/instance/state.js#L113,在initState函数:

function initData (vm: Component) {
let data = vm.$options.data
data = vm._data = typeof data === 'function'
? getData(data, vm)
: data || {}
if (!isPlainObject(data)) {
data = {}
process.env.NODE_ENV !== 'production' && warn(
'data functions should return an object:\n' +
'https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function',
vm
)
}
// proxy data on instance
const keys = Object.keys(data)
const props = vm.$options.props
const methods = vm.$options.methods
let i = keys.length
while (i--) {
const key = keys[i]
if (process.env.NODE_ENV !== 'production') {
if (methods && hasOwn(methods, key)) {//这里会对同名属性和方法进行警告
warn(
`Method "${key}" has already been defined as a data property.`,
vm
)
}
}
if (props && hasOwn(props, key)) {//这里会对同名的props和属性进行警告
process.env.NODE_ENV !== 'production' && warn(
`The data property "${key}" is already declared as a prop. ` +
`Use prop default value instead.`,
vm
)
} else if (!isReserved(key)) {
proxy(vm, `_data`, key)
}
}
// observe data
observe(data, true /* asRootData */)
}

5、怎么给vue定义全局方法?

  1. 挂载到Vue的原型上,即:Vue.prototype.methodsName = function(){}。

  2. 使用mixin,即Vue.use(mixins)。

6、vue2.0中不再支持在v-html中使用过滤器了怎么办?

  1. 使用全局方法。推荐

  2. 使用filters过滤器。

  3. 使用computed。

  4. 使用methods。

全局方法:

Vue.prototype.msg = function(msg){ 
 return msg.replace("\n","
")
};
<div v-html="msg(content)">div>

filters过滤器:

filters:{
msg:function(msg){
return msg.replace(/\n/g,"
")
}
}

computed:

computed:{
msg:function(msg){
return msg.replace(/\n/g,"
")
}
}

mehtods:

methods:{
msg:function(msg){
return msg.replace(/\n/g,"
")
}
}

7、使用vue后怎么针对搜索引擎做SEO优化?

  1. SSR服务端渲染

  2. NUXT同构

  3. prerender-spa-plugin 预渲染

8、和keep-alive相关的生命周期有哪些?描述下这些生命周期

activated 和 deactivated。

  1. activated:当页面进入的时候,依次触发:created –> mounted –> activated。

  2. deactivated:当退出页面的时候触发deactivated,当在此前进或者后退的时候之后触发activated。

9、你知道vue中key的原理吗?

src\core\vdom\patch.js - updateChildren()

1、key的作用主要是为了高效的更新虚拟DOM,其原理是vue在patch过程中通过key可以精准判断两个节点是否是同一个,从而避免频繁更新不同元素,使得整个patch过程更加高效,减少DOM操作量,提高性能。
2、同时,在vue中使用相同标签名的元素过渡的时候需要使用key进行区分,否则vue之后更新其内部属性而不会触发过渡效果。

10、 vue如何重置data?

this.$data: 获取当前状态下的data。
this.$options.data():获取当前组件初始化状态下的data。
so:Object.assgin( this.$data,this.$options.data() )

11、谈谈你对mvc 、mvp和mvvm的理解?

在web1.0时代,并没有web前端的概念,当时开发一个web应用基本是由asp、.net、java等后台人员完成。项目通常包含html、css、js等文件。这样做的优势就是开发简单快捷。缺点就是jsp文件难以维护。

  • mvc:为了解决上述问题,使前后端职责更加清晰、代码更容易维护、于是mvc开发模式和框架应运而生。在这个模式下,前端主要负责v,即视图层view,前端使用html模版渲染html。后台负责c层和m层,即控制层和数据层。当用户发起请求时,后端根据用户请求路径,返回相应的页面。这样的缺点就是前端页面开发效率不高、前后端职责还不够清晰明确。

085eaaea884af53dbafa6075ac0dbb52.png
在web2.0时代,随着ajax的出现,让前端可以使用ajax和后台进行交互,前后端职责更加清晰。于是浏览器和服务器之间的整体架构变成了这样:5ebe5022cc432f9987e60ebfcf6c8f5c.png

页面通过ajax与服务器进行交互,前端人员只负责页面部分,数据部分由后台获取。而且使用ajax可以局部刷新页面,大大降低了服务端压力和流量消耗,而且对用户端体验也更加友好。

  • mvp:随着业务的增加,我们对项目的不断跌倒,就会导致view层越来越庞大,controller层显得越发单薄。于是人们就这v层和m层中间添加了p层。由p层负责m层和v层之间的数据流动,防止二者直接进行数据流动。

e2a067a7ad0c14f3e943703b2213740c.png

我们可以通过看到,presenter负责和Model进行双向交互,还和View进行双向交互。这种交互方式,相对于MVC来说少了一些灵活,VIew变成了被动视图,并且本身变得很小。虽然它分离了View和Model。但是应用逐渐变大之后,导致presenter的体积增大,难以维护。

  • mvvm:首先,何为MVVM呢?MVVM可以分解成(Model-View-VIewModel)。ViewModel可以理解为在presenter基础上的进阶版。如图所示:

503e1aae555965e177a25a2abd72d228.png

ViewModel通过实现一套数据响应式机制自动响应Model中数据变化;
同时Viewmodel会实现一套更新策略自动将数据变化转换为视图更新;
通过事件监听响应View中用户交互修改Model中数据。
这样在ViewModel中就减少了大量DOM操作代码。
MVVM在保持View和Model松耦合的同时,还减少了维护它们关系的代码,使用户专注于业务逻辑,兼顾开发效率和可维护性。

总结:

  • 这三者都是框架模式,它们设计的目标都是为了解决Model和View的耦合问题。

  • MVC模式出现较早主要应用在后端,如Spring MVC、ASP.NET MVC等,在前端领域的早期也有应用,如Backbone.js。它的优点是分层清晰,缺点是数据流混乱,灵活性带来的维护性问题。

  • MVP模式在是MVC的进化形式,Presenter作为中间层负责MV通信,解决了两者耦合问题,但P层过于臃肿会导致维护问题。

  • MVVM模式在前端领域有广泛应用,它不仅解决MV耦合问题,还同时解决了维护两者映射关系的大量繁杂代码和DOM操作代码,在提高开发效率、可读性同时还保持了优越的性能表现。

12、你知道style加scope属性的原理和作用吗

用途:防止全局同名CSS污染
原理:在标签加上v-data-something属性,再在选择器时加上对应[v-data-something],即CSS带属性选择器,以此完成类似作用域的选择方式。

13、vue边界情况有哪些

  1. 访问根实例:this.$root

  2. 访问父组件:this.$parent

  3. 访问子组件:this.$refs

  4. 依赖注入:provide inject

  5. 组件递归引用

14、子组件如何访问父组件

  1. 直接在子组件中使用this.$parent.methods

  2. 子组件使用$emit发送一个事件,在父组件中设置监听

  3. 父组件将事件通过属性传递给子组件

15、watch/methods中使用箭头函数会怎么样?

不能使用箭头函数。因为箭头函数的this默认绑定父级作用域,而不是vue实例。如果使用的是npm安装的vue,则此时this指向当前组件:d376f938279fe3f4ccc0d49ce3627195.png
如果使用的是script标签,则this指向window。

16 、vue如何配置favicon

  • 在插件配置中的HtmlWebpackPlugin中配置

new HtmlWebpackPlugin({
template: 'src/index.html',
favicon:''
})
  • 在html模版中配置:

<link rel="icon" href="/assets/title.png" type="image/x-icon" />

17、vue的错误处理你知道多少?

  • errorHandler

具体请看:errorHandler

Vue.config.errorHandler = function (err, vm, info) {
// handle error
// `info` is a Vue-specific error info, e.g. which lifecycle hook
// the error was found in. Only available in 2.2.0+
}

其中:err指的是error对象本身,info指的是错误信息,vm指的是vue实例。

  • warnHandler

Vue.config.warnHandler = function (msg, vm, trace) {
// `trace` is the component hierarchy trace
console.log(`Warn: ${msg}\nTrace: ${trace}`);
}

trace代表组件树。
例如:我们引入一个不存在的变量

<div id="app" v-cloak>
Hello, {{name}}
</div>

就会提示:

Warn: Property or method 'name' is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.
Trace:

(found in <Root>)
  • renderError:和前面两个不同,这个技巧不适用于全局,和组件相关。并且只适用于非生产环境。

const app = new Vue({
el:'#app',
renderError (h, err) {
return h('pre', { style: { color: 'red' }}, err.stack)
}
})

举个栗子:

<div id="app" v-cloak>
Hello, {{name2}}
</div>

<script>
const app = new Vue({
el:'#app',
computed:{
name2() {
return x;
}
}
})
</script>
ReferenceError: x is not defined
at Vue.name2 (pen.js:45:7)
at Watcher.get (https://unpkg.com/vue@2.6.11/dist/vue.js:4478:27)
at Watcher.evaluate (https://unpkg.com/vue@2.6.11/dist/vue.js:4583:23)
at Proxy.computedGetter (https://unpkg.com/vue@2.6.11/dist/vue.js:4832:19)
at Proxy.eval (eval at createFunction (https://unpkg.com/vue@2.6.11/dist/vue.js:11649:14), <anonymous>:3:68)
at Vue._render (https://unpkg.com/vue@2.6.11/dist/vue.js:3551:24)
at Vue.updateComponent (https://unpkg.com/vue@2.6.11/dist/vue.js:4067:23)
at Watcher.get (https://unpkg.com/vue@2.6.11/dist/vue.js:4478:27)
at new Watcher (https://unpkg.com/vue@2.6.11/dist/vue.js:4467:14)
at mountComponent (https://unpkg.com/vue@2.6.11/dist/vue.js:4074:5)
  • errorCaptured

类型:(err: Error, vm: Component, info: string) => ?boolean
当捕获一个来自子孙组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回 false 以阻止该错误继续向上传播。

18、vue文件中style、script是必须的吗

style不是必须的。但是script是必须的:export default {}

19、如果vue变量名出现以_或者$开头的时候,会出现什么情况?

会报undefined。因为在initState的时候,vm会代理所有的data,如果出现有_或者$开头的变量名,可能会和vm内部属性冲突,vue不会代理该属性。可以通过vm.$data.访问。

20、vue使用v-for遍历对象的时候,是按什么顺序遍历的?如何保证遍历顺序?

首先,会判断对象是否有iterator接口,如果有,则循环执行next()方法。
没有iterator接口的情况下,使用Object.keys()遍历,但是在不同浏览器的情况下,遍历的结果不可能完全一致。
可以将对象放在数组中,遍历数组可以保证遍历顺序。

21、vue想扩展组件时该怎么做?

  • Vue.mixin混入

  • Vue.extend

  • solt

22、vue中$attrs 和 $listeners的使用场景

组件传值的时候会用到 爷爷在父亲组件传递值,父亲组件会通过$attrs获取到不在父亲props里面的所有属性,父亲组件通过在孙子组件上绑定$attrs 和 $listeners 使孙组件获取爷爷传递的值并且可以调用在爷爷那里定义的方法
A组件:爷爷级组件

<template>
<div>
<B :a="a" :b="b" :c="c" v-bind="$attrs" @test="test" @test2="test2" v-on="$listeners"/>
</div>
</template>

<script>
import B from './B.vue'
export default {
name:"A",
components:{
B
},
data(){
return {
a:1,
b:2,
c:3
}
},
methods:{
test(){
alert(0)
},
test2(){
alert(2)
}
}
}
</script>

B组件:父亲级组件

<template>
<div>
<p>attrs: {{ $attrs }}</p>
<p style="background:#ccc;" @click="$listeners.test">props: {{ a }} </p>
<C v-bind="$attrs"/>
</div>
</template>

<script>
import C from './C.vue'
export default {
components:{
C
},
name:"B",
props:['a'],
data(){
return {

}
}
}
</script>

C:孙子级组件

<template>
<div>
<p>C : {{$attrs }}</p>
</div>
</template>

<script>
export default {
name:"C",
props:['name'],
inheritAttrs:false,
data(){
return {

}
}
}
</script>

23、vue为什么要求组件模版只能有一个根结点

因为vue组件最终是要被各种loader打包解析的,而我们必须为loader指定一个入口。而且,模版最终是会被编译成vdom的,所以必须有一个根结点来递归遍历其子节点,渲染成一个“树”。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值