当前位置:主页 > 查看内容

关于vue在面试或开发中需要留意的地方

发布时间:2021-08-16 00:00| 位朋友查看

简介:前段时间学习了Vue框架因此在我学习过程中整理了一些关于Vue的一些需要注意的地方在后面根据所开发的项目我可能会持续更新这篇基于Vue的博客欢迎交流 文章目录 1.Vue中的mvvm 2. methods和computed 3. v-on的参数传递问题与常用的修饰符 3.1 参数传递问题 3.……

前段时间学习了Vue框架,因此在我学习过程中整理了一些关于Vue的一些需要注意的地方,在后面根据所开发的项目,我可能会持续更新这篇基于Vue的博客,欢迎交流

1.Vue中的mvvm

我们使用过Vue的人后都会清楚Vue是一种使用mvvm模式开发的框架,但是它的具体体现在哪里呢。

查看源图像

如上图所示:

View层:就是我们常说的视图层,也就时我们的BOM。主要用于给用户展示数据

Model层:数据层,可能是我们给定的死数据,但在开发中大概率是从服务器端请求的数据

View-model层:视图模型层,是View和Model沟通的桥梁。它主要实现了数据的绑定和数据的动态监听,实现了响应式数据化。

2. methods和computed

在vue的options选项中,除了method方法可以处理我们的逻辑以外,计算属性也是可以操作相同的事情的,似乎他们很相似,其实他们是有区别的。所以这两个方式有什么区别呢。

  1. 计算属性不需要使用调用的形式的写法,而methods方法必须使用方法()调用的形式
  2. 计算属性依赖data中的变化,如果data并没有发生变化,则计算属性则会取缓存结果,也就是说计算属性具有缓存功能。
  3. method方法不论data中的值改不改变,都会重新调用。也就是调用多少次就实现多少次,因此比较浪费效率

3. v-on的参数传递问题与常用的修饰符

v-on经常用来处理一些事件监听的操作。它的语法糖是@事件

3.1 参数传递问题

我们在使用v-on来处理事件时经常在事件中嵌入方法。这时会分三种情况。

  1. 不传参时,可以不带可以不带括号,但是在方法实现时可加一个参数来表示当 前event。
  <div class="box">
    <button @click='btnclivk'></button>
  </div>
    btnclivk(e){
        console.log(e);//当前event对象
    }
  1. 传普通参数时,就像通常使用函数一样,但是需要注意的是,这里的参数要么是基本数据类型,要么就必须是data中的变量
  2. 在传普通参数时还需要event参数,这时传入$event()固定写法来表示当前event对象

3.2 常用修饰符

  1. v-on:事件.stop:阻止事件冒泡
  2. v-on:事件.prevent:阻止默认行为
  3. v-on:事件.{keycode}:等待指定键位触发
  4. v-on:事件.once:只触发一次
  5. v-on:事件.native:监听组件跟元素的原生

5.v-if和v-show的区别

首先我们应该清楚v-if和v-show都是用来处理dom是否显示出来的操作,因此我们在这里需要清楚他们有什么不同之处。

**v-if:**在使用v-if时通常时需要创建dom的,也就是说当值为false时,删除dom,当值为true时创建dom

**v-show:**在使用时通常时使用display:none的css样式来处理是否可见的

使用常见:

当在界面中需要重复显示和隐藏的操作时我们通常需要使用v-if,因为这样更见的节省效率。

当只有一次切换时我么通常选择v-if来进行操作。

6.v-for时绑定key与不绑定key的区别

首先想象一个场景,我们要将一个数组显示在li标签上,这时会使用到v-for来对li标签进行操作。但是当我有一个需求:你需要在数组中间插入一个内容应该如何操作。

这时我们可能想着直接将内容插入数组即可。但是你是否考虑到一个问题。在Vue的底层时如何实现的。

实际上Vue底层会使用虚拟DOM来实现这个操作,但是当我们插入在中间时,可能会出现以下这种情况:

除了前面相同的dom会复用以外,剩下的所有数据都要被重新渲染。

举个例子,如果我们现在的数组是[a,b,c,d,e],当我们现在在b后面加一个f。那么默认操作是将c—>f,d—>c,e—>d,最后插入e。这样做感觉效率有所欠缺。如下图所示:

img

因此官方建议我们使用绑定key,key的值一般为是一个唯一标识(注意不能使用index:因为插入元素后index会改变,因此无意义)。这样一来diff算法可以找到相同的复用dom进行渲染,也就是将我们有key的li一一对应起来

最后再将我们的待插入结点插入。这样就省了不少的效率。

img

所以用一句话来概括,key的作用主要是为了高效的更新虚拟DOM。

7. Vue中数组方法中哪些是响应式的

我们再使用Vue时感觉其很方便的一个主要原因就是它可以响应式刷新数据。

那么再我们使用数组时,有哪些方式是数据响应式的呢。

push()
pop()
shift()
unshift()
splice() 
sort()
reverse()
Vue.set()

