Vue学习

框架和类库

前端从后端获取到数据之后,如何将其展示到页面上?

  1. 原生DOM操作,将数据一个个的往上放

  2. 字符串拼接法

  3. 模板引擎

  4. 数据驱动的MVVM框架

Vue等这些框架做的事情,其实就是简化数据渲染的操作!提高开发效率的!!

框架(Framework)

框架是一整套完整的解决方案,我们需要将自己的代码按照框架的规则,放在合适的位置,框架会在合适的时机,帮我们调用代码,实现指定的功能。(framework call you)

类库(Library)

类库是一系列方法的集合,在我们编程的时候,我们需要自己决定什么时候,调用哪个方法,实现什么功能。(you call library)

MV*框架

MV*模式指的其实就是对代码进行按照功能划分模块的方式!

MVC

  • Model: 和数据相关的代码,负责提供数据的!

  • View: 和展示相关的代码,负责展示数据的!

  • Controller: 负责将数据转交给视图,同样负责从视图中收集数据,转交给Model(需要程序员自己控制)

MVVM

  • Model、View:与MVC的是一样的

  • View-Model: 这个部分是由框架实现的,不需要程序员再进行开发了,就可以自动实现数据到视图,以及视图到数据的流程!

Vue是什么?

渐进式的JavaScript框架

渐进式(Progressive)

Vue的核心功能非常小,可以用来支撑小型的网页的开发,Vue还支持其他额外的一些插件,可以逐步的扩展框架的功能用以支撑大型企业级项目的开发。 由小到大演变的过程,其实就是所谓的渐进式。

Vue的使用

  1. 安装vue 通过npm 或者yarn(也可以直接去官网下载vue.js文件)

  2. 在页面中引入vue.js文件

  3. 在script标签中创建Vue的实例

    const vm = new Vue({
        // 当前vue实例要控制的元素范围,放元素的id
        el:'#app',
        data:{
             // data中放的就是要在视图中展示的数据
            name:'zs'
    	}
    })
    // 如果之前用过模板引擎的,比如art-template,这里就可以类比的来看
    // art-template中使用的方式  template('模板id',对象类型的数据)
    `el: '#app'` // 相当于和页面建立了绑定关联
    `data:{...}` // 相当于说绑定的那部分数据是什么
    
    1. 在HTML代码中创建视图对应的元素

    2. 在视图元素的范围内,通过插值表达式或者指令来使用Vue的功能

      <div id='app'>
          <h1>
              {{name}}
          </h1>
      </div>
      

数据驱动(核心的理念)

什么是数据驱动? 就是通过控制数据的变化来改变某物或某事。

Vue的数据驱动中, 数据驱动什么? 就是说物或者事是什么? 这里的vue数据驱动的是视图也就是DOM元素让DOM的内容随着数据的改变而改变, 这里视图(DOM)可以理解成上面的改变的某物或者某事

如果想要操作页面元素的变化,不要再去想DOM操作了!!要想办法通过修改数据来达成效果!

插值表达式

可以看到我们上面使用{{name}}这样的方式把数据绑定到了页面上,这种语法我们叫做插值表达式

也叫做小胡子语法

