【灵魂拷问】Vue初级知识

857 阅读7分钟

Vue2.0兼容IE哪个版本以上吗?

不支持ie8及以下,部分兼容ie9 ,完全兼容10以上, 因为vue的响应式原理是基于es5的Object.defineProperty(),而这个方法不支持ie8及以下。

请描述下vue的生命周期是什么?

  • beforeCreate:实例创建前被调用;
  • created:实例创建后被调用,完成数据观测,属性和方法的运算,watch/event事件回调,模板渲染成html前(vm.$el未定义)故数据初始化最好在这阶段完成;
  • beforeMount:在el挂载前被调用,相关的render函数首次被调用,期间将模块渲染成html,此时vm.el挂载前被调用,相关的 render 函数首次被调用,期间将模块渲染成html,此时vm.el还是未定义;
  • mounted:在el挂载后被调用,此时vm.el挂载后被调用,此时vm.el可以调用,不能保证所有的子组件都挂载,要等视图全部更新完毕用vm.$nextTick();
  • beforeUpdate:数据更新时调用;
  • updated:数据更新后调用;
  • activated:包裹的组件激活时调用;
  • deactivated:包裹的组件离开时调用;
  • beforeDestroy:实例销毁之前调用,此时实例仍然完全可用;
  • destroyed:实例销毁之后调用,此时实例的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。

computed中的属性名和data中的属性名可以相同吗?

不能同名,因为不管是computed属性名还是data数据名还是props数据名都会被挂载在vm实例上,因此这三个都不能同名。

if (key in vm.$data) {
    warn(`The computed property "${key}" is already defined in data.`, vm)
} else if (vm.$options.props && key in vm.$options.props) {
    warn(`The computed property "${key}" is already defined as a prop.`, vm)
}

data的属性名可以和methods中的属性名相同吗?

不能同名,因为看源码

let data = vm.$options.data
const keys = Object.keys(data)
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
            )
        }
    }
}

怎么缓存当前打开的路由组件,缓存后想更新当前组件怎么办呢?

用内置组件包裹路由组件,在钩子函数activated中更新。

跟keep-alive有关的生命周期是哪些?

  • activated钩子:keep-alive 组件激活时调用。
  • deactivated钩子:keep-alive 组件停用时调用。
  • 以上钩子服务器端渲染期间不被调用。

watch的属性使用箭头函数定义可以吗?

不可以。this会是undefind,因为箭头函数中的this指向的是定义时的this,而不是执行时的this,所以不会指向Vue实例的上下文。

watch:{
    show:(val)=>{
        console.log(this)//undefind this会指向show
    },
    id(val){
        conosle.log(this)//Vue实例对象
    }
}

怎么在watch监听开始之后立即被调用?

在选项参数中指定immediate: true将立即以表达式的当前值触发回调。

watch怎么深度监听对象变化?

watch:{
   a:{
       handler:function(val,oldval){
           
       },
       deep:true
   }
}

methods的方法用箭头函数定义可以吗?

不可以。this会是undefind,因为箭头函数中的this指向的是定义时的this,而不是执行时的this,所以不会指向Vue实例的上下文。

怎么强制刷新组件?

  • this.$forceUpdate()。
  • 组件上加上key,然后变化key的值。

父组件中的自定义事件怎么接收子组件的多个参数?

this.$emit('eventName',data),data可以是个对象,包含子组件的多个参数,然后传给父组件。

给组件绑定自定义事件无效怎么解决?

加上修饰词.native。

怎么访问子组件的实例或者子元素?

先用ref特性为子组件赋予一个ID引用</

比如子组件有个focus的方法,可以这样调用this.refs.myInput.focus();比如子组件有个value的数据,可以这样使用this.refs.myInput.focus(); 比如子组件有个value的数据,可以这样使用this.refs.myInput.value。

先用ref特性为普通的 DOM 元素赋予一个ID引用

<ul ref="mydiv">
  <li class="item">第一个li</li>
  <li class="item">第一个li</li>
