VUE面试题

目录

computed

watch主要应用场景:

methods有什么功能?

data为什么是一个函数?

Vue有哪些生命周期?你常用哪些生命周期?

父子组件的生命周期顺序

 在哪个生命周期内调用异步请求? 

 在什么阶段才能访问操作DOM?

父组件可以监听到子组件的生命周期吗?

**v-show和v-if的区别和适用场景?

面试题:v-text和v-html的区别

class 如何动态绑定?

面试题:Style如何动态绑定?

v-model可以用哪些修饰符?

@click有哪些修饰符?

如何将父组件的全部props,都传给子组件?

v-pre指令和v-once指令有什么用?

面试题:v-bind:is指令有什么用?


computed

computed是啥意思呢:根据依赖(就是某个data值或者props值),计算后的某个值。

`computed`是计算属性的意思,是依赖其他的属性计算所得出最后的值。在Vue中,`computed`被定义为函数,但是不能传入任何参数,它只能“依赖”其它`data`或者`props`值。当它依赖的属性值发生改变,就会重新计算 `computed ` 的值,依赖数据不变时会直接从缓存中获取,不会重新计算。`computed`可以拆为`getter`和`setter`,这样的话,可以和`v-model`配合。

运用场景:当一个属性受多个属性影响时,比如我曾经制作过的美元、人民币、日元的换算**,用户可以在任何一个币种的输入框中输入数值,其他输入框要联动。此时用watch就会引发连锁变化的问题,所以使用`computed`,因为`computed`要有一个“依赖值”,我们自然而然用美元当做所有币种的**依赖值**,他们的`getter`都是美元乘汇率,他们的`setter`都是设置美元为`newValue`除汇率。当时那个例子做完之后,我对`computed`有了非常深的理解。

<template>
  <div>
    <p> 人民币:<input type="text" v-model="rmb"> </p>
    <p> 美元:<input type="text" v-model="usDollar"> </p>
    <p> 日元:<input type="text" v-model="jpDollar"> </p>
    <p> 泰币:<input type="text" v-model="swdkDollar"> </p>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        usDollar: 1
      }
    },
    computed: {
      rmb: {
        get() {
          return this.usDollar * 6;
        },
        set(newValue) {
          this.usDollar = newValue / 6;
        }
      },
      jpDollar: {
        get() {
          return this.usDollar * 180;
        },
        set(newValue) {
          this.usDollar = newValue / 180;
        }
      },
      swdkDollar: {
        get() {
          return this.usDollar * 33.65;
        },
        set(newValue) {
          this.usDollar = newValue / 33.65;
        }
      }
    }
  }
</script>

<style lang="scss" scoped>

</style>

watch主要应用场景:

什么时候用:当一条数据影响多条数据

`watch`,主要是监控`v-model`的值的变化,比如再做筛选器(搜索框)时,复选框的`v-model`值可以被`watch`,这样就能当复选框被改变时,发出Ajax了。

methods有什么功能?

 答:methods最常见的就是事件处理函数,我们的`@click="clickHandler()"`,这个`clickHandler`就要定义在methods中。methods中定义的函数,也可以直接显示在页面上。

data为什么是一个函数?

JavaScript中的对象是引用类型值的数据,当多个实例引用同一个对象时,只要一个实例对这个对象进行操作,其他实例中的数据也会发生变化。而在Vue中,更多的是想复用组件,那就需要组件都有自己的数据,这样组件之间才不会相互干扰。组件中的data写成一个函数,数据以函数返回值得形式定义,这样每次复用程序的时候,都会返回一份新的data,相当于每个组件实例都有自己私有的数据空间,他们只负责各自维护的数据,不会造成混乱。

Vue有哪些生命周期?你常用哪些生命周期?

答:Vue一共是11种生命周期,它们是:

- 8个普通生命周期: `beforeCreate`、`created`、`beforeMount`、`mounted`、`beforeUpdate`、`updated`、`beforeDestroy`、`destroyed`。
- 2个和路由相关的生命周期: `active`、`deactived`
- 1个捕获错误的生命周期: `captureError`

我工作中,最常用的生命周期是:

- `created`:这个生命周期用来发出Ajax请求,以及将props的值赋值给data;
- `mounted`: 这个生命周期用来得到DOM元素,比如`echart`图表的盒子,就要在这个生命周期中用`this.$refs`获得;
- `destroyed`: 这个生命周期通常用来配合本地存储,比如当组件消亡时,就命令本地存储器清空。