表达式和语句怎么区分? (参考说明 https://zhuanlan.zhihu.com/p/38622128

语句是为了进行某种操作,一般情况下不需要返回值,而表达式都是为了得到返回值,一定会返回一个值(这里的值不包括undefined)

简单的理解就是:表达式指的就是有值得内容, 我们把他放到等号的右边,看能不能成立,如果可以,就是表达式

插值表达式中可以出现的内容

  • {{data中的数据名}}
  • {{ 1 }}
  • {{ “字符串” }}
  • {{ true }}
  • {{ 数据名.方法}} {{name.toUpperCase()}}

插值这里存在一个问题——插值闪烁

原因:Vue加载太慢,没人处理插值表达式,直接原样显示在页面上,等Vue加载完了,才会处理,这时数据才会展示出来,会有闪烁的效果出现
解决方案: v-cloak

  1. 给元素添加v-cloak指令

    <h1 v-cloak>{{name}}</h1>
    
  2. 在style标签中添加一个 v-cloak的属性选择器样式 display:none

    [v-cloak]{
        display:none
    }
    

解决的原理: 一开始先隐藏,当Vue加载完了,数据渲染完成,就把v-cloak删掉,数据就显示出来了!

数据的双向绑定

数据绑定,说的就是,将数据和视图关联起来

  • 单向绑定: 当数据发生变化的时候,页面中的内容也会随之发生变化,而页面中的内容不会影响数据的变化
<!-- v-bind是一个单项绑定的指令 -->
<input type="text" :value="name">
  • 双向绑定:当数据发生变化的时候,页面中的内容会随之变化,页面中的内容发生变化的时候,数据也会随之变化 双向绑定一般只会出现在表单元素中!

    <!-- 双向绑定最实用的场景,就是获取用户在表单中输入的数据 -->
    <input type="text" v-model="name">
    

    双向绑定原理

    可以分为两部分,一部分是视图数据变化,如何去改变绑定的数据,另一部分是绑定的数据改变,如何去改变视图数据。

    第一部分是很简单的,我们可以监听表单控件的input事件,就可以知道数据发生了修改,但是关键是第二部分,我们怎么知道绑定的数据修改了呢?

    Object.defineProperty方法

    // 1. 如何给对象添加一个属性?
    
    let obj = {name: ""}
    obj.age = 18;
    obj["gender"] = "male";
    
    // Object.defineProperty可以用来给对象添加属性,也可以用来修改现有的属性
    // 在添加属性的时候,可以设置属性以下的特性:
    // 1. 是否为只读属性
    // 2. 是否可以删除
    // 3. 是否可以遍历
    // 4. 可以为属性注册像改变事件一样的函数
    
    // Object.defineProperty(要添加或者修改属性的对象, 要添加或者修改的属性名, 特征对象)
    
    Object.defineProperty(obj, "name", {
        // 1. 默认的,该属性是只读的,不能被赋值 默认是false
        writable: true,
        // 2. 默认的,该属性不能被for in循环遍历 默认是false
        enumerable: true,
        // 3. 默认的,该属性不能被delete删除 默认是false
        configurable: true,
        // value属性用来设置属性的默认值
        value: "123"
    })
    
    
    let nameValue = "";
    
    Object.defineProperty(obj, "name", {
        // set和get不能和上面的额writable,value同时出现
        set(value){
            // 这个函数就像是属性的改变事件,我们在给属性赋值的时候
            // JS内部会自动调用这个函数
            console.log("属性被赋值了");
            // 在set函数中,需要接收用户所赋值的内容,也就是等号右边的内容 可以通过value形参接收
            // 将其存储起来
            nameValue = value;
        },
        get(){
            // 这个函数就像是属性的被获取的事件,只要有人用到这个属性了,那这个函数就会被调用
            console.log("属性被获取值了")
            // 这个函数会在用户获取值得时候调用,用户获取到的值,就是当前函数的返回值
            return nameValue;
        }
    })
    

    通过Object.defineProperty 方法我们就可以像监听事件一样来监听绑定数据是何时修改的,然后把这个修改后的数据重新帮到表单控件上

    let nameValue = "";
    Object.defineProperty(obj, "name", {
        set(value){
            input.value = nameValue = value;
        },
        get(){
            return nameValue;
        }
    })
    

计算属性(computed)

如果页面中需要某个数据,而这个数据是根据当前data中的数据计算出来的,那么我们就使用计算属性。计算属性的本质: 就是一个函数,这个函数会有一个返回值

  • 计算属性的使用

    <div id="app">
        FirstName<input type="text" v-model="firstName">
        LastName<input type="text" v-model="lastName">
        <!-- 这里直接使用属性名就行了不用加小括号-->
        FullName<input type="text" v-model="fullName">
    </div>
    
     <script>
        const vm = new Vue({
          el: "#app",
          data: {
           firstName: "",
           lastName: ""
          },
          computed: {
            // 计算属性的属性名  
             fullName(){
               return this.firstName + "·" + this.lastName
             }
          }
        })
    </script>
    
    • 计算属性的完整形式
    //因为我们用v-model进行了双向绑定,所以我们就需要使用完整形式来类似于监听数据的修改(用set监听)
    fullName: {
        get(){
            // 这个函数会在用户获取这个计算属性值得时候调用,返回值就是用户获取到的值
            return this.firstName + "·" + this.lastName
        },
        set(value){
            // 这个函数会在用户为这个计算属性赋值的时候调用
            // 在这个函数中,我们可以对fullname进行拆分
            // value就是用户给这个计算属性赋的值
            this.firstName = value.split("·")[0]
            this.lastName = value.split("·")[1]
            }
    	}
    }
    
    • 计算属性(computed)和方法(methods)的区别
      1. methods 可以传参,计算属性不能
      2. methods不一定有返回值,而计算属性必须有返回值
      3. 计算属性有缓存,如果页面中多次使用,只会调用一次计算属性的函数
      4. 如果用methods来实现计算属性的功能,他是没有缓存的,使用多次的时候,用几次调几次性能不好

