Vue核心概念及特性 (一)

982 阅读5分钟

Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。 特点: 易用,灵活,高效 渐进式框架

可以随意组合需要用到的模块 vue + components + vue-router + vuex + vue-cli

一.Vue的概念和特性

1.什么是库,什么是框架?

  • 库是将代码集合成一个产品,库是我们调用库中的方法实现自己的功能。

  • 框架则是为解决一类问题而开发的产品,框架是我们在指定的位置编写好代码,框架帮我们调用。

框架与库之间最本质区别在于控制权:you call libs, frameworks call you

Vue属于框架

2.MVC模型 && MVVM模型

在传统的mvc中除了model和view以外的逻辑都放在了controller中,导致controller逻辑复杂难以维护,在mvvm中view和model没有直接的关系,全部通过viewModel进行交互

Vue是MVVM模式

3.声明式和命令式

  • 自己写for循环就是命令式 (命令其按照自己的方式得到结果)

  • 声明式就是利用数组的方法forEach (我们想要的是循环,内部帮我们去做)

二.Vue的基本使用

1.mustache语法

允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据。在使用数据前需要先声明

  • 编写三元表达式

  • 获取返回值

  • JavaScript 表达式

<div id="app">
    {{ 1+1 }}
    {{ msg == 'hello'?'yes':'no' }}
    {{ {name:1} }}
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
    el:'#app',
    data:{
        msg:'hello'
    }
})
</script>

2.响应式数据变化

Vue中使用Object.defineProperty重新将对象中的属性定义,如果是数组的话需要重写数组原型上的方法

// 观察一个数据Vue2.0 definePropety, 针对数组 length// https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty// 只针对对象 数组没有使用definePropety的let arrayProto = Array.prototype; // 数组原型上的方法let proto = Object.create(arrayProto);['push','unshift','splice','reverse','sort','shift','pop'].forEach(method=>{    proto[method] = function (...args) { // 这个数组应该也被监控        // Array.prototype.push.call([1,2,3],4,5,6);        let inserted; // 默认没有插入新的数据        switch (method) {            case 'push':            case 'unshift':                inserted = args                break;            case 'splice': // 数组的splice 只有传递三个参数 才有追加效果                inserted = args.slice(2);            default:                break;        }        console.log('视图更新');        ArrayObserver(inserted)        arrayProto[method].call(this, ...args)    }});function ArrayObserver(obj) {    for (let i = 0; i < obj.length; i++) {        let item = obj[i];        // 如果是普通值 就不监控了        observer(item); // 如果是对象会被 defineReactive    }}function observer(obj) {    if (typeof obj !== 'object' || obj == null) {        return obj;    }    if (Array.isArray(obj)) {        //  上面处理的是数组格式 push shift splice (如果调用这三个方法)应该把这个值判断一下是否是对象        Object.setPrototypeOf(obj,proto); // 实现一个对数组的方法进行重写        ArrayObserver(obj)    } else {        // 下面的是处理对象的        for (let key in obj) {            // 默认只循环第一层            defineReactive(obj, key, obj[key]);        }    }}function defineReactive(obj, key, value) {    observer(value); // 递归创建 响应式数据,性能不好    Object.defineProperty(obj, key, {        get() {            return value;        },        set(newValue) { // 给某个key设置值的时候 可能也是一个对象            if (value !== newValue) {                observer(newValue);                value = newValue                console.log('视图更新');            }        }    })}let data = {    d: [1, 2, 3,{name:'mengwuya'}]};observer(data);data.d = [1,2,3]// observer(data);// data.name = {n:'jw'}// data.name.n = 'zf';// 特点: 使用对象的时候 必须先声明属性 ,这个属性才是响应式的// 1.增加不存在的属性 不能更新视图 (vm.$set)// 2。默认会递归增加 getter和setter// 3.数组里套对象 对象是支持响应式变化的,如果是常量则没有效果// 4.修改数组索引和长度 是不会导致视图更新的// 5.如果新增的数据 vue中也会帮你监控(对象类型)
  • 缺陷

  • 不能通过通过长度,索引改变数组

  • 不能给对象新增属性

  • 需要通过vm.$setvm.$delete方法强制添加/删除响应式数据

