2020年vue常见面试题总结

vue常见面试题

1. vue优点

低耦合。视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的"View"上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。

可重用性。你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑。

独立开发。开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计。

可测试。界面素来是比较难于测试的,而现在测试可以针对ViewModel来写。

2. vue父组件向子组件传递数据?

  1. 父组件将数据绑定在子组件上

     <template>
      <transition name="slide">
        <music-list :songs="songs" :title="title" :bg-image="bgImage"></music-list>
      </transition>
    </template>
    
  2. 子组件接受数据prop

export default {
  props: {
    bgImage: {
      type: String,
      default: ''
    },
    songs: {
      type: Array,
      default: () => []
    },
    title: {
      type: String,
      default: ''
    }
   },
 }

3. 子组件像父组件传递事件

在子组件里用$emit向父组件触发一个事件,父组件监听这个事件就行了

父组件

<script>
  import child from '~/components/dam/child';
  export default {
    components: {
      child
    },
    methods: {
      fatherMethod() {
        console.log('测试');
      }
    }
  };
</script>

子组件

<script>
  export default {
    methods: {
      childMethod() {
        this.$emit('fatherMethod');
      }
    }
  };
</script>

4. v-show和v-if指令的共同点和不同点

v-show指令是通过修改元素的display的CSS属性让其显示或者隐藏

v-if指令是直接销毁和重建DOM达到让元素显示和隐藏的效果

5. 如何让CSS只在当前组件中起作用

将当前组件的修改为

6. 的作用是什么?

包裹动态组件时,会缓存不活动的组件实例,主要用于保留组件状态或避免重新渲染。

7. 如何获取dom

通过refs方法

<div id="App">
     <div class="aa" ref="menuItem" @click="aa($event)">aa</div>
<div @click="bb"\>bb</div>
</div>

JS

<script>
     new Vue({
          el: '#App',
          methods: {
               bb: function() {
                    var getMenuText = this.$refs.menuItem.innerText;
                    console.log(getMenuText);//aa
               },
               aa: function(e) {
                    var el = e.target;
                    console.log(el);//<div class="aa">aa</div>
               }
          }
     })
</script>

8. 说出几种vue当中的指令和它的用法?

v-if:判断是否隐藏;

v-for:数据循环;

v-bind:class:绑定一个属性;

v-model:实现双向绑定

9. vue-loader是什么?使用它的用途有哪些?

vue文件的一个加载器。

用途:js可以写es6、style样式可以scss或less、template可以加jade等

根据官网的定义,vue-loader 是 webpack 的一个 loader,用于处理 .vue 文件。

10. 为什么使用key

当有相同标签名的元素切换时,需要通过key 特性设置唯一的值来标记以让Vue 区分它们,否则Vue 为了效率只会替换相同标签内部的内容。

11. axios及安装

1.axios是什么?

请求后台资源的模块

2.axios安装?

根目录运行

npm install axios -S

在使用的地方

import axios from ‘axios’

12. axios解决跨域

首先在build/webpack.dev.conf.js设置代理

var express \= require('express')
var axios \= require('axios')
var app \= express()
var apiRoutes \= express.Router()
app.use('/api', apiRoutes)before(apiRoutes) {  
      apiRoutes.get('/api/getDiscList', function (req, res) {  
        var url = 'https://c.y.qq.com/splcloud/fcgi-bin/fcg_get_diss_by_tag.fcg' // 原api 
        axios.get(url, {  
          headers: {  
            referer: 'https://c.y.qq.com/',  
            host: 'c.y.qq.com'  
          },  
          params: req.query  
        }).then((response) => {  
          res.json(response.data)  
        }).catch((e) => {  
          console.log(e)  
        })  
      })
 }  

在页面中使用

export function getDiscList() {
  const url = '/api/getDiscList'
  const data = Object.assign({}, commonParams, {
    platform: 'yqq',
    hostUin: 0,
    sin: 0,
    ein: 29,
    sortId: 5,
    needNewCode: 0,
    categoryId: 10000000,
    rnd: Math.random(),
    format: 'json'
  })
  return axios.get(url, {
    params: data
  }).then((res) => {
    return Promise.resolve(res.data)
  })}