侦听器(watch)

虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。这就是为什么 Vue 通过 watch 选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。

侦听器的使用

const vm = new Vue({
    el: "#app",
    data: {
        msg: "hello world"
    },
    watch: {
        // watch属性是一个对象,对象中的属性名就是要监视的数据(data中的)的名字
        // 当这个数据发生变化的时候,这个函数会自动被执行
        // 并且Vue提供了两个参数,newValue 是修改后的值, oldValue 是修改前的值
        msg(newValue, oldValue){
            console.log("msg发生变化了", newValue, oldValue)
        }
    }
})

侦听器完整形式

const vm = new Vue({
    el: "#app",
    data: {
        person: {
            name: "张学友",
            age: 18
        }
    },
    watch: {
        // 如果要监视对象中的属性的变化,不能只写对象的名字
        // 因为对象是个引用类型的数据,属性发生变化的时候,地址是不会变化的
        // 地址不变化,监视就不生效

        // 我们需要在监视属性的时候,将对象.属性名作为监视函数的名字,这样就能监视到属性的变化了
        // 这么写是非常麻烦的,特别是针对属性特别多的时候,对于简单类型数据来说可以这么写
         "person.name": function(newValue, oldValue){
           console.log("person.name发生变化了", newValue, oldValue)
         },
         "person.age": function(newValue, oldValue){
           console.log("person.age发生变化了", newValue, oldValue)
         }

        // watch的平时的写法只是一个简写形式,他还有一个完整形态
        // 针对数组、对象这样的复杂类型需要如下这么写
        person: {
            handler(newValue, oldValue){
                console.log("person变化了")
                console.log(newValue, oldValue)
            },
            // 进行深度监视,只要对象的任意属性发生变化,都会触发这个监视函数
            // 进行深度监视的时候,newValue和oldValue值一样,因为监视的是引用类型的值,newValue和oldValue指向的是同一个对象
            deep: true,
            // 这个属性设置的是,代码一开始运行,就执行一次handler函数!
            immediate: true
        }
    }
})

filter(过滤器)

过滤器其实就是一个函数,允许你自定义过滤器,可被用于一些常见的文本格式化,过滤器可以用在两个地方:双花括号插值和 v-bind 表达式

<!-- 在双花括号中 -->
{{ message | capitalize }}

<!-- 在 `v-bind` 中 -->
<div v-bind:id="rawId | formatId"></div>

<!-- 
	带参数的过滤器(v-bind使用方式一样),过滤器的默认第一个参数就是 管道符 "|" 前面的表达式的值(要过滤的数据) 括号中添加的是第二次开始的参数
-->
{{ message | capitalize(arg1,arg2)}}

注:过滤器可以串联

{{ message | filterA | filterB }}
<!--
filterA 被定义为接收单个参数的过滤器函数,表达式 message 的值将作为参数传入到函数中。然后继续调用同样被定义为接收单个参数的过滤器函数 filterB,将 filterA 的结果传递到 filterB 中。
-->
  • 定义全局过滤器

    全局注册的过滤器,当前页面中所有的vue实例都可以使用

    Vue.filter('过滤器名', function('要过滤的数据',arg1,arg2){
        // 对过滤的数据进行加工后输出
        return xxx
    })
    
  • 定义局部过滤器

    只在某个vue实例中生效(是私有的) 在创建vue实例的时候,参数对象中添加一个 filters属性,将过滤器函数注册在这个对象中即可

    {{message | dateFormat('YYYY-MM-DD')}}  <!-- 2019-06-18 -->
    
    const vm = new Vue({
        el:'#app',
        data:{
            message:new Date() // Tue Jun 18 2019 20:20:33 GMT+0800 (中国标准时间)
        },
        filters:{
            // 第一个参数就是原始的日期,第二个参数是传递的需要的日期格式
            dateFormat(data,pattern){
                // 这里使用了moment.js这个库
                return moment(data).format(pattern)
            }
        }
    })
    

自定义指令(directive)

有的情况下,你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令(自定义指令在实际开发中用的不多)

以Vue官网的Demo为例

<div id='app'>
	<input type='text' v-focus>    
</div>