生命周期作用
beforeCreate组件创建之前。**没用**。因为这个生命周期,组件还没有创建,所有的`data`值无法访问,比如`this.a`会得到`undefined`。
created组件已经创建。**非常有用,**`data`值已经可以使用了,`methods`都可以使用,组件的一切都已经就绪了。我们通常在`created`生命周期中,发出Ajax请求。
beforeMount组件上树之前。**没用**。
mounted组件已经上树。**非常有用。**比如echarts要得到一个盒子,把图表放里面。就要用mounted生命周期。
beforeUpdate当data或者props改变之前触发。**没用。** 注意,不能在beforeUpdate生命周期中改变data、props,否则死循环。
updated当data或者props改变之后触发。**有点用。**注意,不能在updated生命周期中改变data、props,否则死循环。可能在updated时,将组件的数据用Ajax告诉服务器。
beforeDestroy当组件消亡之前做的事情。**没用。**
destroyed当组件消亡之后做的事情。**有点用。**比如清空本地存储数据。

父子组件的生命周期顺序

  • 加载渲染过程: 父 beforeCreate → 父 created → 父 beforeMount → 子 beforeCreate → 子 created → 子 beforeMount → 子 mounted → 父 mounted

  • 子组件更新过程(父亲的data当做props传给了子组件): 父 beforeUpdate -> 子 beforeUpdate -> 子 updated -> 父 updated

  • 销毁过程(当父组件销毁,带着儿子一切销毁):父 beforeDestroy -> 子 beforeDestroy -> 子 destroyed -> 父 destroyed

 在哪个生命周期内调用异步请求? 

理论上,可以在`created`、`beforeMount`、`mounted` 中发出Ajax请求,因为在这三个钩子函数中,`data` 已经创建、`this`也可以使用。(只要不是`beforeCreated`都能用)。

实战中,`created` 钩子函数发出Ajax请求是最多的,因为它有着独一无二的两个优点:

1、是**最快**的可用生命周期,第一时间获取到服务端数据,减少页面 `loading` 时间;

2、服务端渲染(SSR)不支持` beforeMount` 、`mounted`钩子函数,所以放在 `created `中有助于**一致性**;

 在什么阶段才能访问操作DOM?

在 `mounted` 中可以访问操作 DOM。使用`this.$refs`这个语法糖,可以快速访问操作DOM。比如Echarts图表,就要在`mounted`中去初始化。 

父组件可以监听到子组件的生命周期吗?

比如有父组件`App`和子组件`Zi`,如果父组件监听到子组件`mounted` 就做一些逻辑处理,可以通过以下写法实现:儿子一旦`mounted`了,那么就触发`$emit`了。

// APP.vue
<Zi @iMounted="iMountedHandler()"/>
    
// Zi.vue
mounted() {
  this.$emit("iMounted");
}

Vue提供了更好用的东西:@hook

<Zi @hook:beforeCreate="x1" @hook:created="x2" @hook:beforeMount="x3"/>

这样,儿子就不用别别扭扭的$emit了。

**v-show和v-if的区别和适用场景?

区别:

v-if决定元素上树与下树。

① 如果v-if写在子组件标签上,比如<Zi v-if="m"/>,那么能引发子组件的销毁和重建;

v-if是惰性的:如果在初始渲染时条件为假,则什么也不做,直到条件第一次变为真时,才会开始渲染条件块;

v-if能结合v-else使用,而v-show不能。

v-show决定元素显示与隐藏。

① 如果v-show写在子组件标签上,不引发子组件的任何生命周期。

