首页 > 技术文章 > vue基础之常用方法

qianzhengkai 2020-05-19 08:57 原文

ES6语法补充

块级作用域:

作用域:变量在什么范围内是可以使用的

没有块级作用域导致的问题:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<div id="app">
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<button>按钮5</button>
<button>按钮6</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
<script>
  var btns = document.getElementsByTagName('button');
  for (var i=0;i<btns.length;i++){
    btns[i].addEventListener('click',function () {
      console.log('第'+ i + '个按钮被点击');
    })
  }

</script>
</body>
</html>

![image-20200225233409318](/Users/qzk/Library/Application Support/typora-user-images/image-20200225233409318.png)

  • 上面出现的问题是var没有块级作用域,导致i被for循环的时候更改。
  • 解决办法之1:闭包函数,因为函数是有块级作用域的。
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<div id="app">
  <button>按钮1</button>
  <button>按钮2</button>
  <button>按钮3</button>
  <button>按钮4</button>
  <button>按钮5</button>
  <button>按钮6</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
<script>
  // es5之前,因为if for都是没有块级作用域的,因此在很多时候,
  // 我们要借助function的块级作用域来解决应用作用域外面变量的问题

  // var btns = document.getElementsByTagName('button');
  // for (var i = 0; i < btns.length; i++) {
  //   btns[i].addEventListener('click', function () {
  //     console.log('第' + i + '个按钮被点击');
  //   })
  // }
  // es6中通过let来声明变量的时候,就可以很好的解决块级作用域的问题
  const btns = document.getElementsByTagName('button');
  for (let i = 0; i < btns.length; i++) {
    btns[i].addEventListener('click', function () {
      console.log('第' + i + '个按钮被点击');
    })
  }

</script>
</body>
</html>

![image-20200225234704835](/Users/qzk/Library/Application Support/typora-user-images/image-20200225234704835.png)

const 的使用和注意点

  • 一旦给const修饰的标识符被赋值之后,不能修改
const name = 'qzk';
name = 'asdaf';
// 不能修改
  • 在使用const定时标识符的时候,必须进行赋值:
// 错误示范
const name
  • 常量的含义是:是指向的对象不能修改,但是可以改变对象内部的属性
const obj_str = 'qzk';
obj_str = 'kobe';

![image-20200226232325354](/Users/qzk/Library/Application Support/typora-user-images/image-20200226232325354.png)

const obj = {
    name:'qzk',
    age:18,
    height:1.88
  };
  console.log(obj);

  obj.age=27;
  obj.name ='kobe';
  obj.height = 1.89;

  console.log(obj)

![image-20200226232534800](/Users/qzk/Library/Application Support/typora-user-images/image-20200226232534800.png)

对象的增强写法

属性的增强写法

const name = 'qzk';
  const age = 18;
  // es5写法
  const obj = {
    name:name,
    age:age
  }
  console.log(obj)
  // es6的增强语法写法
  const objES6 = {
    name,
    age
  }
  console.log(objES6)

![image-20200226233605929](/Users/qzk/Library/Application Support/typora-user-images/image-20200226233605929.png)

函数的增强写法

// 函数的增强语法
  // es5写法,没有增强语法
  const func = {
    eat:function () {
      console.log('eat')
    },
    running:function () {
      console.log('running')
    }
  }
  const funcES6 = {
    running(){
      console.log('running')
    },
    eat(){
      console.log('eat')
    },
  }

————————————————————————————————————————————————————————————————————————

创建vue实例传入的options

el:

  • 类型:string | HTMLElement(字符串或者 html)
  • 作用:决定之后vue 实例会管理哪一个DOM

data

  • 类型: Object | Function(组件中data必须是一个函数)
  • 作用:Vue 实例对应的数据对象

methods

  • 类型:{ [key:string] : Function }

  • 作用:定义属于Vue的一些方法,可以在其他地方调用,也可以在指令中使用

ps:

方法与函数的区别:通俗的说在 类里面的是方法,单独写的不在类里面的是函数

vue的生命周期(钩子函数)-->hook(callHook)

生命周期:事物从诞生到消亡的整个过程

vue的生命周期:创建出Vue对象到Vue对象的消亡。

生命周期函数:

参考链接:

https://blog.csdn.net/zjhzjh893/article/details/83691155

https://cn.vuejs.org/v2/guide/instance.html#%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E5%9B%BE%E7%A4%BA

绿色部分:vue源码内部执行的操作

红色部分:我们可以写的钩子函数

lifecycle

示例代码:

<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <h2>计数器</h2>
    <h1>{{counter}}</h1>
    <button v-on:click="add">+</button>
    <button v-on:click="sub">-</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
<script>
    // 语法糖:简写的意思
    // proxy
    const obj = {
        counter: 0,
        message: 'abc'
    }
    const app = new Vue({
        el: '#app',
        data: {
            counter: 0,
        },
        methods: {
            add: function () {
                console.log('add,+1');
                this.counter++
            },
            sub: function () {
                console.log('sub,-1');
                this.counter--
            }

        }

    })
</script>
</body>
</html>

vue的模版语法

插值操作

如何将data中的文本数据,插入到html中呢?

  • Mustache语法(也就是双大括号):响应式的
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <h1>{{body}}</h1>
    <h2>{{message}}</h2>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            message: '你好',
            body: 'qzk'
        }
    })
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <h2>计数器</h2>
<!--    v-once 指令,指定当 {{ }} 内的变量的值发生改变的时候,变量所展示的还是原来的值-->
    <h1 v-once>{{message}}</h1>
    <h1 >{{message}}</h1>
    <h1 >{{message}},你好啊</h1>
<!--    v-text='变量名',在html标签中渲染变量,并且会覆盖原标签内的文本-->
    <h1 v-text="message"></h1>
    <h1 v-text="message">你好啊</h1>
<!--    v-htm='url变量名',在html标签中渲染a标签-->
    <h1 v-html="url"></h1>
    <h1>url</h1>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
<script>
    // 语法糖:简写的意思
    // proxy
    const obj = {
        counter: 0,
        message: 'abc'
    }
    const app = new Vue({
        el: '#app',
        data: {
            counter: 0,
            message:'123',
            url:'<a href="https://www.baidu.com">百度一下</a>'
        },
        methods: {
            add: function () {
                console.log('add,+1');
                this.counter++
            },
            sub: function () {
                console.log('sub,-1');
                this.counter--
            }

        }

    })
</script>
</body>
</html>

指令之v-pre:

V-pre 用于跳过这个元素和他的字元素的编译过程,用于显示原本的Mustache语法


指令之v-cloak:

在某些情况下,我们浏览器可能会直接显示出来未编译的Mystache标签

因此,v-cloak就是防止改现象发生的指令。

下述代码,执行过程中设置了一秒的延迟:

<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <h2>{{counter}}</h2>
  	<h2 v-cloak>
      {{counter}}
  </h2>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
<script>
    // 语法糖:简写的意思
    // proxy
    const obj = {
        counter: 0,
        message: 'abc'
    }
    setTimeout(function () {
        const app = new Vue({
            el: '#app',
            data: {
                counter: 0,
            },
            methods: {
                add: function () {
                    console.log('add,+1');
                    this.counter++
                },
                sub: function () {
                    console.log('sub,-1');
                    this.counter--
                }

            }

        })
    },1000)

</script>
</body>
</html>

v-bind介绍

前面我们学习的指令主要作用是将值插入到我们的模版内容中,但是,除了内容需要动态来决定外,某些属性我们也希望可以动态来绑定。

比如:

  • 动态绑定a元素的href
  • 比如动态绑定img元素的src属性