3.Vue实例上的方法

  • vm.$el;

  • vm.$data;

  • vm.$options;

  • vm.$nextTick();

  • vm.$mount();

  • vm.$watch();

  • vm.$set();

三.Vue中的指令

在vue中 指令 (Directives) 是带有 v- 前缀的特殊特性,主要的功能就是操作DOM

1.v-once

<div v-once>{{state.count}} </div>

2.v-html

永远不要对用户输入使用v-html,可能会导致xss攻击

<div v-html="text"></div>

3.v-bind

动态绑定属性需要使用v-bind进行绑定

<img v-bind:src="src">

可以使用:来简写 v-bind

4.v-for

<template v-for="(fruit,index) in fruits" >
    <li :key="`item_${index}`">{{fruit}}</li>
    <li :key="`fruit_${index}`">{{fruit}}</li>
</template>

多个元素循环时外层需要增加template标签,需要给真实元素增加key,而且key不能重复,尽量不要采用索引作为key的值

举个key值的例子:

5.v-if/v-else/v-show

v-if可以切换DOM元素是否存在,并且v-iffalse时内部指令不会被执行 v-show可以控制元素的显示及隐藏,主要控制的是元素样式

6.v-on

  • 事件的绑定 v-on绑定事件

  • 事件修饰符 (.stop .prevent) .capture .self .once .passive

7.v-model

双向数据绑定

<input type="text" :value="value" @input="input">
<input type="text" v-model="value">

  • select

    <select v-model="select">
        <option 
            v-for="fruit in fruits"
            :value="fruit">
                {{fruit}}
        </option>
    </select>

  • radio

    <input type="radio" v-model="value"  value="男">
    <input type="radio" v-model="value"  value="女">

  • checkbox

    <input type="checkbox" v-model="checks" value="游泳" >
    <input type="checkbox" v-model="checks" value="健身">

  • 修饰符应用 .number .lazy .trim

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

四.自定义指令

  • 全局指令和局部指令

  • 编写一个自定义指令

    • 钩子函数bind,inserted,update

       <input type="text" v-focus.color="'red'" />
          Vue.directive('focus',{
              inserted:(el,bindings)=>{
                  let color = bindings.modifiers.color;
                  if(color){
                      el.style.boxShadow = `1px 1px 2px ${bindings.value}`
                  }   
                  el.focus();
              }
          });

    • clickoutside指令

      <div v-click-outside="change">
              <input type="text"  @focus="flag=true" >
              <div v-show="flag">
                  contenter
              </div>
          </div>
          <script>
              let vm = new Vue({
                  el:'#app',
                  data:{
                      flag:false
                  },
                  methods:{
                      change(){
                          this.flag = false
                      }
                  },
                  directives:{
                      'click-outside'(el,bindings,vnode){
                          document.addEventListener('click',(e)=>{
                              if(!el.contains(e.target,vnode)){
                                  let eventName = bindings.expression;
                                  vnode.context[eventName]()
                              }
                          })
                      }
                  }
              })
          </script>

五.Vue中的生命周期

  • beforeCreate 在实例初始化之后,数据观测(data observer) 和 event/watcher 事件配置之前被调用。

  • created 实例已经创建完成之后被调用。在这一步,实例已完成以下的配置:数据观测(data observer),属性和方法的运算, watch/event 事件回调。这里没有$el

  • beforeMount 在挂载开始之前被调用:相关的 render 函数首次被调用。

  • mounted el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。

  • beforeUpdate 数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。

  • updated 由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。

  • beforeDestroy 实例销毁之前调用。在这一步,实例仍然完全可用。

  • destroyed Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。 该钩子在服务器端渲染期间不被调用。

钩子函数中该做的事情

  • created 实例已经创建完成,因为它是最早触发的原因可以进行一些数据,资源的请求。

  • mounted 实例已经挂载完成,可以进行一些DOM操作

  • beforeUpdate 可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程。

  • updated 可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态,因为这可能会导致更新无限循环。 该钩子在服务器端渲染期间不被调用。

  • destroyed 可以执行一些优化操作,清空定时器,解除绑定事件

六.面试题环节

  • 请说下对于MVVM的理解

  • Vue实现数据双向绑定的原理

  • Vue常用的指令有哪些?

  • v-model的原理

  • v-if 和 v-show 区别

  • Vue中 key 值的作用