</ul>
console.log(this.$refs['mydiv'].getElementsByClassName('item')[0].innerHTML)//第一个li

怎么在子组件中访问父组件的实例?

使用this.$parent来访问

怎么在组件中访问到根实例?

this.$root

组件会在什么时候下被销毁?

  • 没有使用keep-alive时的路由切换;
  • v-if='false';
  • 执行vm.$destroy();

is这个特性你有用过吗?主要用在哪些方面?

  • 动态组件

<component :is="componentName"></component>, componentName可以是在本页面已经注册的局部组件名和全局组件名,也可以是一个组件的选项对象。

当控制componentName改变时就可以动态切换选择组件。

  • is的用法

有些HTML元素,诸如 <ul>、<ol>、<table>和<select>,对于哪些元素可以出现在其内部是有严格限制的。

而有些HTML元素,诸如 <li>、<tr> 和 <option>,只能出现在其它某些特定的元素内部。

<ul>
    <card-list></card-list>
</ul>

复制代码所以上面会被作为无效的内容提升到外部,并导致最终渲染结果出错。应该这么写:

<ul>
    <li is="cardList"></li>
</ul>

Vue组件之间的通信都有哪些?

  • this.$emit('input',data)
  • this.root.root.on('input',function(data){})和this.root.root.emit('emit',data)
  • this.$refs.tree
  • this.$parent
  • provide和inject
  • vueX

prop验证的type类型有哪几种?

String、Number、Boolean、Array、Object、Date、Function、Symbol, 此外还可以是一个自定义的构造函数Personnel,并且通过 instanceof 来验证prop wokrer的值是否是通过这个自定义的构造函数创建的。

function Personnel(name,age){
    this.name = name;
    this.age = age;
}
export default {
    props:{
        wokrer:Personnel
    }
}

prop是怎么做验证的?可以设置默认值吗?

export default {
    props:{
        propA:[String,Number],
        propB:{
            type:Number,
            default:1,
        },
        propC:Boolean,
        propD:{
            type:Object,
            default(){
                return{}
            }
        }
    }
}

在Vue事件中是如何使用event对象的?

  • @click="handleOpen" 默认第一个参数传入event对象;
  • @click="handleOpen(0, event)",如果自己需要传入参数和event对象,则需要使用event)",如果自己需要传入参数和event对象,则需要使用event来获取event对象并传入handleOpen。

在Vue事件中传入event,使用event,使用event.target和$event.currentTarget有什么区别?

event.currentTarget始终指向事件所绑定的元素,而event.currentTarget始终指向事件所绑定的元素,而event.target指向事件发生时的元素。

写出你知道的表单修饰符和事件修饰符

  1. 事件修饰符
  • .stop:阻止事件传递;
  • .prevent: 阻止默认事件;
  • .capture :在捕获的过程监听,没有capture修饰符时都是默认冒泡过程监听;
  • .self:当前绑定事件的元素才能触发;
  • .once:事件只会触发一次;
  • .passive:默认事件会立即触发,不要把.passive和.prevent一起使用,因为.prevent将不起作用。
  1. 表单修饰符.number .lazy .trim

使用事件修饰符要注意什么?

要注意顺序很重要,用@click.prevent.self会阻止所有的点击,而@click.self.prevent只会阻止对元素自身的点击。

说说你对Vue的表单修饰符.lazy的理解。

input标签v-model用lazy修饰之后,并不会立即监听input的value的改变,会在input失去焦点之后,才会监听input的value的改变。

Vue如何监听键盘事件?

使用按键修饰符 <input @keyup.enter="submit">按下回车键时候触发submit事件。

  • .enter
  • .tab
  • .delete (捕获“删除”和“退格”键)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

写出你常用的指令有哪些?

v-show、v-if、v-else-if、v-else、v-for、v-on、v-bind、v-model、v-once、v-slot、v-html、v-text。

v-once的使用场景有哪些?

