美文网首页
vue组件化的好处及vue常见面试题

vue组件化的好处及vue常见面试题

作者: 小王子__ | 来源:发表于2020-07-20 18:56 被阅读0次

    1,组件化开发思想:

    * 提高开发效率
    * 方便重复使用
    * 简化调试步骤
    * 提升项目的可维护性
    * 便于多人协同开发
    

    2, vue优点

    vue是一个构建数据驱动的web界面的渐进式MVVM框架,性能好、简单易用、前后端分离、单页面应用用户体验好
    3,谈谈你对MVVM开发模式的理解

    MVVM分为Model、View、viewModel三者
    * Model:代表数据模型,数据和业务逻辑都在Model层定义
    * View: 代表视图模型,负责数据的展示
    * viewModel: 负责监听Model中的数据的改变并控制视图的更新,处理用户交互操作
    4, v-if和v-show区别

    v-show仅仅控制元素的显示方式,将display属性在block和none直接来回切换;v-if会控制这个DOM节点的存在与否,如果需要经常切换某个元素的显示/隐藏的时候,这时候使用v-show更节省性能上的开销
    5, vue常见的指令

    v-html、v-if、v-show、v-for、v-model、v-once、v-on
    6, v-loader是什么

    vue文件的一个加载器,将template/js/style转换成js模块
    用途: js可以写es6、style样式可以scss、less、template可以加jade等

    1. vue中key的作用

    key来给每个节点做一个唯一标识,作用是为了高效的更新虚拟DOM
    8,computed和watch区别及使用场景
    computed适用于动态计算data里的属性值,必须加return,不能对data里的属性进行赋值,当无变化时会先从缓存里读取。
    使用场景:当一个值受多个属性影响的时候

    computed: {
        btnText(){
          return this.totalCount !== 0 ? `${this.totalCount}s`: "获取验证码"
        }
      }
    

    watch
    watch是监听data里的值的变化,当data中的属性发生改变的时候,watch中的函数就会执行,有两个参数,前者是newVal,后者是oldVal。当监听引用类型数据的变化,需要进行深度监听(用handler + deep的方式进行深度监听。immediate:true 页面首次加载的时候做一次监听。
    使用场景:当一条数据的更改影响到多条数据的时候

    watch: {
        //a,b,c,d为data里的数据名
        a(val, oldVal) {
            console.log( val, oldVal)
        },
        // 方法名
        b: 'someMethod',
        c: {
          handler(val, oldVal) {},
          deep: true // 该回调会在任何被侦听的对象的 property 改变时被调用,不论其被嵌套多深
        },
        d: {
          handler: 'someMethod',
          immediate: true    // 该回调将会在侦听开始之后被立即调用
        },
    }
    computed当一个属性受多个属性影响的时候使用computed 最典型的例子: 购物车商品结算的时候
    watch当一条数据影响多条数据的时候使用watch,典型的例子: 搜索数据
    

    9,MVVM响应式原理
    实现数据绑定的做法大致如下几种:
    发布者 - 订阅者模式
    数据劫持
    数据劫持: vue是采用数据劫持结合发布者-订阅者模式的方式,通过object.defineProperty()来劫持各个属性的setter, getter,在数据变动时发布消息给订阅者,触发相应的监听回调


    image.png

    1,实现一个指令解析器Compile
    待补全 ....
    10, Vue的三种常用传值方式父传子、子传父、非父子组件传值
    1、父组件向子组件进行传值
    父组件

    <template>
      <div>
        父组件:
        <input type="text" v-model="name">
        <br>
        <br>
        <!-- 引入子组件 -->
        <child :inputName="name"></child>
      </div>
    </template>
    <script>
      import child from './child'
      export default {
        components: {
          child
        },
        data () {
          return {
            name: ''
          }
        }
      }
    </script>
    

    子组件:

    <template>
      <div>
        子组件:
        <span>{{inputName}}</span>
      </div>
    </template>
    <script>
      export default {
        // 接受父组件的值
        props: {
          inputName: String,
          required: true
        }
      }
    </script>
    
    1. 子组件向父组件传值
      子组件:
    <template>
      <div>
        子组件:
        <span>{{childValue}}</span>
        <!-- 定义一个子组件传值的方法 -->
        <input type="button" value="点击触发" @click="childClick">
      </div>
    </template>
    <script>
      export default {
        data () {
          return {
            childValue: '我是子组件的数据'
          }
        },
        methods: {
          childClick () {
            // childByValue是在父组件on监听的方法
            // 第二个参数this.childValue是需要传的值
            this.$emit('childByValue', this.childValue)
          }
        }
      }
    </script>
    

    父组件:

    <template>
      <div>
        父组件:
        <span>{{name}}</span>
        <br>
        <br>
        <!-- 引入子组件 定义一个on的方法监听子组件的状态-->
        <child v-on:childByValue="childByValue"></child>
      </div>
    </template>
    <script>
      import child from './child'
      export default {
        components: {
          child
        },
        data () {
          return {
            name: ''
          }
        },
        methods: {
          childByValue: function (childValue) {
            // childValue就是子组件传过来的值
            this.name = childValue
          }
        }
      }
    </script>
    

    3,非父子组件进行传值

    非父子组件之间传值,需要定义个公共的公共实例文件bus.js,作为中间仓库来传值,不然路由组件之间达不到传值的效果

    eventBus 就是创建一个事件中心,相当于中转站,可以用它来传递事件和接受事件

    公共bus.js:

    //bus.js
    import Vue from 'vue'
    export default new Vue()
    

    组件A:

    <template>
      <div>
        A组件:
        <span>{{elementValue}}</span>
        <input type="button" value="点击触发" @click="elementByValue">
      </div>
    </template>
    <script>
      // 引入公共的bug,来做为中间传达的工具
      import Bus from './bus.js'
      export default {
        data () {
          return {
            elementValue: 4
          }
        },
        methods: {
          elementByValue: function () {
            Bus.$emit('val', this.elementValue)
          }
        }
      }
    </script>
    

    组件B:

    <template>
      <div>
        B组件:
        <input type="button" value="点击触发" @click="getData">
        <span>{{name}}</span>
      </div>
    </template>
    <script>
      import Bus from './bus.js'
      export default {
        data () {
          return {
            name: 0
          }
        },
        mounted: function () {
          var vm = this
          // 用$on事件来接收参数
          Bus.$on('val', (data) => {
            console.log(data)
            vm.name = data
          })
        },
        methods: {
          getData: function () {
            this.name++
          }
        }
      }
    </script>
    

    11, vue中vue-router hash和history模式区别
    为了构建SPA,vue引入了前端路由系统vue-router。
    vue-route有两种模式:history模式和hash模式。

    1. hash模式(vue-router默认hash模式)
      hash模式背后的原理是onhashchange事件。
    window.onhashchange=function(){
     let hash=location.hash.slice(1);
     document.body.style.color=hash;
    }
    

    localtion是js里管理地址栏的内置对象,是window对象的一部分,可通过window.localtion访问,在w3cshool里的详细介绍)
    由于hash发生变化的url都会被浏览器记录下来,使得浏览器的前进后退都可以使用了,尽管浏览器没有亲求服务器,但是页面状态和url关联起来。后来人们称其为前端路由,成为单页应用标配。

    比如http://www.abc.com/#/index,hash值为#/index。hash模式的特点在于hash出现在url中,但是不会被包括在HTTP请求中,对后端没有影响,不会重新加载页面。
    2.history模式
    history模式利用了HTML5 History Interface中新增的pushState()和replaceState()方法。MDN相关介绍(需要特定浏览器支持)。这两个方法应用于浏览器的历史记录栈,提供了对历史记录进行修改的功能。只是当他们进行修改时,虽然修改了url,但浏览器不会立即向后端发送请求。
    当使用history模式时,url就像正常的url,例如http://abc.com/user/id相比hash模式更加好看。特别注意,history模式需要后台配置支持。如果后台没有正确配置,访问时会返回404。
    通过history api,我们丢弃了丑陋的#,但是有一个缺点,当刷新时,如果服务器中没有相应的相应或者资源,会分分钟刷出一个404来(刷新需要请求服务器)。所以history模式不怕前进,不怕后退,就怕刷新。
    3.hash模式和history模式区别

    • pushState()设置新的url可以是和当前url同源的任意url;hash只可修改#后面的部分,只能设置当前url同文档的url。
    • pushState()设置的新url可与当前url一致,这样也会把记录添加到栈中;hash必须设置与当前url不同的url的,才会触发动作将记录添加到栈中。
    • pushState()通过stateObject参数可以添加任意类型的数据到记录中;hash只可添加短字符串。
    • pushState()可额外设置title属性供后续使用。
      不过,hash模式也有比history模式优势的地方:
    • hash模式下,仅hash符号之前的url会被包含在请求中,后端如果没有做到对路由的全覆盖,也不会返回404错误。
    • history模式下,前端的url必须和实际向后端发起请求的url一致,如http://abc.com/user/id,后端如果没有对user/id的路由处理,将返回404错误。
      12, vue路由的钩子函数
      首页可以控制导航跳转,beforeEach,afterEach等,一般用于页面title的修改。一些需要登录才能调整页面的重定向功能。
      beforeEach主要有3个参数to,from,next:
      to: route即将进入的目标路由对象
      from: route当前导航正要离开的路由
      next:function一定要调用该方法resolve这个钩子。执行效果依赖next方法的调用参数。可以控制网页的跳转。
      13,vue.js的两个核心是什么?
      数据驱动、组件系统
      14,vue-router是怎么传递参数的
      (1)通过在router.js文件中配置path的地方动态传递参数 eg: path: ‘/detail/:id’
      (2).在router-link标签中传递参数

    <router-link :to={
    params: {
    x: 1
    }
    } />
    获取:this.$route.params.id
    15, v-if和v-for一起使用的弊端以及解决办法
    v-for的优先级比v-if高,导致每循环一次就会去v-if一次,而v-if是通过创建和销毁dom元素来控制元素的显示与隐藏,所以就会不停的去创建和销毁元素,造成页面卡顿,性能下降。
    解决办法:
    1.在v-for的外层包裹一个标签来使用v-if
    2将需要的判断在computed里处理,然后在放到v-for里
    16, vue中父组件如何获取子组件的属性和方法
    在子组件上定义ref属性来获取子组件的属性和方法

    // 这里是父组件
    <templete>
        <child ref="child"/>
    </templete>
    <script>
    method: {
        getChild () {
            this.$refs.child.属性名(方法名)
        }
    }
    </script>
    

    16, watch和computed的区别
    watch:监听数据变化,并执行一个回调函数
    computed:对已有的数据进行加工,具有缓存功能,只有数据发生改时,才会重新计算
    17, vue中父组件能监听到子组件的生命周期吗
    能,通过@hook:进行监听代码如下:

    // 这里是父组件
    <template>
        <child
        @hook:mounted="getChildMounted"
        />
    </template>
    <script>
    method: {
        getChildMounted () {
            // 这里可以获取到子组件mounted的信息
        }
    }
    </script>
    

    17, vue中的事件修饰符主要有哪些?分别是什么作用?
    .stop: 阻止事件冒泡
    .native: 绑定原生事件
    .once: 事件只执行一次
    .self:将事件绑定在自身身上,相当于阻止事件冒泡
    .prevent: 阻止默认事件
    .caption: 用于事件捕获
    18, watch如何实现深度监听

    watch: {
        obj: {
            handler: function(val) {
            },
            deep: true // 深度监听
        }
    }
    

    19, vue中如何解决页面不重新渲染问题?
    (1)修改对象属性后,页面未重新渲染:

    this.$set(对象名称, '属性名', '属性值')
    

    (2)使用this.forceUpdate()方法可重新渲染页面 20, 什么是路由懒加载 通过异步的方式来加载对应的路由组件,提高页面的加载速度 21,nextTick有什么作用?
    处理数据动态变化后,dom还未及时更新的问题。nexttick就可以获取到数据更新后最新的dom变化

    相关文章

      网友评论

          本文标题:vue组件化的好处及vue常见面试题

          本文链接:https://www.haomeiwen.com/subject/arzacktx.html