• Vue.js 学习笔记 一



    本文的Demo和源代码已放到GitHub,如果您觉得本篇内容不错,请点个赞,或在GitHub上加个星星!

    https://github.com/zwl-jasmine95/Vue_test

     以下所有知识都是基于vue.js 2.0版本


    一、简介

    Vue.js(读音 /vjuː/,类似于 view) 是一套构建用户界面的渐进式框架。与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计Vue 的核心库只关注视图层,它不仅易于上手,还便于与第三方库或既有项目整合。

    另一方面,当与单文件组件和 Vue 生态系统支持的库结合使用时,Vue 也完全能够为复杂的单页应用程序提供驱动。

    Vue.js是当下很火的一个JavaScript MVVM库,它是以数据驱动和组件化的思想构建的。相比于Angular.js,Vue.js提供了更加简洁、更易于理解的API,使得我们能够快速地上手并使用Vue.js。

    MVVM:

     DOM Listeners和Data Bindings两个工具,它们是实现双向绑定的关键。
    从View侧看,ViewModel中的DOM Listeners工具会帮我们监测页面上DOM元素的变化,如果有变化,则更改Model中的数据;
    从Model侧看,当我们更新Model中的数据时,Data Bindings工具会帮我们更新页面中的DOM元素。


    二、vue.js基础指令知识

    Vue.js提供了一些常用的内置指令:

    • v-if指令
    • v-show指令
    • v-else指令
    • v-for指令
    • v-bind指令
    • v-on指令

    1.声明式渲染

    Vue.js 的核心是一个允许采用简洁的模板语法来声明式的将数据渲染进 DOM。  个人感觉实现原理还是和angularJS很像的。

    我们试一下写一个简单的hello world!:

     1 <body>
     2     <div id="app">
     3         {{message}}
     4     </div>
     5 
     6     <script type="text/javascript" src="lib/js/vue.js"></script>
     7     <script type="text/javascript">
     8         /**
     9          * 采用简洁的模板语法来声明式的将数据渲染进 DOM
    10          */
    11         var app = new Vue({
    12             el:'#app',
    13             data:{
    14                 message:'Hello World!'
    15             }
    16         });
    17     </script>
    18 </body>

    可以通过app.message来查看数据值。但是在写代码的过程中需要注意很重要的两点:

    1)我们编写的js代码一定要放在body标签的最下面,不然会报错‘没有找到#app’,因为js代码放在head标签里时页面DOM结果还没加载完。

    2){{message}}这里其实相当于一个变量,可以任意命名,只要和js里对应即可。

    数据和 DOM 已经被绑定在一起,一切都是响应式的。可以通过app.message改变数据值。

    ______________  除了文本插值,我们还可以采用指令的方式绑定 DOM 元素属性,指令带有前缀 v-,以表示它们是 Vue 提供的特殊属性。

    v-bind指令可以在其名称后面带一个参数,中间放一个冒号隔开,这个参数通常是HTML元素的特性(attribute),例如:v-bind:class

    v-bind:argument="expression"
     1 <body>
     2     <div id="app-2">
     3         <span v-bind:title="message">
     4             鼠标悬停几秒钟查看此处动态绑定的提示信息!
     5         </span>
     6     </div>
     7 
     8     <script type="text/javascript" src="lib/js/vue.js"></script>
     9     <script type="text/javascript">
    10         /**
    11          * 采用简洁的模板语法来声明式的将数据渲染进 DOM
    12          */
    13         var app2 = new Vue({
    14             el: '#app-2',
    15             data: {
    16                 message: '页面加载于 ' + new Date()
    17             }
    18         })
    19     </script>
    20 </body>

    这里该指令的作用是:“将这个元素节点的 title 属性和 Vue 实例的 message 属性保持一致”。

    使用Vue的过程就是定义MVVM各个组成部分的过程的过程。

    1. 定义View
    2. 定义Model
    3. 创建一个Vue实例或"ViewModel",它用于连接View和Model

    在创建Vue实例时,需要传入一个选项对象,选项对象可以包含数据、挂载元素、方法、模生命周期钩子等等。

    在这个示例中,选项对象el属性指向View,el: '#app'表示该Vue实例将挂载到<div id="app">...</div>这个元素;data属性指向Model,data: message表示我们的Model是message对象。
    Vue.js有多种数据绑定的语法,最基础的形式是文本插值,使用一对大括号语法,在运行时{{ message }}会被数据对象的message属性替换,所以页面上会输出"Hello World!"。

    双大括号以及v-text会将数据解释为纯文本,而非 HTML 。为了输出真正的 HTML ,需要使用 v-html 指令。

    2、条件与循环

    1)v-if

    v-if是条件渲染指令,根据条件表达式的值来执行元素的插入或者删除行为。

    v-if="expression"

    expression是一个返回bool值的表达式,表达式可以是一个bool属性,也可以是一个返回bool的运算式。

    1 <div class="app">
    2     <span v-if="true">你好!vue.js!</span>
    3 </div>

    这一段代码可以还用js来实现:

    <body>
        <div class="app">     <!--这里不一定要用id,class也行的,只要js里的选择器对应-->
            <span v-if="tag">你好!vue.js!</span>
        </div>
    
        <script type="text/javascript" src="lib/js/vue.js"></script>
        <script type="text/javascript">
            var app = new Vue({
                el:'.app',    //注意选择器
                data:{
                    tag:true
                }
            });
        </script>
    </body>

    尽管用了class而不是id,但是在控制台也是可以通过app.tag来查看变量的:

     拓展:

    v-show也是条件渲染指令,和v-if指令不同的是,使用v-show指令的元素始终会被渲染到HTML,它只是简单地为元素设置CSS的style属性。

    还可以用v-else指令为v-ifv-show添加一个“else块”。v-else元素必须立即跟在v-ifv-show元素的后面——否则它不能被识别。

    v-else元素是否渲染在HTML中,取决于前面使用的是v-if还是v-show指令。)

     1 <body>
     2     <div id="app">
     3         <p v-if="tag">你好!vue.js!</p>
     4         <p v-else>这里是例外情况</p>
     5     </div>
     6 
     7     <script type="text/javascript" src="lib/js/vue.js"></script>
     8     <script type="text/javascript">
     9         var app = new Vue({
    10             el:'#app',    //注意选择器
    11             data:{
    12                 tag:true
    13             }
    14         });
    15     </script>
    16 </body>

    在控制台中改变tag的值:

    2)v-for

    v-for指令基于一个数组渲染一个列表,它和JavaScript的遍历语法相似:

    v-for="item in items"

    items是一个数组,item是当前被遍历的数组元素。

    v-for 指令可以绑定数组的数据来渲染一个项目列表:

     1 <body>
     2     <div class="app">
     3         <p>前端学习之路:</p>
     4         <ol>
     5             <li v-for="item in items">{{item.text}}</li>
     6         </ol>
     7     </div>
     8 
     9     <script type="text/javascript" src="lib/js/vue.js"></script>
    10     <script type="text/javascript">
    11         var app = new Vue({
    12             el:'.app',
    13             data:{
    14                 items:[
    15                     {text:'HTML'},
    16                     {text:'CSS'},
    17                     {text:'JavaScript'},
    18                     {text:'jQuery'}
    19                 ]
    20             }
    21         });
    22     </script>
    23 </body>

     

     在控制台里,输入 app.items.push({ text: '新项目' }),你会发现列表中添加了一个新项:

     另外:v-for还有一种特殊写法可以获取索引值:

    index可以直接用作索引值


     3、处理用户输入

    1)v-on

    v-on指令用于给监听DOM事件,它的用语法和v-bind是类似的,例如监听<a>元素的点击事件:

    <a v-on:click="doSomething">

    有两种形式调用方法:绑定一个方法(让事件指向方法的引用),或者使用内联语句。

     1 <body>
     2     <div id="app">
     3         <p>{{ message }}</p>
     4         <button v-on:click="reverseMessage">逆转消息</button>
     5     </div>
     6 
     7     <script type="text/javascript" src="lib/js/vue.js"></script>
     8     <script type="text/javascript">
     9         var app = new Vue({
    10             el: '#app',
    11             data: {
    12                 message: 'Hello Vue.js!'
    13             },
    14             // 在 `methods` 对象中定义方法
    15             methods: {
    16                 reverseMessage: function () {
    17                     //reverse() 方法用于颠倒数组中元素的顺序。
    18                     //方法中的this指向app
    19                     this.message = this.message.split('').reverse().join('')
    20                 }
    21             }
    22         })
    23     </script>
    24 </body>

    ——————>

    Vue.js为最常用的两个指令v-bindv-on提供了缩写方式。v-bind指令可以缩写为一个冒号,v-on指令可以缩写为@符号。

    2)v-model

    Vue 提供了 v-model 指令,使表单输入和应用状态间的双向绑定变得轻而易举。

     1 <body>
     2     <div id="app">
     3         <p>{{ message }}</p>
     4         <input type="text" v-model="message">
     5         <button v-on:click="alertMessage">弹出输入框内容</button>
     6     </div>
     7 
     8     <script type="text/javascript" src="lib/js/vue.js"></script>
     9     <script type="text/javascript">
    10         var app = new Vue({
    11             el: '#app',
    12             data: {
    13                 message: 'Hello Vue.js!'
    14             },
    15             // 在 `methods` 对象中定义方法
    16             methods: {
    17                 alertMessage: function () {
    18                     
    19                     //方法中的this指向app
    20                     alert(this.message);
    21                 }
    22             }
    23         })
    24     </script>
    25 </body>

    改变输入框的值,会发现上面的p标签的值也改变了。然后点击按钮,弹框中会显示改变的输入框值,这就是双向数据绑定。(也可以通过控制台来改变输入框以及p标签的值)


    三、vue.js基础用法知识

     一开始就学习vue.js的内置指令,估计有些人对vue.js的执行还是有点不理解,下面做简单的讲解。

    1、构造器

    每个 Vue.js 应用都是通过构造函数 Vue 创建一个 Vue 的根实例 启动的:

    1 var vm = new Vue({
    2   // 选项
    3 })

    虽然没有完全遵循 MVVM 模式, Vue 的设计无疑受到了它的启发。因此在文档中经常会使用 vm (ViewModel 的简称) 这个变量名表示 Vue 实例。

    在实例化 Vue 时,需要传入一个选项对象,它可以包含数据、模板、挂载元素、方法、生命周期钩子等选项。

    (这是我用思维导图工具xMind画的,后面三个就不具体列出来了,更加具体的内容可以在官方API查看。)

    new一个vue对象的时候可以设置属性,其中最重要的包括三个,分别是data、methods、watch

    其中data代表vue对象的数据,methods代表vue对象的方法,watch设置了对象监听的方法。如下:

    在第二节的内置指令中已经用到了data和methods。,其他的后面用到了再系统讲解。

    另外可以扩展Vue构造器,从而用预定义选项创建可复用的组件构造器:

    1 var MyComponent = Vue.extend({
    2   // 扩展选项
    3 })
    4 // 所有的 `MyComponent` 实例都将以预定义的扩展选项被创建
    5 var myComponentInstance = new MyComponent()

    所有的 Vue.js 组件其实都是被扩展的 Vue 实例。

    2、属性与方法

     每个 Vue 实例都会代理其 data 对象里所有的属性

     1 var data = { a: 1 }
     2 var vm = new Vue({
     3   data: data
     4 })
     5 vm.a === data.a // -> true
     6 // 设置属性也会影响到原始数据
     7 vm.a = 2
     8 data.a // -> 2
     9 // ... 反之亦然
    10 data.a = 3
    11 vm.a // -> 3

    注意只有这些被代理的属性是响应的。如果在实例创建之后添加新的属性到实例上,它不会触发视图更新。

    除了 data 属性, Vue 实例暴露了一些有用的实例属性与方法。这些属性与方法都有前缀 $,以便与代理的 data 属性区分。

     1 var data = { a: 1 }
     2 var vm = new Vue({
     3   el: '#example',
     4   data: data
     5 })
     6 vm.$data === data // -> true
     7 vm.$el === document.getElementById('example') // -> true
     8 // $watch 是一个实例方法
     9 vm.$watch('a', function (newVal, oldVal) {
    10   // 这个回调将在 `vm.a`  改变后调用
    11 })

    3、实例生命周期

     每个 Vue 实例在被创建之前都要经过一系列的初始化过程。例如,实例需要配置数据观测(data observer)、编译模版、挂载实例到 DOM ,然后在数据变化时更新 DOM 。在这个过程中,实例也会调用一些 生命周期钩子 ,这就给我们提供了执行自定义逻辑的机会。例如,created 这个钩子在实例被创建之后被调用:

    var vm = new Vue({
      data: {
        a: 1
      },
      created: function () {
        // `this` 指向 vm 实例
        console.log('a is: ' + this.a)
      }
    })
    // -> "a is: 1"

    也有一些其它的钩子,在实例生命周期的不同阶段调用,如 mounted、 updated 、destroyed 。钩子的 this 指向调用它的 Vue 实例。一些用户可能会问 Vue.js 是否有“控制器”的概念?答案是,没有。组件的自定义逻辑可以分布在这些钩子中。

    生命周期图示:


    四、实践案例

     1、表格

     主要是利用v-for来实现的:(源代码: github上 demo1/table.html)

    html:

     1 <table id="myTable"  class="table table-striped">
     2         <thead>
     3             <tr>
     4                 <th>姓名</th>
     5                 <th>性别</th>
     6                 <th>年龄</th>
     7             </tr>
     8         </thead>
     9        <tbody>
    10            <tr v-for="item in items">
    11                <td>{{item.name}}</td>
    12                <td>{{item.sex}}</td>
    13                <td>{{item.age}}</td>
    14            </tr>
    15        </tbody>
    16     </table>

    js:

    var vm = new Vue({
                el:'#myTable',
                data:{
                    items:[
                        {
                            name:'张姗',
                            sex:'女',
                            age:'42'
                        },
                        {
                            name:'李四',
                            sex:'男',
                            age:'33'
                        },
                        {
                            name:'王五',
                            sex:'男',
                            age:'58'
                        }
                    ]
                }
            });

    将v-for嵌套在tr标签中,这样就可以生成下面的表格了。案例比较简单。

     2、实时表格编辑

    (源代码: github上 demo1/editTable.html)

    首先我们先确定一下需要做什么:

    我们可以在上面的表单中输入要添加的表格行的具体内容,然后点击添加按钮即可在表格中增加一行。

    点击表格每一行后面的删除按钮,即可删除该表格行。

     1)布局

    在实现功能之前,现将表单模块和表格模块利用HTML实现,这里为了节省时间,直接是使用bootstrap框架。

     1 <form class="form-horizontal" role="form">
     2         <div class="form-group">
     3             <label for="name" class="col-sm-2 control-label">姓名</label>
     4             <div class="col-sm-10">
     5                 <input type="text" class="form-control" id="name" placeholder="请输入名字">
     6             </div>
     7         </div>
     8         <div class="form-group">
     9             <label for="age" class="col-sm-2 control-label">年龄</label>
    10             <div class="col-sm-10">
    11                 <input type="text" class="form-control" id="age" placeholder="请输入年龄">
    12             </div>
    13         </div>
    14         <div class="form-group">
    15             <label for="sex" class="col-sm-2 control-label">性别</label>
    16             <div class="col-sm-10">
    17                 <select name="" id="sex" class="form-control">
    18                     <option value="男"></option>
    19                     <option value="女"></option>
    20                 </select>
    21             </div>
    22         </div>
    23         <div class="form-group">
    24             <div class="col-sm-offset-2 col-sm-10">
    25                 <button type="button" class="btn btn-primary">添加</button>
    26             </div>
    27         </div>
    28     </form>
    29 
    30     <table id="editTable" class="table table-striped">
    31         <thead>
    32             <tr>
    33                 <th>姓名</th>
    34                 <th>年龄</th>
    35                 <th>性别</th>
    36                 <th>操作</th>
    37             </tr>
    38         </thead>
    39         <tbody>
    40             <tr v-for="item in items">
    41                 <td>{{item.name}}</td>
    42                 <td>{{item.age}}</td>
    43                 <td>{{item.sex}}</td>
    44                 <td><button type="button" class="btn btn-primary">删除</button></td>
    45             </tr>
    46         </tbody>
    47     </table>
    View Code

     2)数据绑定

    接下来我们使用v-model将表单输入框绑定到数据层。

    先在data里创建一个新的对象-newItem,用来存放新增的表格行:

    然后将数据绑定到输入框,例如:

     3)添加新增按钮事件

     

    定义名为createItem的函数:

    1 methods:{
    2                 creatItem:function () {
    3                     this.items.push(this.newItem);  //this指向data
    4                     // 添加完newItem对象后,重置newItem对象
    5                     this.newItem = {name: '', age: 0, sex: '女'}
    6                 }
    7             }

     4)添加删除按钮事件

    定义名为deleteItem的函数,并将该表格行的索引作为参数传入;

     1 //事件处理
     2             methods:{
     3                 /**
     4                  * 根据表格行的索引删除该表格行
     5                  * @param  {[number]} index [表格行的索引]
     6                  * @return 
     7                  */
     8                 deleteItem:function (index) {
     9                     this.items.splice(index,1);
    10                 }
    11             }

     完整代码:

    https://github.com/zwl-jasmine95/Vue_test/blob/master/demo1/editTable.html

      1 <!DOCTYPE html>
      2 <html lang="en">
      3 <head>
      4     <meta charset="UTF-8">
      5     <title>实时表格编辑</title>
      6     <link rel="stylesheet" href="../lib/css/bootstrap.min.css">
      7     <style>
      8         body{
      9             padding:50px;
     10         }
     11     </style>
     12 </head>
     13 <body>
     14     <div id="editTable">
     15         <form class="form-horizontal" role="form">
     16             <div class="form-group">
     17                 <label for="name" class="col-sm-2 control-label">姓名</label>
     18                 <div class="col-sm-10">
     19                     <input type="text" class="form-control" id="name" placeholder="请输入名字" v-model="newItem.name">
     20                 </div>
     21             </div>
     22             <div class="form-group">
     23                 <label for="age" class="col-sm-2 control-label">年龄</label>
     24                 <div class="col-sm-10">
     25                     <input type="text" class="form-control" id="age" placeholder="请输入年龄" v-model="newItem.age">
     26                 </div>
     27             </div>
     28             <div class="form-group">
     29                 <label for="sex" class="col-sm-2 control-label">性别</label>
     30                 <div class="col-sm-10">
     31                     <select name="" id="sex" class="form-control" v-model="newItem.sex">
     32                         <option value="男"></option>
     33                         <option value="女"></option>
     34                     </select>
     35                 </div>
     36             </div>
     37             <div class="form-group">
     38                 <div class="col-sm-offset-2 col-sm-10">
     39                     <button type="button" class="btn btn-primary" v-on:click="creatItem">添加</button>
     40                 </div>
     41             </div>
     42         </form>
     43 
     44         <table class="table table-striped">
     45             <thead>
     46             <tr>
     47                 <th>姓名</th>
     48                 <th>年龄</th>
     49                 <th>性别</th>
     50                 <th>操作</th>
     51             </tr>
     52             </thead>
     53             <tbody>
     54             <tr v-for="(item,index) in items">
     55                 <td>{{item.name}}</td>
     56                 <td>{{item.age}}</td>
     57                 <td>{{item.sex}}</td>
     58                 <td><button type="button" class="btn btn-primary" v-on:click="deleteItem(index)">删除</button></td>
     59             </tr>
     60             </tbody>
     61         </table>
     62     </div>
     63 
     64     <script type="text/javascript" src="../lib/js/vue.js"></script>
     65     <script type="text/javascript">
     66         var vm = new Vue({
     67             el:'#editTable',
     68             data:{
     69                 newItem:{
     70                     name:'',
     71                     sex:'',
     72                     age:'0'
     73                 },
     74                 items:[
     75                     {
     76                         name:'张姗',
     77                         sex:'',
     78                         age:'42'
     79                     },
     80                     {
     81                         name:'李四',
     82                         sex:'',
     83                         age:'33'
     84                     },
     85                     {
     86                         name:'王五',
     87                         sex:'',
     88                         age:'58'
     89                     }
     90                 ]
     91             },
     92             //事件处理
     93             methods:{
     94                 creatItem:function () {
     95                     this.items.push(this.newItem);  //this指向data
     96                     // 添加完newItem对象后,重置newItem对象
     97                     this.newItem = {name: '', age: 0, sex: ''}
     98                 },
     99 
    100                 /**
    101                  * 根据表格行的索引删除该表格行
    102                  * @param  {[number]} index [表格行的索引]
    103                  * @return
    104                  */
    105                 deleteItem:function (index) {
    106                     this.items.splice(index,1);
    107                 }
    108             }
    109             
    110         });
    111     </script>
    112 </body>
    113 </html>
    View Code

  • 相关阅读:
    【权值分块】bzoj1208 [HNOI2004]宠物收养所
    【权值分块】bzoj1588 [HNOI2002]营业额统计
    【权值分块】bzoj1503 [NOI2004]郁闷的出纳员
    【pb_ds】bzoj1056 [HAOI2008]排名系统 bzoj1862 [Zjoi2006]GameZ游戏排名系统
    【分块】【树状数组】bzoj3744 Gty的妹子序列
    【权值分块】bzoj3685 普通van Emde Boas树
    【权值分块】bzoj3224 Tyvj 1728 普通平衡树
    【搜索】数学组の问题
    【块状链表】AutSky_JadeK的块状链表模板+总结(STL版)
    【DFS】【最短路】【spfa】【BFS】洛谷P2296 NOIP2014提高组 day2 T2 寻找道路
  • 原文地址:https://www.cnblogs.com/jasmine-95/p/6652783.html
Copyright © 2020-2023  润新知