主要:直接通过数组[下标值]是不能做到数据响应式的。

8. v-model双向绑定使用

8.1 用于表单时

v-model通常在表单中用来实现双向绑定,从而实现操作与数据实时更新,实现响应式。

也就是说当我们在表单中输入数据时,实际上数据直接就发生了更改。

lizi :

	<input type="text" v-model='message'>
    <p>{{message}}</p>

以上例子就可以实现当我们输入数据时,message就实时的发生了改变,对应的p标签的内容也就发生了改变。

实际上v-model是以下两个操作的语法糖:

  1. v-bind为value绑定数据
  2. v-on:input 为表单绑定触发事件,从而为message传值。
 <input type="text" :value='message' @input='message=$event.target.value'>
 <p>{{message}}</p>

其实除了在text上外,v-model还经常用在select、chacked、radio上。

修饰符:

这里主要介绍它的三个修饰符

  1. v-model.lazy:表示不实时更新数据,只有在用户回车时或者input失焦时才更新数据
  2. v-model.number:在默认情况下v-model都是一个string类型的字符串,这个修饰符可以使返回一个数字类型
  3. v-model.trim:去空格

9. 为什么组件中data必须是一个函数类型

首先vue的组件大多是用来复用的,那么他每复用一次,就会使用我们的data属性,如果这时我们data是一个对象时,那么当我们复用组件时则会出现一个问题,一个组件中数据变化,那么所有的组件中的数据都会变化。因此vue的底层在data属性这里添加了这个设定。

当然在开发过程中也可能会遇到这个属性,这个可以将对象暴露出去再引入,实现所有组件数据的一致性。

我们可以看一下一个很简单的例子:

写一个计数器的组件

 Vue.component('mycom', {
    template: '#mypom',
    data() {
      return {
        message: 0
      }
    },
    methods: {
      add() {
        this.message++
      },
      decre() {
        this.message--
      },
    },
  })

使用:

<div id="app">
    <mycom></mycom>
    <mycom></mycom>
    <mycom></mycom>
    <mycom></mycom>
  </div>

这时我们会发现每个组件都是独立的,这时因为,这就归功于data属性是一个函数。因此他们不会共同使用一个对象内的数据。

但是如果我们有这种一个动,全部动的需求时,也很容易。

  var obj={
    message: 0
  }
  Vue.component('mycom', {
    template: '#mypom',
    data() {
      return obj
    },
    methods: {
      add() {
        this.message++
      },
      decre() {
        this.message--
      },
    },
  })

这就可以实现我们想要的效果。

10.父子组件之间实现的复杂双向绑定

一个需求:现在在组件中有两个input,其中需要实现input的双向绑定(且改变父组件的data值),且输出时第二个input的值时第二个值的100倍。

用到的技术点:父子组件通信,表单的双向绑定

值得一提的是当我们Vue官方不建议使用model时直接将props的值放在里面,因为这样这里的值是从父组件传递而来,因此直接修改可能会导致紊乱。因此我们需要借助组件的data属性来做值得绑定;

至于另一个需求,改变data的属性,那么我们可以使用父传子的方法将组件的data传给父组件,再去修改父组件data的值,这样一来我们及修改了父组件的data,同时也就修改了子组件props的相关值。

最后的需求是100倍,这个也在我们的input事件触发时监听,然后计算,在通过emit传递即可

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <div id="app">
    <mycon :cnum1='num1' :cnum2='num2' @event1='event1' @event2='event2'></mycon>
  </div>
  <template id="cpm">
    <div>
      <p>props:{{cnum1}}</p>
      <p>data:{{copycnum1}}</p>
      <input type="text" name="" id="" :value='copycnum1' @input='docopycnum1'>
      <p>props{{cnum2}}</p>
      <p>data{{copycnum2}}</p>
      <input type="text" name="" id="" :value='copycnum2' @input='docopycnum2'>
    </div>
  </template>
</body>
<script src="../vue.js"></script>
<script>
  var cpm = {
    template: '#cpm',
    props: {
      cnum1: Number,
      cnum2: Number,
    },
    data() {
      // 官方建议做法
      return {
        copycnum1: this.cnum1,
        copycnum2: this.cnum2,
      }
    },
    methods: {
      docopycnum1(event) {
        this.copycnum1 = event.target.value;
        this.$emit('event1', this.copycnum1);
        this.copycnum2=this.copycnum1*100
        this.$emit('event2', this.copycnum2)
      },
      docopycnum2(event) {
        this.copycnum2 = event.target.value;
        this.$emit('event2', this.copycnum2)
        this.copycnum1=this.copycnum2/100
        this.$emit('event1', this.copycnum1)
      }
    },
  }
  new Vue({
    el: '#app',
    data: {
      num1: 0,
      num2: 0
    },
    components: {
      mycon: cpm
    },
    methods: {
      event1(data) {
        this.num1 = parseFloat(data);
      },
      event2(data) {
        this.num2 = parseFloat(data);
      }
    },
  })
</script>

