飞道的博客

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

314人阅读  评论(0)

前段时间学习了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。这样做感觉效率有所欠缺。如下图所示:

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

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

所以用一句话来概括,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
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场