可能会有疑问直接用autofocus这个不就能自动获取焦点了吗?但是这里是有问题的,当我们加了autofocus 这个属性后,界面一开始的确执行了这个属性,但是因为上面这部分代码是在Vue控制的区域中的,Vue自身生命周期会对这段代码进行编译,导致之前执行一次的autofocus不会再一次执行,因此不会起作用,因此需要用到自定义指令

  • 全局自定义指令

    // 注意:这里的指令名是不带 v- 的,但是界面上使用的时候需要带 v-
    Vue.directive('focus',{
        // 当被绑定的元素插入到 DOM 中时……
      inserted: function (el) {
        // 聚焦元素
        el.focus()
      }
    })
    
  • 局部自定义指令

    const vm = new Vue({
        el:'#app',
        directives: {
          focus: {
            // 指令的定义
            inserted: function (el) {
              el.focus()
            }
          }
        }
    })
    
  • 指令钩子函数

    什么是钩子函数?钩子函数指的就是在特定的时机下触发的函数

    Vue.directive('focus',{
        bind(el,binding){ // 比较常用
            // 在vue开始解析这个指令的时候执行的
            // 在这里一般可以进行一些样式的设置,比如设置字体颜色、字体粗细等
        },
        inserted(el,binding){
            // 在vue将当前指令所在的元素渲染到页面上的时候执行的
            // 比如执行自动获取焦点的操作,需要在inserted中执行
        },
        update(el,binding){ // 比较常用
            // 当当前指令绑定的数据发生变化的时候,页面元素还没有更新的时候调用
            // 一般update中执行的和bind中执行的差不多,以此就有了后面的简写形式
        },
        componentUpdated(el,binding){
            // 当当前指令绑定的数据发生变化的时候,页面元素更新全部完成时候调用
        },
        unbind(el,binding){
            // 指令被卸载的时候调用
        }
    })
    

    钩子函数参数说明

    • el: 表示的是当前的元素
    • binding:一个对象
      • name 指令名,不包括 v- 前缀。
      • rawName 带v的指令名
      • arg 传给指令的参数
      • modifiers 一个包含修饰符的对象 ,修饰符对象为 { foo: true, bar: true }
      • expression =后面的表达式 这是一个字符串
      • value 表达式对应的值

    指令的简写形式

    在很多时候,你可能想在 bindupdate 时触发相同行为,而不关心其它的钩子。比如这样写:

    Vue.directive('color-swatch', function (el, binding) {
      el.style.backgroundColor = binding.value
    })
    
    const vm = new Vue({
        el: '#app',
        data: {
            msg: 'hello world!'
        },
        directives: {
            mytext(el, binding) {
                el.innerText = binding.value
            }
        }
    })
    

Vue实例生命周期

一个实例从开始到最后消亡所经历的各种状态,就是一个实例的生命周期

总体可以分为三个阶段:初始化阶段、更新(运行)阶段、销毁(卸载)阶段

生命周期
  1. 初始化阶段

    1. (Init Events & Lifecycle) 初始化事件和生命周期 (具体是什么事件参考这里)
    2. (Init injections & reactivity)初始化数据(把data中的数据通过Object.defineProperty加到Vue实例中),最先能访问到数据是在这个时候
    3. (Has “el” option?)判断当前创建Vue实例的时候传进来的参数中是否有el属性
      • (Has ‘template option ?’)如果有,就继续判断是否有template属性
        • (Compile template into render Function)如果有,就编译模板,创建一个render函数出来
        • (Compile el’s outerHTML as template)如果没有,就把el对应的元素的html代码编译成模板(我们常见的代码要走这一步)
      • (when vm. m o u n t ( e l ) i s c a l l e d ) 如 果 没 有 , 就 当 v m . mount(el) is called)如果没有,就当vm. mount(el)iscalledvm.mount被调用之后继续执行(我们常见的代码要走这一步)
    4. (Create vm. e l a n d r e p l a c e ′ e l ′ w i t h i t ) 创 建 v m . el and replace &#x27;el&#x27; with it)创建vm. elandreplaceelwithitvm.el(里面的数据已经完全渲染好了), 并且用这个新创建的元素,把页面中的el给替换掉

    这个时候,我们就在页面上看到了有数据的html元素了!!!

  2. 更新(运行)阶段

    1. (when data changes)Vue会监听数据的变化,当数据发生变化的时候
    2. (Virtual DOM re-render and patch)Vue会通过虚拟DOM重新渲染,对页面内容进行更新
  3. 销毁(卸载)阶段

    1. (when wm. d e s t r o y ( ) i s c a l l e d ) 当 v m . destroy() is called) 当vm. destroy()iscalledvm.destory被调用的时候
    2. (Teardown watches, child components and event listeners)会将所有的和当前vue实例相关的资源进行释放
