Vue基础

Vue学习

  • 教程:Vue官网打广告那个教程真是不敢恭维
  • 菜鸟教程

安装

作为一款构建前端用户界面的JavaScript框架,我们只需要新建.html文件并引入Vue.js文件即可

  • Vue官网
  • 编辑器使用Sublime或者其他
  • 其他的安装方法和应用构建参看教程

基本操作

  • 创建一个Vue实例,并绑定页面元素

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    <body>
    <!-- 将来 new 的Vue实例,会控制这个元素中的所有内容 -->
    <!-- {{var}} 叫做插值表达式,输出data属性中的数据 -->
    <div id="app">
    <p>{{msg}}</p>
    <p>{{msg2}}</p>
    <p>{{msg3}}</p>
    <p>{{msg4}}</p>
    </div>

    <!-- 也可以通过vm.msg直接访问data属性中的数据 -->
    <script>
    // 创建一个Vue的实例
    // 当我们导入包之后,在浏览器的内存中,就多了一个 Vue 构造函数
    var vm = new Vue({// el、data等可以称之为属性
    el: '#app', // 指明要控制页面上的id为app的区域
    data: { // 存放 el 中要用到的数据
    msg: 'Hello Vue!', // 通过 Vue 提供的指令,很方便的就能把数据渲染到页面上,不需要手动操作DOM元素了
    msg2: 'Hello Vue2!',// 前端的Vue之类的框架,不提倡我们去手动操作DOM元素
    msg3: 'Hello Vue3!',
    msg4: 'Hello Vue4!'
    }
    })
    </script>
    </body>
  • 代码可以在谷歌浏览器打开,使用自带的开发者查看并调试

  • v-cloak可以解决在网速慢的情况下,插值表达式在浏览器中闪烁的问题

    1
    <p v-cloak>{{msg}}</p>
    • 使用v-text同样可以解决闪烁的问题,区别在哪?

      1
      2
      3
      4
      <div id='app'>
      <p v-cloak>从Vue对象获取数据:{{msg}}</p>
      <p v-text="msg">从Vue对象获取数据</p>
      </div>
    • 运行这段代码我们会发现下面的p标签只输出msg变量的值。即插值表达式可以把Vue传递过来的数据和前台用户自己定义的数据结合在一起,但是v-text只能显示Vue对象传递过来的数据,会替换掉节点里已有的内容

  • v-html可以解析html的标签并展示

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <!--这里不会显示标签里的内容“Vue”-->
    <div v-html="msg">Vue</div>

    <script>
    var vm = new Vue({
    el: '#app2',
    data: {
    msg: '<h1>哈哈,我是一个大大的H1, 我大,我骄傲</h1>',
    },
    })
    </script>
  • v-bind:xxx绑定Vue实例中的属性

  • v-on:xxx绑定实例中的方法methods,即事件监听指令

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    <!-- 注意: v-bind: 指令可以被简写为 冒号+要绑定的属性 -->
    <!-- v-bind 中,可以写合法的JS表达式 -->
    <!-- v-bind:title 作用是鼠标放置在按钮上时的提示文字;指定为mytitle后,还可以拼接其他字符串-->
    <!-- Vue.js 都提供了完全的 JavaScript 表达式支持 -->
    <input type="button" value="按钮" v-bind:title="mytitle + 'hello'">
    <!-- 可传参 -->
    <input type="button" value="按钮" :title="mytitle" v-on:click="show2">
    <!-- v-on: 绑定方法,可以简写为 @ -->
    <input type="button" value="按钮@" @click="show3">

    <script>
    var vm = new Vue({
    el: '#app2',
    data: {
    msg: '123',
    mytitle: '这是一个自己定义的title'
    },
    methods: { // 这个 methods属性中定义了当前Vue实例所有可用的方法
    show2: function () {
    alert('Hello')
    },
    show3(){
    alert('Hello World');
    }
    }
    })
    </script>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <div id="app">
    <!-- 可以直接操作data属性 -->
    <button v-on:click="counter += 1">增加 1</button>
    <p>这个按钮被点击了 {{ counter }} 次。</p>
    </div>

    <script>
    new Vue({
    el: '#app',
    data: {
    counter: 0
    }
    })
    </script>