v-show不是惰性的,不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 的 display`”属性进行切换。

③ 不能结合v-else使用。

适用场景:

  • v-if 适用于:

    • 需要触发子组件的生命周期,特别是销毁子组件时,比如弹出层的表单;

    • 需要初始值惰性防错时,比如Ajax值没有返回回来,那么arr[0].title就会报错,而如果写在v-if="arr.length != 0"的盒子中,就没有错误了;

    • 不适合大型子组件频繁切换。

  • v-show 适用于:

    • 不需惰性防错,只是简单的显示、隐藏特效。

 v-if后面能够跟上v-else,表示当v-if条件为假的时候,这个盒子上树。

<div v-if="m">A</div>
<div v-else>B</div>

m是真,A上树,B下树。m是假,A下树,B上树。

面试题:v-text和v-html的区别

v-text不会解析HTML标签,而v-html会解析HTML标签。但要注意的是,v-textv-html中的HTML标签,无法渲染双大括号、指令等Vue的语法。

我曾经用v-html制作过“智能感应”

<template>
  <div>
    <input type="text" v-model="keyword" />
    <ul>
      <li v-for="(item, index) in arr" :key="index" v-html="xianShi(item)"></li>
    </ul>
  </div>
</template>

<script>
export default {
  data() {
    return {
      keyword: "钱",
      arr: ["钱队长", "金元宝", "元宝金", "钱多多", "种种钱"],
    };
  },
  methods: {
    xianShi(str) {
      const index = str.indexOf(this.keyword);
      if (index != -1) {
        return (
          str.slice(0, index) +
          "<b>" +
          this.keyword +
          "</b>" +
          str.slice(index + this.keyword.length)
        );
      }
    },
  },
};
</script>

<style lang="less">
b {
  color: pink;
}
li {
  list-style: none;
}
</style>

class 如何动态绑定?

<div :class="{current: index == nowIndex}"></div>

普通class和动态class可以写在一个div中:

<div class="box" :class="{cur: index == nowIndex}"></div>

其实还有数组+对象形式:

<div :class="['cu', 'hong', { xie: 3 > 2, xian: 3 > 500 }]">
    你好
</div>

解释:数组中的字符串会被当做一定有的类名,而对象呢?要看表达式是否为真。即,cu这个类名一定有、hong一定有。xie因为表达式是真,也有。xian因为表达式是假,所以没有。

面试题:Style如何动态绑定?

<div :style="{width: a + 'px'}"></div>

其实还有数组+对象形式:

<section :style="[ys1, ys2()]">哈哈哈</section>

ys1定义在data中,是一个对象:

data() {
    return {
        ys1: {
            'color': 'red',
            'font-size': '40px'
        }
    };
},

ys2是一个函数,定义在methods中,返回一个对象:

methods: {
    ys2() {
        return {
            'transform': 'rotate(' + (this.a * 2) + 'deg)'
        }
    }
},

v-model可以用哪些修饰符?

必须背诵v-model有三个修饰符:

  • .lazy - 加上.lazy之后,拖拽条松手才改变a的值,拖拽过程中不改变a的值。即取代了 input 监听 change 事件。

  • .number - 输入字符串转为数字

  • .trim - 输入首尾空格过滤

比如拖拽条,加了.lazy,只有松手的时候才触发,拖拽的时候,不触发。

<input type="range" v-model.lazy="a">

 比如文本框,加了.number,输入的东西就是数字了,双向绑定改变a为数字,不是字符串;加了.trim,输入的东西前后的空格会被自动去掉。

<input type="text" v-model.number="a">
<input type="text" v-model.number.trim="a">

@click有哪些修饰符?

  • .stop 阻止事件冒泡
  • .prevent 阻止默认行为

 例如弹出层应用

<template>
  <div>
    <div class="mask" v-show="isShow" @click="isShow = false">
      <div class="inner" @click.stop></div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      isShow: true,
      a: 12,
    };
  },
};
</script>

<style lang="less">
.mask {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.668);
  display: flex;
  justify-content: center;
  align-items: center;
}
.inner {
  width: 300px;
  height: 200px;
  background-color: white;
}
</style>

如何将父组件的全部props,都传给子组件?

<child-component v-bind="$props"></child-component>

v-pre指令和v-once指令有什么用?

v-pre指令跳过这个元素和它的子元素的编译过程。可以用来显示原始标签,内部的所有双大括号和指令都不会执行,适用于跳过大量没有指令的HTML元素,会加快编译过程

v-once指令只渲染元素和组件一次。一旦数据渲染了,今后所有的重新渲染,将被视为静态内容并跳过。这可以用于优化更新性能

面试题:v-bind:is指令有什么用?

is就表示动态选择用什么组件:is=""双引号里面是组件的标签名。

准备三个组件Step1,Step2,Step3

owStep值是1的时候,让Step1组件显示;

nowStep值是2的时候,让Step2组件显示;

nowStep值是3的时候,让Step3组件显示;

<template>
  <div>
    <el-steps :active="nowStep">
      <el-step
        title="步骤 1"
        description="这是一段很长很长很长的描述性文字"
      ></el-step>
      <el-step
        title="步骤 2"
        description="这是一段很长很长很长的描述性文字"
      ></el-step>
      <el-step title="步骤 3" description="这段就没那么长了"></el-step>
    </el-steps>
    <div style="padding: 40px">
      <div :is="'Step' + nowStep"></div>
      <!-- <Step1 v-if="nowStep == 1" />
      <Step2 v-if="nowStep == 2" />
      <Step3 v-if="nowStep == 3" /> -->
    </div>
    <el-button @click="nowStep++">下一步</el-button>
  </div>
</template>

<script>
import Step1 from "./Step1.vue";
import Step2 from "./Step2.vue";
import Step3 from "./Step3.vue";
export default {
  components: {
    Step1,
    Step2,
    Step3,
  },
  data() {
    return {
      nowStep: 1,
      a: 12,
    };
  },
};
</script>

<style lang="less">
.mask {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.668);
  display: flex;
  justify-content: center;
  align-items: center;
}
.inner {
  width: 300px;
  height: 200px;
  background-color: white;
}
</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值