这个时候,我们就可以使用 v-bind指令:

  • 作用:动态绑定属性
  • 缩写::
  • 预期:any(with arguement | Object(without arguement))
  • 参数:attrOrProp(optional)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <!--    该方式不可取,因为mastache语法只能添加在文本中,不可在属性中使用-->
    <img src="{{imgURL}}" alt="">
    <!--    正确做法,适应v-bind: 这样 src属性中 imgURL会被看作变量,回去 vue实例中去找我们的imgurl属性-->
    <img v-bind:src="imgURL" alt="">
    <!--    缩写形式-->
    <img :src="imgURL" alt="">

</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            imgURL: 'http://uploads.5068.com/allimg/1802/78-1P22QAK3-51.jpg'
        }
    })
</script>
</body>
</html>


效果如图:

![image-20200223194903180](/Users/qzk/Library/Application Support/typora-user-images/image-20200223194903180.png)

v-bind绑定对象class(对象语法与数组绑定)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

</head>
<body>
<div id="app">
    <!--    对象语法 -->
    <h2 :class="{active:isActive,line:isLine}">{{message}}</h2>
    <!--    对象语法加函数-->
    <h2 :class="GetClass()">{{message}}</h2>
    <!--    数组语法-->
    <!--    ['',''] 加单引号当字符串去解析-->
    <h2 :class="['active','line']">{{message}}</h2>
    <!--    不加单引号,当变量去解析-->
    <h2 :class="[isActive,isLine]">{{message}}</h2>
    <h2 :class="GetListClass()">{{message}}</h2>
    <button v-on:click="btnClick">点击</button>

</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            message: 'qzk',
            isActive: true,
            isLine: false,
            imgURL: 'http://uploads.5068.com/allimg/1802/78-1P22QAK3-51.jpg',
            ahref: 'https://www.baidu.com'
        },
        methods: {
            btnClick: function () {
                alert(this.isActive);
                this.isActive = !this.isActive
            },
            GetClass: function () {
                return {active: this.isActive, line: this.isLine}
            },
            GetListClass: function () {
                return [this.isActive, this.isLine]
            }
        }
    })
</script>
</body>
</html>

vue计算属性的基本使用(computed)

<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <h2>{{firstName + ' ' + lastName}}</h2>
    <h2>{{FullName}}</h2>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
<script>
    const app = new Vue({
        el:'#app',
        data:{
            firstName:'qzk',
            lastName:'test'
        },
        // 计算属性
        computed:{
            /**
             * @return {string}
             */
            // 将data 计算称 FullName 在html中返回
            FullName:function () {
                return this.firstName + ' ' + this.lastName
            }
        }
    })

</script>
</body>
</html>

<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <h2>总价:{{totalPrice}}</h2>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            books: [
                {id: 100, name: '深入理解计算机原理0', price: 100},
                {id: 101, name: '深入理解计算机原理1', price: 100},
                {id: 102, name: '深入理解计算机原理2', price: 100},
                {id: 103, name: '深入理解计算机原理3', price: 100}
            ]
        },
        // 计算属性
        computed: {
            /**
             * @return {string}
             */
            totalPrice: function () {
                let result = 0;
                for (let i = 0; i < this.books.length; i++) {
                    result += this.books[i].price

                }
                // es6语法实现
                for (let i in this.books){

                }
                // es6语法2
                for (book in this.books){
                    
                }
                return result;


            }
        }
    })

</script>
</body>
</html>

计算属性(在mustache语法中不需要加()),有些时候在 computed中做属性的操作,更方便。

计算属性为什么不是按照函数方式执行而是按照data方式执行--getter和setter

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <div>{{fullName}}</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
<script>
    let app;
    app = new Vue({
        el: '#app',
        data: {
            firstName:'qian',
            lastName:'zhengkai'
        },
        computed:{
            // fullName: function () {
            //     return this.firstName + ' ' + this.lastName
            // },
            fullName:{
                // 计算属性一般不建议使用set方法
                set:function (newName) {
                    // 一般用于设置data中变量的属性,且需要传入参数
                    const name=newName.split(' ');
                    this.firstName = name[0];
                    this.lastName = name[1];
                },
                get:function () {
                    // 如果 这里 fullName return的是 abc 则返回abc
                    // return 'abc'
                    return this.firstName + ' ' + this.lastName
                }
            }
        }
    });