13. v-modal的使用

用v-model指令在表单、及元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但v-model本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。

v-model在内部使用不同的属性为不同的输入元素并抛出不同的事件:

l text 和 textarea 元素使用value属性和input事件;

l checkbox 和 radio 使用checked属性和change事件;

l select 字段将value作为 prop 并将change作为事件。

14. scss的安装以及使用

1、开始在vue项目中使用sass,在命令行输入一下命令进行安装(使用git命令行要用shift+insert 进行粘贴否则粘贴不上)

cnpm install node-sass --save-dev //安装node-sass

cnpm install sass-loader --save-dev //安装sass-loader

cnpm install style-loader --save-dev //安装style-loader 有些人安装的是 vue-style-loader 其实是一样的!

2、这个时候你打开build文件夹下面的webpack.base.config.js

把里面的module改成这样的

module: { 
    rules: [ 
          { 
            test: /\.vue$/, 
            loader: 'vue-loader', 
            options: vueLoaderConfig
          }, 
          { 
            test: /\.js$/,
            loader: 'babel-loader', 
            include: [resolve('src'), 
            resolve('test')] 
          }, 
          {
             test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 
             loader: 'url-loader', 
             options: { 
                limit: 10000,
                 name: utils.assetsPath('img/[name].[hash:7].[ext]')
                            } 
                 }, 
          { 
                    test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
                    loader: 'url-loader', 
                   options: { 
                               limit: 10000, 
                               name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
                            } 
                   }, 
          { //从这一段上面是默认的!不用改!下面是没有的需要你手动添加,相当于是编译识别sass! 
                     test: /\.scss$/,
                     loaders: ["style", "css", "sass"]
                  } 
               ] 
           }

3、在需要用到sass的地方添加lang=scss

<style lang="scss" scoped="" type="text/css"> //你的sass语言 $primary-color: #333; 
   body {
        color: $primary-color; //编译后就成了 color:#333;类似于js的变量! 
      } 
</style>

15. 请说出vue.cli项目中src目录每个文件夹和文件的用法?

assets文件夹是放静态资源;

components是放组件;

router是定义路由相关的配置;view视图;

app.vue是一个应用主组件;

main.js是入口文件

16. 分别简述computed和watch的使用场景

一. methods和(watch、computed)的 区别

1.watch和computed都是以Vue的依赖追踪机制为基础的,它们都试图处理这样一件事情:当某一个数据(称它为依赖数据)发生变化的时候,所有依赖这个数据的“相关”数据“自动”发生变化,也就是自动调用相关的函数去实现数据的变动。

2.对methods:methods里面是用来定义函数的,很显然,它需要手动调用才能执行。而不像watch和computed那样,“自动执行”预先定义的函数

二. methods和computed的 相比 computed的好处

import Vue from 'vue'