事件修饰符

  • 为 v-on 提供了事件修饰符来处理 DOM 事件细节

  • .stop阻止事件冒泡

    1
    2
    3
    <div class="inner" @click="divHandler">
    <input type="button" value="戳他" @click.stop="btnHandler">
    </div>
  • .prevent阻止标签默认行为

    1
    <a href="http://www.baidu.com" @click.prevent="linkClick">有问题去百度</a>
  • .capture实现捕获触发事件的机制

    • 当元素发生冒泡时,先触发带有该修饰符的元素。若有多个该修饰符,则由外而内触发
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <!--弹出的顺序为:obj1、obj2、obj4、obj3;由于1,2有修饰符,故而先触发事件,然后就是4本身触发,最后冒泡事件。-->
    <div id="content">
    <div id="obj1" v-on:click.capture="doc">
    obj1
    <div id="obj2" v-on:click.capture="doc">
    obj2
    <div id="obj3" v-on:click="doc">
    obj3
    <div id="obj4" v-on:click="doc">
    obj4
    </div>
    </div>
    </div>
    </div>
    </div>
  • .self只有点击当前元素时候,才会触发事件处理函数

    • 可以理解为只会阻止来到自己身上的冒泡事件,不受别人影响,但.stop是通知所有冒泡事件
  • .once只触发一次事件处理函数

    1
    <a href="http://www.baidu.com" @click.prevent.once="linkClick">有问题,先去百度</a>

按键修饰符

  • 监听键盘事件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <!-- 记住所有的 keyCode 比较困难,所以 Vue 为最常用的按键提供了别名 -->
    <!-- 只有在 keyCode 是 enter 时调用 vm.submit() -->
    <input v-on:keyup.enter="submit">
    <input @keyup.enter="submit">
    //全部别名:
    .enter
    .tab
    .delete (捕获 "删除" 和 "退格" 键)
    .esc
    .space
    .up
    .down
    .left
    .right
    .ctrl
    .alt
    .shift
    .meta
  • v-showv-if的区别

    1
    2
    3
    4
    5
    <!-- 如果元素涉及到频繁的切换,最好不要使用 v-if, 而是推荐使用 v-show -->
    <!-- 如果元素可能永远也不会被显示出来被用户看到,则推荐使用 v-if -->
    <h3 v-if="flag">这是用v-if控制的元素</h3>
    <!-- 若flag=false,则样式切换为display:none,而不是消失 -->
    <h3 v-show="flag">这是用v-show控制的元素</h3>
  • v-model实现双向绑定

    • 即同时实现data属性中的数据渲染和修改
  • 自动绑定表单元素的相关标签value值,更新修改

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <div id="app">
    <!-- v-bind 只能实现数据的单向绑定 -->
    <input type="text" v-bind:value="msg" style="width:100%;">
    <!-- 可以实现 表单元素和 Model 中数据的双向数据绑定 -->
    <!-- 注意: v-model 只能运用在 表单元素中 -->
    <input type="text" style="width:100%;" v-model="msg">
    </div>

    <script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
    el: '#app',
    data: {
    msg: '大家都是好学生,爱敲代码,爱学习,爱思考,简直是完美!'
    },
    methods: {
    }
    });
    </script>
  • 通过双向数据绑定,实现表单上的应用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    <div id="app">
    <p>单个复选框:</p>
    <input type="checkbox" id="checkbox" v-model="checked">
    <!--for 属性规定 label 与哪个表单元素绑定-->
    <label for="checkbox">{{ checked }}</label>

    <p>多个复选框:</p>
    <input type="checkbox" id="baidu" value="Baidu" v-model="checkedNames">
    <label for="baidu">Baidu</label>
    <input type="checkbox" id="google" value="Google" v-model="checkedNames">
    <label for="google">Google</label>
    <input type="checkbox" id="taobao" value="Taobao" v-model="checkedNames">
    <label for="taobao">taobao</label>
    <br>
    <span>选择的值为: {{ checkedNames }}</span>
    </div>

    <script>
    new Vue({
    el: '#app',
    data: {
    checked : false,
    checkedNames: []
    }
    })
    </script>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    <div id="app">
    <select v-model="selected" name="fruit">
    <option value="">选择一个网站</option>
    <option value="www.baidu.com">Baidu</option>
    <option value="www.google.com">Google</option>
    </select>

    <div id="output">
    选择的网站是: {{selected}}
    </div>
    </div>

    <script>
    new Vue({
    el: '#app',
    data: {
    selected: ''
    }
    })
    </script>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <div id="app">
    <input type="radio" id="runoob" value="Baidu" v-model="picked">
    <label for="runoob">Baidu</label>
    <br>
    <input type="radio" id="google" value="Google" v-model="picked">
    <label for="google">Google</label>
    <br>
    <span>选中值为: {{ picked }}</span>
    </div>

    <script>
    new Vue({
    el: '#app',
    data: {
    picked : 'Runoob'
    }
    })
    </script>