</script>

</body>
</html>

![image-20200225230342617](/Users/qzk/Library/Application Support/typora-user-images/image-20200225230342617.png)

计算属性的缓存(计算属性和methods的对比)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<div id="app">
<!--  直接拼接的方式 此方法不推荐使用-->
  <h2>{{firstName}} {{lastName}}</h2>
  <h2>{{fullName()}}</h2>
  <h2>{{fullName()}}</h2>
  <h2>{{fullName()}}</h2>
  <h2>{{fullName()}}</h2>
  <h2>{{fullName()}}</h2>
  <h2>{{fullName1}}</h2>
  <h2>{{fullName1}}</h2>
  <h2>{{fullName1}}</h2>
  <h2>{{fullName1}}</h2>
  <h2>{{fullName1}}</h2>

</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
<script>
    let app;
    app = new Vue({
      el: '#app',
      data: {
        firstName:'qian',
        lastName:'ZHENGKAI',
      },
      computed:{
        fullName1: function () {
          console.log('full_computed');
          return this.firstName + ' ' + this.lastName
        }
      },

      methods:{
        fullName: function () {
          console.log('full_method');
          return this.firstName + ' ' + this.lastName
        }
    }
    });

</script>
</body>
</html>

![image-20200225231703471](/Users/qzk/Library/Application Support/typora-user-images/image-20200225231703471.png)

v-on使用

<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<div id="app">
  <h1>方法一:</h1>
  <h2>{{counter1}}</h2>
  <button v-on:click="counter1++">+</button>
  <button v-on:click="counter1--">-</button>
  <h1>方法二:</h1>
  <h2>{{counter2}}</h2>
  <button v-on:click="increment">+</button>
  <button v-on:click="increment">-</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
<script>
  let app;
  app = new Vue({
    el: '#app',
    data: {
      counter1: 0,
      counter2: 0
    },
    methods: {
      // ES6增强写法
      increment() {
        this.counter2++
      },
      // ES6 增强写法
      decrement() {
        this.counter2--
      }
    }
  });

</script>
</body>
</html>

![image-20200309005857554](/Users/qzk/Library/Application Support/typora-user-images/image-20200309005857554.png)

v-on语法糖是 @ ,例如 v-on:click. = @click

<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<div id="app">
  <h1>方法一:</h1>
  <h2>{{counter1}}</h2>
  <!--@ 是 v-on 语法糖-->
  <button @click="counter1++">+</button>
  <button @click="counter1--">-</button>
  <h1>方法二:</h1>
  <h2>{{counter2}}</h2>
  <button @click="increment">+</button>
  <button @click="decrement">-</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
<script>
  let app;
  app = new Vue({
    el: '#app',
    data: {
      counter1: 0,
      counter2: 0
    },
    methods: {
      // ES6增强写法
      increment() {
        this.counter2++
      },
      // ES6 增强写法
      decrement() {
        this.counter2--
      }
    }
  });

</script>
</body>
</html>

v-on参数问题(传递参数)

当通过methods中定义的方法,以供@click调用的时候,需要注意参数问题

  • 情况一:如果该方法不需要额外参数,那么方法后的()可以不添加
    • 但是注意:如果方法本身中有一个参数,那么会默认将原省时间event参数传递进去
  • 情况二:如果需要同事传入某个参数,同时需要event时,可以通过$event传入事件