生命周期钩子函数
  • create: 在数据初始化前后调用的事件

    • beforeCreate
    • created
  • mount: 在将有数据的元素挂载到页面前后调用的事件

    • beforeMount
    • mounted
  • update: 数据发生改变,页面更新前后调用的事件

    • beforeUpdate
    • updated
  • destroy: 当vm.$destroy被调用,资源释放前后调用的事件

    • beforeDestroy
    • destroyed
const vm = new Vue({
    el:'#app',
    data:{
        msg:'hello world'
    },
    beforeCreate() {
        // beforeCreate 数据初始化之前执行的,这时候还没数据
        // console.log(this.msg);
        console.warn("beforeCreate 被执行了")
    },
    created() {
        // 能够访问数据最早的钩子函数,其实就是created
        // 重点: 工作中最常用的就是这个钩子函数
        // 页面一家在就要请求数据的ajax请求一般都在这里发送
        // console.log(this.msg);
        console.warn("created 被执行了")
    },
    beforeMount() {
        // console.log(document.getElementById("app"));
        console.warn("beforeMount 被执行了")
    },
    mounted() {
        // console.log(document.getElementById("app"));
        // 如果在实际开发当中,我们要访问有数据的DOM,那么久需要在mounted钩子函数里去做
        console.warn("mounted 被执行了")
    },
    beforeUpdate() {
        // 这里可以访问更新前的DOM
        console.log(document.getElementById("app").innerHTML);
        console.warn("beforeUpdate 被执行了")
    },
    updated() {
        // 这里可以访问更新后的DOM
        console.log(document.getElementById("app").innerHTML);
        console.warn("updated 被执行了")
    },
    beforeDestroy() {
        console.warn("beforeDestroy 被执行了")
    },
    destroyed() {
        console.warn("destroyed 被执行了")        
    }
})

在这里插入图片描述

Vue实例的完整形式

根据需要添加相应的属性参数

const vm = new Vue({
    el:'#app',
    data:{
        msg:'hello world!'
    },
    methods:{
        // 定义函数、事件处理函数
        fn(){}, // 简写方式
        fn1:function(){}
    },
    computed:{
        cmp(){return 数据},
        cmp1:function(){return 数据},
        // 完整形式,一般有双向绑定的时候会用到这完整形式
        cmp:{
            get(){
                return 数据
            },
            set(value){
              	this.xxx = value
            }
        }
    },
    watch:{
        msg(newValue, oldValue){
            // msg数据改变的时候自动执行
        },
        // 完整形式
        msg:{
            handler(newValue, oldValue){
                // msg数据改变的时候自动执行
            },
            deep:true, // 默认是false
            immediate:true // 默认是false
        }
    },
    filters:{
        // 局部过滤器
        // 参数一定死了是 管道符 "|" 前面的值
        dateFormat(data,arg1,arg2){},
        dateFormat:function(data,arg1,arg2){}
    },
    directives:{
        // 局部自定义指令
        mytext:{
            // 指令钩子函数
            bind(el,binding){},
            inserted(el,binding){},
            update(el,binding){},
            componentUpdated(el,binding){},
            unbind(el,binding){}
        }
    },
    beforeCreate(){},
    created(){},
    beforeMount(){},
    mount(){},
    beforeUpdate(){},
    updated(){},
    beforeDestroy(){},
    destroyed(){}
})

Vue指令

vue中内置了很多自定义的类似于html属性的东西(带有 v- 前缀的特殊特性),每个vue提供的这种属性都会对应一个特定的功能,这些类似于自定义属性的东西就叫做指令,职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM

先定义一个Vue的实例,后面的指令都取值自这里

const vm = new Vue({
    el:'#app',
    data:{
        msg:'hello world',
        msg1:'<h1>hello world</h1>'
        imageSrc:'./logo.png',
        size:24,
        isShow:true,
        classA:{
            red:true,
            bd:false
        },
        divStyle1: "width: 100px; height: 100px; background-color: pink;",
        divStyle2: {width: "100px", height: "100px", backgroundColor: "pink"},
        divStyle3: {width: "50px", height: "50px", backgroundColor: "green"},
        items:['zs','ls','ww'],
        items1: [
            {id:1, name: 'zs', age: 18 },
            {id:2, name: 'ls', age: 24 },
            {id:3, name: 'ww', age: 30 }
          ]
    }
})
v-bind指令

在Vue中给标签的属性赋值数据的时候,不可以使用插值表达式,因此需要用到v-bind