其作用是只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。故当组件中有大量的静态的内容可以使用这个指令。

v-show和v-if有什么区别?使用场景分别是什么?

  • v-show,切换元素的display属性,来控制元素显示隐藏,初始化会渲染,适用频繁显示隐藏的元素,不能用在<template>上;
  • v-if,通过销毁并重建组件,来控制组件显示隐藏,初始化不会渲染,不适用频繁显示隐藏的组件,可以用在<template>上。

v-on可以绑定多个方法吗?

可以,v-on后面接一个对象,但是不支持事件修饰符

<template>
    <div v-on:{click:a,dblclick:b}></div>
</template>
<script>
    methods:{
        a(){
            alert(1)
        },
        b(){
            alert(2)
        }
    }
</script>

v-cloak和v-pre有什么作用

v-cloak:可以解决在页面渲染时把未编译的 Mustache 标签({{value}})给显示出来

[v-cloak] {
    display: none!important;
}
<div v-cloak>
    {{ message }}
</div>

v-pre:跳过这个元素和它的子元素的编译过程。可以用来显示原始Mustache标签。跳过大量没有指令的节点会加快编译。

<span v-pre>{{ this will not be compiled }}</span>

:class和:style有几种表示方式?

共4种

<template>
  <div>
  <!--第一种对象语法 -->
  <div class="test" :class="{
    active: actived ,
    'active-click': clicked && actived
  }"></div>
  <!-- 第二种数组语法 -->
  <div class="test" :class="[
    actived? activeClass : '', 
    clicked && actived ? activeClickClass : ''
  ]"></div>
  <!-- 第三种对象和数组混合 -->
  <div :class="[
    testClass , 
    {active: actived} , 
    {'active-click': clicked && actived}
  ]"></div>
  <!-- 第四种对象和计算属性(推荐) -->
  <div :class="classObject"></div>
  </div>
</template>

在.vue文件中style是必须的吗?那script是必须的吗?

都不是必须的。

怎么使css样式只在当前组件中生效?

<style lang="less" scoped></style>

在style上加scoped属性需要注意哪些?

  • 第一种:使用 /deep/

语法: .自己定义的类名 /deep/ .组件内的类名 { /* 代码块 */ }

如果在公共组件中使用,修改公共组件的样式需要用/deep/。

为了避免影响到其他页面这个组件的样式,我们可以使用/deep/深度选择器修改子组件的样式。

比如:修改elementui原有样式——/deep/

.el-radio /deep/ .el-radio__inner{
  border: 1px solid #DCDFE6;/* no */
  width: 7px;/* no */
  height: 7px;/* no */
}
  • 方法二:使用 >>>

语法: .自己定义的类名 >>> .组件内的类名 { /* 代码块 */ }

使用这三个大于号就可以找到,跟上面的 /deep/ 差不多。

.box-out >>> .xxxxx组件样式类 {
  color: red;
}

你知道style上加scoped属性的原理吗?

vue通过在DOM结构以及css样式上加上唯一的标记data-v-xxxxxx,保证唯一,达到样式私有化,不污染全局的作用。

Vue渲染模板时怎么保留模板中的HTML注释呢?

在组件中将comments选项设置为true

<template comments> ... <template> 

你知道style上加scoped属性的原理吗?

vue通过在DOM结构以及css样式上加上唯一的标记data-v-xxxxxx,保证唯一,达到样式私有化,不污染全局的作用。

vm.$nextTick有什么作用?

vm.$nextTick(() =>{this.handleadd()}),将handleadd回调延迟到下次 DOM 更新循环之后执行。

Vue中怎么重置data?

Object.assign(this.data,this.data,this.options.data())

手写一个过滤器

filters:{
  addUnit(val){
      if(val){
          return val+'元/米'
      }else{
          return ''
      }
  }
}
Vue.filter('addUnit',function(val){
    if(val){
        return val+'元/米'
    }else{
        return ''
    }
})
new Vue({
  // ...
})

过滤器中可以用this吗?

不可以