<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<div id="app">
  <!--  <h1>方法一:</h1>-->
  <!--  <h2>{{counter1}}</h2>-->
  <!-- 演示 @click 不传递参数-->
  <button @click='btn1Click'>按钮1</button>
  <button @click='btn1Click()'>按钮2</button>
  <!-- 在事件定义时,写函数时省略小括号,但是方法本身时需要一个参数的-->
  <button @click='btn3Click(123)'>按钮3</button>
  <!--如果我们的方法在定义时需要传入参数,但是没有传入则默认值为undefined-->
  <button @click='btn3Click()'>按钮3</button>
  <!--如果不加括号,则浏览器会默认将event事件对象传入到函数中,这里表现为 MouseEvent-->
  <button @click='btn3Click'>按钮3</button>
  <!--  方法定义时同时需要event又需要其他参数的情况-->
    <!-- 在调用方法时,如何手动的获取d到浏览器的eventd对象:$event -->
  <button @click='btn4Click(abc,$event)'>按钮4</button>
  <!--   -->
<!--  <button @click='btn5Click'>按钮5</button>-->

</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
<script>
  let app;
  app = new Vue({
    el: '#app',
    data: {
      counter1: 0,
      counter2: 0,
      abc:123
    },
    methods: {
      // ES6增强写法
      btn1Click() {
        console.log('点击')
      },
      btn3Click(abc) {
        console.log('----->', abc)
      },
      btn4Click(abc, event) {
        console.log('++++>', abc, event)
      }

    }
  });

</script>
</body>
</html>

![image-20200309012332654](/Users/qzk/Library/Application Support/typora-user-images/image-20200309012332654.png)

![image-20200309013207410](/Users/qzk/Library/Application Support/typora-user-images/image-20200309013207410.png)

v-on修饰符

在某些情况下,我们拿到event的魔都可能是进行一些事件处理,vue提供了修饰符来帮助我们方便的处理事件:

  • stop---调用 event.stopPropagation()
  • .prevent ---- 调用 event.preventDefault()
  • .{keyCode|KeyAlias} - 只当前时间是从特定键出发时才触发
  • .native ---监听组件根元素的原生事件
  • .once --- 只出发一次回调
<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<!--.stop  来阻止冒泡事件-->
<div id="app">
  <div @click="divClick">
    <h3>asdf</h3>
    <button @click.stop='submit1Click'>按钮</button>
  </div>

  <br>

  <div>
    <!--    该方法form提交一次,但是submit2click 方法也执行了, 其中 input点击的默认事件是 提交form-->
    <h2>form提交 submit</h2>
    <form action="baidu">
      <input type="submit" value="提交1" @click='submit2Click'>
    </form>
    <br>
    <!--  我们可以通过 .prevent 来阻止默认事件  -->
    <h2>通过method click事件操作form</h2>
    <form action="baidu">
      <input type="submit" value="提交2" @click.prevent='submit3Click'>
    </form>
  </div>

</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
<script>
  let app;
  app = new Vue({
    el: '#app',
    data: {
      counter1: 0,
      counter2: 0
    },
    methods: {
      divClick() {
        console.log('divclick')
      },
      submit1Click() {
        console.log('提交1')
      },
      submit2Click() {
        console.log('提交2')
      },
      submit3Click() {
        console.log('提交3')
      }
    }
  });

</script>
</body>
</html>

![image-20200309015551554](/Users/qzk/Library/Application Support/typora-user-images/image-20200309015551554.png)

v-if用法

<!--基本使用-->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<div id="app">
<!--  isShow为true的时候显示-->
  <h2 v-if="isShow">{{message}}</h2>
<!--  isShow 为false的时候显示-->
  <h2 v-else>isshow为false的时候显示我</h2>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
<script>
  let app;
  app = new Vue({
    el: '#app',
    data: {
      message: 'hello',
      isShow: true
    }
  });

</script>
</body>
</html>

![image-20200309231810077](/Users/qzk/Library/Application Support/typora-user-images/image-20200309231810077.png)

V-else-if

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<div id="app">
<!--  isShow为true的时候显示-->
  <h2 v-if="score>=85">优秀</h2>