样式

  • :class:style

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="./lib/vue-2.4.0.js"></script>
    <style>
    .red {
    color: red;
    }
    .thin {
    font-weight: 200;
    }
    .italic {
    font-style: italic;
    }
    .active {
    letter-spacing: 0.5em;
    }
    </style>
    </head>

    <body>
    <div id="app">
    <h1 class="red thin">这是一个很大很大的H1,大到你无法想象!!!</h1>

    <!-- 第一种使用方式,直接传递一个数组,注意: 这里的 class 需要使用 v-bind 做数据绑定 -->
    <h1 :class="['thin', 'italic']">这是一个很大很大的H1,大到你无法想象!!!</h1>

    <!-- 在数组中使用三元表达式 -->
    <h1 :class="['thin', 'italic', flag?'active':'']">这是一个很大很大的H1,大到你无法想象!!!</h1>

    <!-- 在数组中使用 对象来代替三元表达式,提高代码的可读性 -->
    <h1 :class="['thin', 'italic', {'active':flag} ]">这是一个很大很大的H1,大到你无法想象!!!</h1>

    <!-- 在为 class 使用 v-bind 绑定 对象的时候,对象的属性是类名,由于对象的属性可带引号,也可不带引号,所以这里我没写引号; 属性的值是一个标识符 -->
    <h1 :class="classObj">这是一个很大很大的H1,大到你无法想象!!!</h1>
    </div>

    <script>
    var vm = new Vue({
    el: '#app',
    data: {
    flag: true,
    classObj: { red: true, thin: true, italic: false, active: false }
    },
    methods: {}
    });
    </script>
    </body>
    </html>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <div id="app">
    <!-- 对象就是键值对的集合 -->
    <h1 :style="styleObj1">这是一个h1</h1>
    <!-- 可以使用数组-->
    <h1 :style="[ styleObj1, styleObj2 ]">这是一个h1</h1>
    </div>
    <!-- 当 v-bind:style 使用需要特定前缀的 CSS 属性时,如 transform ,Vue.js 会自动 侦测并添加相应的前 -->

    <script>
    var vm = new Vue({
    el: '#app',
    data: {
    styleObj1: { color: 'red', 'font-weight': 200 },
    styleObj2: { 'font-style': 'italic' }
    },
    methods: {}
    });
    </script>