</html>

11.vue使用webpack时的注意事项

首先我们项目中需要有vue的环境。

npm安装:

npm install vue --save

安装以后,我们直接写vue相关的代码后进行编译会发现有报错:

在这里插入图片描述

这个错误的原因是因为vue在构建发布时有两个版本,runtime-only和runtime-compiler

**runtime-only:**该版本不能有任何的template

**runtime-compiler:**代码里可以有template,因为有compiler可以编译template

解决方案(在webpack配置文件中加入):

 resolve: {
    alias: {
      'vue$': 'vue/dist/vue.esm.js'
    }
  }

因为这个resolve时专门来处理路径问题的,所以故名思意,我们也可以猜出来,这是改变了默认配置

11.2 编译vue文件

使用webpack中打包vue文件时,我们需要安装vue-loader插件和vue-template-compiler 插件

接着在配置文件中配置:

  module: {
    rules: [
      {
        test: /\.vue$/,
        use: ['vue-loader']
      }
    ]
  },

使用之后我们会发现会报错。

报错原因大概是:vueloader不能使用,缺少一个插件。

我们可以配置一个插件(不用安装):

const VueLoaderPlugin = require('vue-loader/lib/plugin');
  plugins: [
    new VueLoaderPlugin(),
    ...
  ],

12.Runtime-Compiler和Runtime-Only的区别

当我们使用vue cli2来构建项目时通常会让我们选择vue的构建模式。我们创建两个项目会发现src目录下的main.js文件按有所不同

Runtime-Compiler模式:

import App from './App';
new Vue({
  el: '#app',
  components: { App },
  template: '<App/>',
});

Runtime-Only模式:

import App from './App';
new Vue({
  el: '#app',
  render:h=>h(app)
});

我们发现这两个模式在Vue实例中的写法有所不同,我们发现Runtime-Compiler模式时使用的时我们常规的注册使用组件的方式,而Runtime-only是使用render函数进行渲染,那么这两者有什么区别?

这是一张template在Vue中的渲染过程:

在这里插入图片描述

ast:template解析后的产物,抽象语法树

render函数:ast被编译就的产物,用于生成一个虚拟dom

virtual dom:虚拟dom

我们可以看出它大概需要这几个过程:template->ast->render函数->虚拟dom->渲染到ui

然而我们使用第二种Runtime-Only是直接在render函数的结点开始往下操作的。

结论:Runtime-Only的效率要比Runtime-Compiler运行效率高,并且源代码的量更少,打包后的体积更加轻量。

runtime-only: 将template在打包的时候,就已经编译为 render函数
runtime-compiler: 在运行的时候,才去编译 template

因此我们更加推荐使用Runtime-Only模式来构建我们的项目。

关于Render函数的使用:

1.直接在render函数中给我们的回调函数传入我们的组件对象。

new Vue({
  el: '#app',
  // components: { App },
  // template: '<App/>',
  render:(e) => {
    return e(App)
  }
});

2.传入基本的dom:

 render:(e) => {
    return e('div',{class:'box'},['web'])
  }

其中第一个参数是dom元素,第二个参数是属性值,第三个为data。

13.vue-router懒加载

? 关于路由的懒加载,官方给我们的解释为:

当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。

? 其实就是说我们的每一个路由对应的就是一个给用户展示的页面,然而按照常规的操作这些页面最终会通过webpack打包为一个bundle.js的文件,因此就造成了这个页面十分的庞大,所在在请求的时候可能会花费一定的时间,给用户造成不好的体验。因此我们可以通过路由懒加载的方式来解决这个问题。也就是说不同的路由页面打包成不同的js文件,这样就解决了服务器耗时的问题。

在我们未使用懒加载时,打包vue项目会生成三个文件,一个是app的所有业务代码,一个是组织管理模块关系的代码,还有一个就是项目引入第三方的代码。

? 接着我们看一下实现懒加载的方式:有三种方式分别是结合异步组件的方式,AMD的方式,es6模块化的方式

? 在ES6中, 我们可以有更加简单的写法来组织Vue异步组件和Webpack的代码分割.所以我们就是用最简单的方式:

 component: () => import('../components/about.vue') 

实例:

 routes: [
    {
      path: '/',
      redirect: '/home'
    },
    {
      path: '/hello',
      component: () =>import('../components/HelloWorld.vue') 
    },
    {
      path: '/home',
      component: () => import('../components/home.vue')  
    },
    {
      path: '/about',
      component: () => import('../components/about.vue') 
    },
    {
      path: '/person/:userid',
      component: () => import('../components/person.vue') 
    }
  ],

我们发现每个路由界面都有一个js文件,这样一来就可以做到我们按需加载的要求,减轻了服务器的压力

;原文链接:https://blog.csdn.net/M_Edison/article/details/115871958
本站部分内容转载于网络,版权归原作者所有,转载之目的在于传播更多优秀技术内容,如有侵权请联系QQ/微信:153890879删除,谢谢!

推荐图文


随机推荐