<!--  这里使用 v-else-if 的时候 不需要再写 <85 ,因为上面条件不满足的时候才会执行下面-->
  <h2 v-else-if="score>=75">还可以</h2>
  <h2 v-else-if="score>=60">及格</h2>
  <h2 v-if="score<60">不及格</h2>
<!--  isShow 为false的时候显示-->

<!--  也可以利用计算属性来实现上述的代码-->
  <h1>{{result}}</h1>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
<script>
  let app;
  app = new Vue({
    el: '#app',
    data: {
      score:99
    },
    computed:{
      result(){
        let showMessage = '';
        if(this.score >=85){
          showMessage = '优秀'
        }else if (this.score >=75){
          showMessage = '还可以'
        }else if (this.score>=60){
          showMessage = '及格'
        }else{
          showMessage = '不及格'
        }
        return showMessage
      }
    }
  });

</script>
</body>
</html>

![image-20200309232828788](/Users/qzk/Library/Application Support/typora-user-images/image-20200309232828788.png)

用户登陆方式选择的小案例

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<div id="app">
  <div v-if="isUserLogin">
    <span>
      <label for="username">用户名登陆</label>
      <input type="text" id="username" placeholder="请输入用户名">
    </span>

  </div>
  <div v-else>
    <span>
      <label for="email">用户邮箱登陆</label>
      <input type="text" id='email' placeholder="请输入邮箱" >
    </span>

  </div>
  <button @click="changeLogin">更改登陆方法</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
<script>
    let app;
    app = new Vue({
        el: '#app',
        data: {
          isUserLogin:true
        },
      methods:{
          changeLogin(){
            this.isUserLogin = !this.isUserLogin;
            console.log(this.isUserLogin)
          }
      }
    });



</script>
</body>
</html>

![image-20200309234523710](/Users/qzk/Library/Application Support/typora-user-images/image-20200309234523710.png)

![image-20200309234541999](/Users/qzk/Library/Application Support/typora-user-images/image-20200309234541999.png)

注意:

  • vue底层为了性能优化,有搞一个虚拟dom放在内存中,这样尽可能的复用已存在的可服用的dom
  • 在上面的案例中,vue内部会发现原来的input元素不在使用,直接做else中的input来使用了

解决方法:

  • 如果我们不希望vue出现类似的重复利用的问题,可以给对应的input添加key
  • 并且保证key的不同

实现示例:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<div id="app">
  <div v-if="isUserLogin">
    <span>
      <label for="username">用户名登陆</label>
      <input type="text" id="username" placeholder="请输入用户名" key="username">
    </span>

  </div>
  <div v-else>
    <span>
      <label for="email">用户邮箱登陆</label>
      <input type="text" id='email' placeholder="请输入邮箱" key="email">
    </span>

  </div>
  <button @click="changeLogin">更改登陆方法</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
<script>
    let app;
    app = new Vue({
        el: '#app',
        data: {
          isUserLogin:true
        },
      methods:{
          changeLogin(){
            this.isUserLogin = !this.isUserLogin;
            console.log(this.isUserLogin)
          }
      }
    });



</script>
</body>
</html>

v-show

​ v-show和v-if非常相似,也是用来决定一个元素是否渲染。

v-show 和 v-if 比较:

  • v-if 当条件为false时,压根不会有对应的元素在dom中
  • v-show 当条件为false时,仅仅是对元素的display属性设置为none而已

开发中如何选择:

  • 当需要在显示与盈仓之间切换很频繁时,使用v-show
  • 当只有一次切换时,使用v-if

示例:略

v-for使用:

  • V-for 遍历数组:
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<div id="app">
  <ul>
    <li v-for="item in names">{{item}}</li>
  </ul>
  <!--index 为 元素的索引-->
  <ul>
    <li v-for="(index,item) in names">
    {{index}} ----> {{item}}
    </li>
  </ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