循环

  • 循环普通数组

    1
    2
    <p v-for="item in list">{{item}}</p>
    <p v-for="(item, i) in list">索引值:{{i}} --- 元素:{{item}}</p>
  • 循环对象数组

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <div id="app">
    <p v-for="(user, i) in list">Id:{{ user.id }} --- 名字:{{ user.name }} --- 索引:{{i}}</p>
    </div>

    <script>
    var vm = new Vue({
    el: '#app',
    data: {
    list: [
    { id: 1, name: 'zs1' },
    { id: 2, name: 'zs2' },
    { id: 3, name: 'zs3' },
    { id: 4, name: 'zs4' }
    ]
    },
    methods: {}
    });
    </script>

    注:都是遍历实例data属性中的数据

  • 循环对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <div id="app">
    <!-- 注意:在遍历对象身上的键值对的时候, 除了有val key ,在第三个位置还有 一个 索引 -->
    <p v-for="(val, key, i) in user">值是: {{ val }} --- 键是: {{key}} -- 索引: {{i}}</p>
    </div>

    <script>
    var vm = new Vue({
    el: '#app',
    data: {
    user: {
    id: 1,
    name: '托尼·赵四',
    gender: '男'
    }
    },
    methods: {}
    });
    </script>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <div id="app">
    <!-- in 后面可以放普通数组,对象数组,对象,还可以放数字 -->
    <!-- 注意:如果使用 v-for 迭代数字的话,前面的 count 值从 1 开始 -->
    <p v-for="count in 10">这是第 {{ count }} 次循环</p>
    </div>

    <script>
    var vm = new Vue({
    el: '#app',
    data: {},
    methods: {}
    });
    </script>
    • 在使用for循环操作标签时,需要注意

      1
      2
      3
      4
      <!--在一些特殊情况中,如果 v-for 有问题,必须在使用 v-for 的同时,指定唯一的 字符串/数字类型 :key 值,使用v-bind绑定-->
      <p v-for="item in list" :key="item.id">
      <input type="checkbox">{{item.id}} --- {{item.name}}
      </p>

    过滤器

    • 用作一些常见的文本格式化。由”管道符”指示, 格式如下:

      1
      2
      3
      4
      5
      <!-- 在两个大括号中 -->
      {{ message | capitalize }}

      <!-- 在 v-bind 指令中 -->
      <div v-bind:id="rawId | formatId"></div>
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      <div id="app">
      {{ message | capitalize }}
      </div>

      <script>
      new Vue({
      el: '#app',
      data: {
      message: 'runoob'
      },
      filters: {
      capitalize: function (value) {
      if (!value) return ''
      value = value.toString()
      return value.charAt(0).toUpperCase() + value.slice(1)
      // 字符串第一个字母转为大写
      }
      }
      })
      </script>
    • 过滤器可以串联

      1
      {{ message | filterA | filterB }}
    • 过滤器是 JavaScript 函数,因此可以接受参数

      1
      2
      {{ message | filterA('arg1', arg2) }}
      // message 是第一个参数,'arg1' 作为第二个参数, arg2 表达式的值将被求值然后作为第三个参数

    计算属性

    • 在处理一些复杂逻辑时很有用

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      <!-- 使用computed关键字 -->
      <div id="app">
      <p>原始字符串: {{ message }}</p>
      <p>计算后反转字符串: {{ reversedMessage }}</p>
      </div>

      <script>
      var vm = new Vue({
      el: '#app',
      data: {
      message: 'Roykun!'
      },
      computed: {
      // 相当于新的属性变量
      reversedMessage: function () {
      // `this` 指向 vm 实例
      return this.message.split('').reverse().join('')
      }
      }
      })
      </script>
    • 和methods方法在效果上一样,但是computed 是基于它的依赖缓存,可以说使用 computed 性能会更好,但是会产生缓存

    • 默认的computed只有get属性,可以编写set

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      var vm = new Vue({
      el: '#app',
      data: {
      name: 'Google',
      url: 'http://www.google.com'
      },
      computed: {
      site: {
      // getter
      get: function () {
      return this.name + ' ' + this.url
      },
      // setter
      set: function (newValue) { // 接收传值
      var names = newValue.split(' ')
      this.name = names[0]
      this.url = names[names.length - 1]
      }
      }
      }
      })
      // 调用 setter, vm.name 和 vm.url 也会被对应更新
      vm.site = '菜鸟教程 http://www.baidu.com';
      document.write('name: ' + vm.name);
      document.write('<br>');
      document.write('url: ' + vm.url);

    watch监听

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <div id = "app">
    <p style = "font-size:25px;">计数器: {{ counter }}</p>
    <!-- 直接在这写表达式 -->
    <button @click = "counter++" style = "font-size:25px;">点我</button>
    </div>
    <script type = "text/javascript">
    var vm = new Vue({
    el: '#app',
    data: {
    counter: 1
    }
    });
    // $watch 是一个实例方法
    // 这个回调将在 vm.counter 改变后调用
    vm.$watch('counter', function(newVal, oldVal) {
    alert('计数器值的变化 :' + oldVal + ' 变为 ' + newVal + '!');
    });
    </script>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    <div id = "computed_props">
    千米 : <input type = "text" v-model = "kilometers">
    米 : <input type = "text" v-model = "meters">
    </div>
    <p id="info"></p>
    <script type = "text/javascript">
    var vm = new Vue({
    el: '#computed_props',
    data: {
    kilometers : 0,
    meters:0
    },
    watch : {
    kilometers:function(val) {
    this.kilometers = val;
    this.meters = this.kilometers * 1000
    },
    meters : function (val) {
    this.kilometers = val/ 1000;
    this.meters = val;
    }
    }
    });
    // $watch 是一个实例方法
    vm.$watch('kilometers', function (newValue, oldValue) {
    // 这个回调将在 vm.kilometers 改变后调用
    document.getElementById ("info").innerHTML = "修改前值为: " + oldValue + ",修改后值为: " + newValue;
    })
    </script>
------ ���Ľ���------