new Vue({

  el: '#root',

  template: `

    <div>

      <p>Name: {{name}}</p>

      <p>Name: {{getName()}}</p>

      <p>Number: {{number}}</p>

      <p><input type="text" v-model="number"/></p>

      <p>FirsName: <input type="text" v-model="firstName"/></p>

      <p>LaseName: <input type="text" v-model="lastName"/></p>

​    </div>

  data: {

​    firstName: 'Jokcy',

​    lastName: 'Lou',

​    number: 0

  },

  computed: {

​    name () {

​      console.log('new name')

​      return `${this.firstName} ${this.lastName}`

​    }

  },

  methods: {

​    getName () {

​      console.log('getName invoked')

​      return `${this.firstName} ${this.lastName}`

​    }

  }
  })

当我们改变 number 时,整个应用会重新渲染,vue 会被数据重新渲染到 dom 中。这时,如果我们使用 getName 方法,随着渲染,方法也会被调用,而 computed 不会重新进行计算,从而性能开销比较小。当新的值需要大量计算才能得到,缓存的意义就非常大。

如果 computed 所依赖的数据发生改变时,计算属性才会重新计算,并进行缓存;当改变其他数据时,computed 属性 并不会重新计算,从而提升性能。

当我们拿到的值需要进行一定处理使用时,就可以使用 computed。

三. watc和computed的 区别

1.watch 监听某个数据的变化(监听完调用什么函数) 一个数据影响多个数据 (比如:浏览器自适应、监控路由对象、监控自身属性变化)

computed 计算后返回新 一个数据受多个数据影响(比如:计算总价格、过滤某些数据)

2.就算在data中没有直接声明出要计算的变量,也可以直接在computed中写入。如果在data中没有相应的属性的话,是不能watch的,这点和computed不一样。

3.computed是用来处理你使用watch和methods的时候无法处理(比如有缓存的时候监听不了数据变化),或者是处理起来并不太恰当的情况的,利用computed处理methods存在的重复计算情况

watch: {

​    firstName(val) { this.fullName = val + this.lastName }}

computed: {

​    fullName() { this.firstName + this.lastName; }}

17. v-on可以监听多个方法吗

v-on可以监听多个方法,例如:

<input type=“text” :value=“name” @input=“onInput” @focus=“onFocus” @blur=“onBlur” />

但是同一种事件类型的方法,vue-cli工程会报错,例如:

<input type=“text” :value=“name” @input=“onInput” @focus=“onFocus” @blur=“onBlur” />

18. $nextTick的使用

为什么使用$nextTick

因为Vue中DOM更新是异步的

$nextTick是DOM更新完成后执行的

在Vue生命周期的created()钩子函数进行的DOM操作一定要放在Vue.nextTick()的回调函数中?

在created()钩子函数执行的时候DOM 其实并未进行任何渲染,而此时进行DOM操作无异于徒劳,所以此处一定要将DOM操作的js代码放进Vue.nextTick()的回调函数中。与之对应的就是mounted()钩子函数,因为该钩子函数执行时所有的DOM挂载和渲染都已完成,此时在该钩子函数中进行任何DOM操作都不会有问题 。

$nextTick的其他应用

在数据变化后要执行的某个操作,而这个操作需要使用随数据改变而改变的DOM结构的时候,这个操作都应该放进Vue.nextTick()的回调函数中。

四 $nextTick的原理

作用

Vue.nextTick用于延迟执行一段代码,它接受2个参数(回调函数和执行回调函数的上下文环境),如果没有提供回调函数,那么将返回promise对象。

源码

/**

 \* Defer a task to execute it asynchronously.

 */

export const nextTick = (function () {

  const callbacks = []

  let pending = false

  let timerFunc

  function nextTickHandler () {

​    pending = false

​    const copies = callbacks.slice(0)

​    callbacks.length = 0

​    for (let i = 0; i < copies.length; i++) {

​      copies[i]()

​    }

  }

  // the nextTick behavior leverages the microtask queue, which can be accessed

  // via either native Promise.then or MutationObserver.

  // MutationObserver has wider support, however it is seriously bugged in

  // UIWebView in iOS >= 9.3.3 when triggered in touch event handlers. It

  // completely stops working after triggering a few times... so, if native

  // Promise is available, we will use it:

  /* istanbul ignore if */

  if (typeof Promise !== 'undefined' && isNative(Promise)) {

​    var p = Promise.resolve()

​    var logError = err => { console.error(err) }

​    timerFunc = () => {

​      p.then(nextTickHandler).catch(logError)

​      // in problematic UIWebViews, Promise.then doesn't completely break, but

​      // it can get stuck in a weird state where callbacks are pushed into the

​      // microtask queue but the queue isn't being flushed, until the browser

​      // needs to do some other work, e.g. handle a timer. Therefore we can

​      // "force" the microtask queue to be flushed by adding an empty timer.

​      if (isIOS) setTimeout(noop)

​    }

  } else if (!isIE && typeof MutationObserver !== 'undefined' && (

​    isNative(MutationObserver) ||

​    // PhantomJS and iOS 7.x

​    MutationObserver.toString() === '[object MutationObserverConstructor]'

  )) {

​    // use MutationObserver where native Promise is not available,

​    // e.g. PhantomJS, iOS7, Android 4.4

​    var counter = 1

​    var observer = new MutationObserver(nextTickHandler)

​    var textNode = document.createTextNode(String(counter))

​    observer.observe(textNode, {

​      characterData: true

​    })

​    timerFunc = () => {

​      counter = (counter + 1) % 2

​      textNode.data = String(counter)

​    }

  } else {

​    // fallback to setTimeout

​    /* istanbul ignore next */

​    timerFunc = () => {

​      setTimeout(nextTickHandler, 0)

​    }

  }

  return function queueNextTick (cb?: Function, ctx?: Object) {

​    let _resolve

​    callbacks.push(() => {

​      if (cb) {

​        try {

​          cb.call(ctx)

​        } catch (e) {

​          handleError(e, ctx, 'nextTick')

​        }

​      } else if (_resolve) {

​        _resolve(ctx)

​      }

​    })

​    if (!pending) {

​      pending = true

​      timerFunc()

​    }

​    if (!cb && typeof Promise !== 'undefined') {

​      return new Promise((resolve, reject) => {

​        _resolve = resolve

​      })

​    }

  }})()

首先,先了解nextTick中定义的三个重要变量。

l callbacks

用来存储所有需要执行的回调函数

l pending

用来标志是否正在执行回调函数

l timerFunc

用来触发执行回调函数

接下来,了解nextTickHandler()函数。

function nextTickHandler () {

​    pending = false

​    const copies = callbacks.slice(0)

​    callbacks.length = 0

​    for (let i = 0; i < copies.length; i++) {

​      copies[i]()

​    }

  }

这个函数用来执行callbacks里存储的所有回调函数。

接下来是将触发方式赋值给timerFunc。

先判断是否原生支持promise,如果支持,则利用promise来触发执行回调函数;

否则,如果支持MutationObserver,则实例化一个观察者对象,观察文本节点发生变化时,触发执行所有回调函数。

如果都不支持,则利用setTimeout设置延时为0。

最后是queueNextTick函数。因为nextTick是一个即时函数,所以queueNextTick函数是返回的函数,接受用户传入的参数,用来往callbacks里存入回调函数。

上图是整个执行流程,关键在于timeFunc(),该函数起到延迟执行的作用。

从上面的介绍,可以得知timeFunc()一共有三种实现方式。

Promise

MutationObserver

setTimeout

其中Promise和setTimeout很好理解,是一个异步任务,会在同步任务以及更新DOM的异步任务之后回调具体函数。

19. vue组件中data为什么必须是一个函数

为什么组件中data必须是一个函数了而不是对象, 我们首先来看一下第一个声明式渲染的demo中data我们只在当前页面的挂载的div#app这个点上使用,但是对于组件有一个很明显的特性是在于它是可以被复用的,好了知道了这一点我们以一个全局注册一个组件来分析

我们先假设将data作为一个对象:

我们前面说组件是可以被复用的,那么注册了一个组件本质上就是创建了一个组件构造器的引用,而真正当我们使用组件的时候才会去将组件实例化,

// 创建一个组件

var Component= function() {}

Component.prototype.data = {

  a: 1,

  b: 2}

// 使用组件

var component1 = new Component()

var component2 = new Component()

component1.data.b = 3

component2.data.b   // 3

我们可以发现当我们使用组件的时候,虽然data是在构造器的原型链上被创建的,但是实例化的component1和component2确是共享同样的data对象,当你修改一个属性的时候,data也会发生改变,这明显不是我们想要的效果。

var Component= function() {}

Component.prototype.data = function() {

  return {

​     a: 1,

​     b: 2

  }}

// 使用组件

var component1 = new Component()

var component2 = new Component()

component1.data.b = 3

component2.data.b   // 2

当我们的data是一个函数的时候,每一个实例的data属性都是独立的,不会相互影响了。你现在知道为什么vue组件的data必须是函数了吧。这都是因为js本身的特性带来的,跟vue本身设计无关。

20. vue事件对象的使用

<button data-aid="123" @click="getInfo($event)">通过事件对象获取自定义属性</button>

getInfo(event){

​    //获取自定义data-id

​	console.log(event.target.dataset.id)

   //阻止事件冒泡

​    event.stopPropagation(); 

​    //阻止默认

​    event.preventDefault()}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jay·Yuen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值