<script>
    let app;
    app = new Vue({
        el: '#app',
        data: {
          names:['q','z','k','1']
        }
    });

</script>

</body>
</html>

V-for 遍历对象

![image-20200312222701846](/Users/qzk/Library/Application Support/typora-user-images/image-20200312222701846.png)

上图是v-for获取对象(字典的相关数据)

示例代码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<div id="app">
<!--  1.在遍历的过程中如果只获取一个值,获取到的时value-->
<ul>
  <li v-for="item in info">{{item}}</li>
</ul>
<!--  2.获取 key和value 用 (key,value)-->
  <ul>
    <li v-for="(key,value) in info">{{key}},{{value}}</li>
  </ul>
<!--  3.获取key和value和索引index,用 (key,value,index)-->
  <ul>
    <li v-for="(key,value,index) in info">{{index}}+{{key}}+{{value}}</li>
  </ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
<script>
    let app;
    app = new Vue({
        el: '#app',
        data: {
          info:{
            name:'qzk',
            age:18,
            height:180
          }
        }
    });

</script>

</body>
</html>

组件的key属性

官方推荐我们在使用v-for时,给对应的元素或组件添加上一个:key属性

  • 为什么需要加上key属性呢?
    • 这个其实和vue的虚拟DOM的Diff算法有关
  • 当某一层油很多相同节点的时候,也就是列表节点时,我们希望插入一个新的节点
    • 我们希望可以再b和c之间插入f, Diff算法默认执行起来是这样的
    • 即把C更新成F ,D更新成C 。。。。
  • 所以我们用key 来给每个节点做一个唯一标识
    • diff 算法就可以正确的识别出此节点
    • 找到正确的位置插入新的节点
  • 所以:key的作用主要是为了更高效的更新虚拟DOM

表单绑定之v-model(常用)

  • 表单控件在实际开发中是非常常见的,特别是对用户信息的提交。需要大量的表单。
  • Vue 中使用 v-model 指令来实现变淡元素数据的双向绑定。
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<div id="app">
  <!--通过v-model 绑定表单元素 ,这样如果 input输入的信息改变的时候 data中的message 也会随之改变。两者之间建立了绑定关系-->
  <input type="text" v-model="message">
  {{ message }}
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      message:'你好'
    }
  })
</script>

</body>
</html>

双向绑定的本质:实际上相当于两个指令的集合

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<div id="app">
  <label>
<!--    <input type="text" v-model="message">-->
    <input type="text" :value="message" @input="message = $event.target.value">
  </label>
  {{ message }}
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      message:'你好'
    }
  })
</script>

</body>
</html>

V-model绑定radio

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<div id="app">
  <label for="male">
    <input type="radio" id="male" name="sex" v-model="sex" value="男">男
  </label>
  <label for="female">
    <input type="radio" id="female" name="sex" v-model="sex" value="女">女
  </label>
  <h2>您选择的性别是:{{sex}}</h2>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      "sex":''
    }
  })
</script>

</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<div id="app">
<!--1. 修饰符:lazy(懒加载)   使用.lazy修饰符后,双向绑定的标签会在敲击回车键或失去焦点后进行实时绑定,这样可以降低加载的次数提升性能-->
  <label for="test1">
    <input type="text" id="test1" v-model.lazy="msg">
  </label>
  <h2>{{msg}}</h2>
<!--  2. 修饰符:trim 删除input左右两边的空格-->
  <label for="test2">
    <input type="text" id="test2" v-model.trim="name">
  </label>
  <h2>{{name}}</h2>
<!--  3。 修饰符:number 使用这个时候默认输入的就是num类型不需要在进行数字类型转换-->
  <label for="test3">
    <input type="number" id="test3" v-model.number="age">
  </label>
  <h2>{{age}}-{{typeof age}}</h2>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      "msg":'你好',
      "name":'',
      "age":''
    }
  })
</script>
</body>
</html>

推荐阅读