<!-- 绑定一个属性 -->
<img v-bind:src="imageSrc">
<!-- 缩写 -->
<img :src="imageSrc">
<!-- class 绑定 -->
<!-- 可以给class属性绑定一个对象,对象中的每个属性名代表的就是对应的类名,属性的值为布尔值,如果是true,就代表当前的元素拥有该类样式,如果是false,就代表当前的元素没有该类样式 -->
<div id="box" :class="{red: true, db: true}"></div> <!-- 直接赋值 -->
<div id="box" :class="classA"></div>  <!-- 从Vue实例中取值-->
<div :class="[classA, { classB: true, classC: false }]">   <!-- 可以是一个数组-->
<!-- style 绑定 -->
<div :style="divStyle1"></div>
<div :style="[divStyle2, divStyle3]"></div>
<!-- 如果数组中直接写类名需要用引号包裹,不然回去实例中找变量名 -->
<div :style="['red', 'db']"></div>
v-for指令

基于源数据多次渲染元素或模板块,可以实现数组/对象/字符串/数字/Iterable的遍历

<div v-for="item in items">
  {{ item }}
</div>
<!-- item表示每一项 index表示对应的索引下标-->
<div v-for="(item, index) in items">{{item}} - {{index}}</div>
<!-- val表示对象的属性值 key表示对象的属性名 -->
<div v-for="(val, key) in object"></div>
<!-- 还可以如下使用,去获取每一项的id然后绑定给标签属性-->
<div v-for="item in items" :key="item.id">
  {{ item.text }}
</div>
<!-- 遍历一个数字 -->
<div v-for='item in 5'>
    {{item}}
</div>
<!-- 遍历一个字符串-->
<div v-for='item in "hello"'>
    {{item}}
</div>

v-for使用最好如下,与key配合使用

当 Vue 正在更新使用 v-for 渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。

“就地更新”:当在进行列表渲染的时候,vue会直接对已有的标签进行复用,不会整个的将所有的标签全部重新删除和创建

在这里插入图片描述

<!-- 让生成的每一项有一个唯一的标识 -->
<div v-for="item in items" :key="item.id">
  {{ item.text }}
</div>

增加Key的好处

  • 加了key属性之后可以提升列表的渲染性能
  • 加了key属性之后可以避免数据混乱(只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出
v-show指令

根据表达式之真假值,切换元素的 display CSS 属性。

<!--  isShow=true 元素显示 isShow=false 标签增加display:none 不显示--> 
<div id="box" v-show="isShow">hello world</div>  
v-if指令

根据表达式的值的真假条件渲染元素。在切换时元素及它的数据绑定 / 组件被销毁并重建,即为false是删除标签和标签数据,为true时重新创建标签和绑定数据

<!--  isShow=true 元素显示 isShow=false 标签被移除不显示--> 
<div id="box" v-if="isShow">hello world</div> 

v-show 和 v-if 比较

区别

  • v-show如果条件是false,里面的所有的vue相关的指令照常进行解析和渲染了
  • v-if如果条件是false,里面的所有的vue相关的指令都不会进行解析和渲染了
  • v-show指令接受一个数据,如果数据是true则元素展示,否则元素隐藏
  • v-if也能控制展示和隐藏,但是,他是直接将元素从页面dom树种移除掉了

应用场景

  • v-show 用于简单的页面中的元素展示和隐藏切换比较频繁的场景!
  • v-if用于只判断一次的场景,因为这个可以用来提高性能,比如管理员拥有的权限,如果是管理员,就展示,如果不是管理员就不展示,就用v-if
v-cloak指令

这个指令保持在元素上直到关联实例结束编译。和 CSS 规则如 [v-cloak] { display: none }一起用时,这个指令可以隐藏未编译的 Mustache 标签直到实例准备完毕。

<div v-cloak>
  {{ message }}
</div>
[v-cloak] {
  display: none;
}
v-text指令

更新元素的 内容

<span v-text="msg"></span>  
<!-- 等价于-->
<span>hello world</span>

v-text指令和之前的插值表达式很像,但是两者有区别

  • 插值表达式会存在插值闪烁问题,而v-text不会有
  • 插值表达式值替换{{Mustache }}的内容,而v-text 会替换标签原本的内容
v-html指令

更新元素的 innerHTML

<div v-html='msg1'></div>
<!-- 等价于 -->
<div>
    <h1>
        hello world
    </h1>
</div>
v-on指令

绑定事件监听器,事件类型由参数指定

<button v-on:click="btnClickHandler">点我呀!</button>
<div id="box" v-on:mouseenter="divMouseEnterHandler"></div>
<!-- v-on:事件名称="事件处理函数的名称"   事件处理函数是保存在methods属性中! -->

<!--事件注册的简写形式:-->
<!-- @事件名称="事件处理函数的名称" -->
<button @click="btnClickHandler">点我呀!</button>
<div id="box" @mouseenter="divMouseEnterHandler"></div>
<!-- 事件注册的时候,如果要给事件处理函数传递参数,那么我们直接给函数名称后面加上小括号,将参数放进去即可! -->
<button @click="btnClickHandler(100)">点我呀!</button>

<!--还可以使用箭头函数的写法-->
<!-- e.target对应的就是当前的文本框 -->
<input type="text" :value="name" @input="e => name = e.target.value">

调用的事件处理函数需要定义在Vue实例的methods中

const vm = new Vue({
    el: "#app",
    methods: {
        btnClickHandler(arg){
            // alert("点你咋地!!")
            alert(arg);
        },
        divMouseEnterHandler(){
            console.log("我进来了")
        }
    }
})

事件对象

  • 如果在注册事件的时候,直接赋值的是函数的名字,不带小括号,那么vue会自动将事件对象传递给这个事件处理函数

    <input type="text" @keyup="keyupHandler">
    <!-- 可以如下调用事件对象,直接通过形参就可以使用了 -->
    const vm = new Vue({
    	el: "#app",
    	methods: {
    		keyupHandler(e){
    			console.log(e)
    		}
    	}
    })
    
  • 如果在注册时间的时候,使用的是带有小括号的形式,则要获取事件对象,需要手动的传递参数$event

    <input type="text" @keyup="keyupHandler($event)"> 
    

事件修饰符

<!-- 
	使用方式 
	@事件名称.修饰符名称="事件处理函数"
-->
<div class="parent" @click="parentClickHandler">
    <div class="child" @click.stop="childClickHandler"></div>
</div>

常用的事件修饰符

  • .stop - 调用 event.stopPropagation()

  • .prevent - 调用 event.preventDefault()

  • .capture - 添加事件侦听器时使用 capture 模式。

  • .self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。

  • .once - 只触发一次回调。

    事件修饰符是可以连写的

    使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用 v-on:click.prevent.self 会阻止所有的点击,而 v-on:click.self.prevent 只会阻止对元素自身的点击。
    

按键修饰符

在监听键盘事件时,我们经常需要检查详细的按键。Vue 允许为 v-on 在监听键盘事件时添加按键修饰符

<!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` -->
<input v-on:keyup.enter="submit">

为了在必要的情况下支持旧浏览器,Vue 提供了绝大多数常用的按键码的别名:

  • .enter
  • .tab
  • .delete (捕获“删除”和“退格”键)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

还可以通过全局 config.keyCodes 对象自定义按键修饰符别名

// 可以使用 `v-on:keyup.f1`
Vue.config.keyCodes.f1 = 112
v-model

在表单控件或者组件上创建双向绑定,你可以用 v-model 指令在表单 <input><textarea><select> 元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素

<!-- 当修改了input框中的数据,响应的Vue实例data中的对应数据也会修改 -->
<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>

<input type="checkbox" id="checkbox" v-model="checked">

注:在文本区域插值 (<textarea>{{text}}</textarea>) 并不会生效,应用 v-model 来代替。

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

  • text 和 textarea 元素使用 value 属性和 input 事件;
  • checkbox 和 radio 使用 checked 属性和 change 事件;
  • select 字段将 value 作为 prop 并将 change 作为事件。
v-pre指令

跳过这个元素和它的子元素的编译过程。可以用来显示原始 Mustache 标签。跳过大量没有指令的节点会加快编译。

<!-- 这样使用,则div及子元素都不会经过Vue的编译 -->
<!-- 可以提升性能-->
<div v-pre>
    <p>111</p>
    <p>111</p>
    <p>111</p>
</div>
v-once指令

只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能

<!-- 都只会在第一次渲染的时候赋值,改变了值后,界面不会重新渲染-->
<!-- 单个元素 -->
<span v-once>This will never change: {{msg}}</span>
<!-- 有子元素 -->
<div v-once>
  <h1>comment</h1>
  <p>{{msg}}</p>
</div>

Vue与ajax

  1. 用axios请求数据(推荐使用)

    Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。

    ​ 使用方式

    axios.post('/user', {
        firstName: 'Fred',
        lastName: 'Flintstone'
    })
        .then( (response)=> {
        console.log(response);
    })
        .catch( (error)=> {
        console.log(error);
    });
    
    axios.get("/user").then((response)=>{}.catch(err => throw err)
    
    axios.请求方式(url [,{参数}].then(response=>{}).catch(err=>{throw err})
    

    ​ axios 简写方式

    axios({
      method: 'post',
      url: '/user/12345',
      data: {
        firstName: 'Fred',
        lastName: 'Flintstone'
      }
    }).then(response => {
        if(response.status == 200){
            console.log(response.data);
        }
    })
    

    注意:在then的回调函数中尽量使用箭头函数,因为如果使用function的话,在函数里使用this指向的时候,这个this指向的是window对象,而我们一般在获取的时候希望这个this是指向Vue的实例的,这样才可以在这个实例上添加数据

  2. 用vue-resource请求数据

    返回的也是一个promise对象

    使用方式

    // 可以直接写在Vue实例的methods对象中
    getInfo() { // get 方式获取数据
      this.$http.get('http://127.0.0.1:8899/api/getlunbo').then(res => {
        console.log(res.body);
      })
    }
    
    postInfo() {
      var url = 'http://127.0.0.1:8899/api/post';
      // post 方法接收三个参数:
      // 参数1: 要请求的URL地址
      // 参数2: 要发送的数据对象
      // 参数3: 指定post提交的编码类型为 application/x-www-form-urlencoded
      this.$http.post(url, { name: 'zs' }, { emulateJSON: true }).then(res => {
        console.log(res.body);
      });
    }
    
    jsonpInfo() { // JSONP形式从服务器获取数据
      var url = 'http://127.0.0.1:8899/api/jsonp';
      this.$http.jsonp(url).then(res => {
        console.log(res.body);
      });
    }
    
  3. RESTful 风格

接口的风格

​ 一个URL地址就对应一个资源,对于资源不同的操作用请求方式来区分

传统接口的体现
http://xxxx.com/getallstudent
http://xxxx.com/addstudent
http://xxxx.com/deletestudent
http://xxxx.com/updatestudent

RESTFul 风格
http://xxxx.com/students  get方式
http://xxxx.com/students/id get方式
http://xxxx.com/students/id  delete方式
http://xxxx.com/studetns/id  patch方式

Vue扩展

  1. 响应式数据

    <div id="app">
        <p>
            我叫{{p.name}}
            <br>
            我有辆{{p.car}}
            <br>
            我今年才{{p.age}}
        </p>
    
        <button @click="btnAddAge">设置年龄</button>
    </div>
    
    const vm = new Vue({
        el: "#app",
        data: {
            p: {
                name: "zs",
                car: "玛莎拉蒂"
            }
        },
        methods: {
            btnAddAge(){
                // 给data中的对象动态新增的属性,不能够有响应式的效果,也就是说不能触发视图更新
                // 如果想要有响应式效果
                // 1. 就需要提前,在对象中先把属性声明好 在hcc中一开始就添加好age属性,哪怕不给值
                // this.p.age = 18;
                // 2. 如果确实需要动态的给p对象添加age属性,那么我们可以用到vue中提供的$set方法 
                // 这个方法,可以动态的给数据添加响应式的属性!
                // this.$set(this.p, "age", 18);
                // Vue.set(vm.p, "age", 18)  // 这两个方法是一样的
                
                // 数组通过索引直接修改索引对应的内容,是无法实现响应式的效果
                // this.students[1] = {id: 2, name: "ls"};
                // 需要用set来设置
                // this.$set(this.students, "1", {id: 2, name: "ls"})
            }
        }
    });
    

    ​ 什么时候用$set??

    ​ 当给对象动态添加属性的时候,需要用$set

    ​ 当想要通过数组的下表给元素赋值的时候,需要用$set

  • 异步数据更新

    Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更

如果你想基于更新后的 DOM 状态来做点什么,可以在数据变化之后立即使用 Vue.nextTick(callback)这样回调函数将在 DOM 更新完成后被调用

<div id="example">{{message}}</div>
var vm = new Vue({
  el: '#example',
  data: {
    message: '123'
  }
})

vm.message = 'new message' // 更改数据
vm.$el.textContent === 'new message' // false
Vue.nextTick(function () {
  vm.$el.textContent === 'new message' // true
})
// 也可以使用 vm.$nextTick
  • 数据在vue实例上

    我们是将数据放在参数对象中的data属性中传递给Vue构造函数的,Vue构造函数在接收到这个参数后

  1. 会读取data属性中所有的数据,通过Object.defineProperty方法,将这些数据全部加到vue实例上
    1. 这样做,可以让属性有了set和get方法,可以实现双向绑定等等功能
    2. 这样做,可以让程序员直接通过this来访问数据,方便使用
  2. Vue还会读取所有methods中的函数,把所有的函数,全部加给vue实例(可以通过this来访问这些函数)
Logo

前往低代码交流专区

更多推荐