关于Vue.js的认识(第一部分)[转载]

一、关于v-bind

1.初识v-bind

(1).加冒号的是 vue 的 v-bind 语法糖(指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用),绑定vue的一个数据;不加冒号的就是HTML的属性,和 onclick="doSth()"是一个意思。它是一个 vue 指令,用于绑定 html 属性,如下:

<div id="app">
  <p v-bind:title="title">html属性不能使用双大括号形式绑定,只能使用v-bind指令</p>
</div>
......
var vm = new Vue({
  el: '#app',
  data: {
    title: 'title content'
  }
});

这里的 html 最后会渲染成:

<div id="app">
  <p title="title content">html属性不能使用双大括号形式绑定,只能使用v-bind指令</p>
</div>

2.指令预期值

a.执行运算

上面这种 v-bind 这也是我们对于 vue 指令最初的理解,但实际上,vue 指令的预期值(如 v-bind:class="classProperty" 中,v-bind 是指令,: 后面的 class 是参数,而 classProperty 则在官方文档中被称为“预期值”),除了像上面那样绑定一个字符串类型变量,其实它是支持一个单一 JavaScript 表达式 (v-for 除外)。
所以在这里,我们就可以有更多的选择,例如:

<div id="app">
  <p v-bind:title="t1 + ' ' + t2">html属性不能使用双大括号形式绑定,只能使用v-bind指令</p>
</div>
......
var vm = new Vue({
  el: '#app',
  data: {
    t1: 'title1',
    t2: 'title2'
  }
});

最后渲染的结果:

<div id="app">
  <p title="title1 title2">html属性不能使用双大括号形式绑定,只能使用v-bind指令</p>
</div>

b.执行函数等

<div id="app">
  <p v-bind:title="getTitle()">html属性不能使用双大括号形式绑定,只能使用v-bind指令</p>
</div>
......
var vm = new Vue({
  el: '#app',
  data: {
    getTitle: function () {
      return 'title content';
    }
  }
});

最后渲染的结果:

<div id="app">
  <p title="title content">html属性不能使用双大括号形式绑定,只能使用v-bind指令</p>
</div>

3.支持的数据类型

上面的内容,指令预期值得到的都是字符串类型的数据,但实际上,我们知道 js 有很多数据类型,它如果放入其中呢?

a.对象类型

<div id="app">
  <p v-bind:title="obj">content</p>
</div>
......
var obj = {};
var vm = new Vue({
  el: '#app',
  data: {
    obj: obj
  }
});

渲染结果如下:

<div id="app">
  <p title="[object Object]">content</p>
</div>

诶,这个怎么有点眼熟?有点像...没错!对象的 toString 方法的返回值!为了验证我们的猜想,我们进行进一步的测试:

<div id="app">
  <p v-bind:title="obj">content</p>
</div>
......
var obj = {};
 
obj.toString = function () {
  return 'edited in toString!';
};
 
var vm = new Vue({
  el: '#app',
  data: {
    obj: obj
  }
});

上面这里修改了 obj 的  toString 方法(但准确的说,这里不是修改,而是添加。一开始的 obj 对象上自身是没有 toString 方法的,它继承了 Object.prototype.toString,但这里我们执行 obj.toString  = function..... 实际上是为它添加了一个 toString 方法,使得它执行的时候,不用再去调用继承自 Object 的方法),渲染结果如下:

<div id="app">
  <p title="edited in toString!">content</p>
</div>

b.数组类型

数组类型的 toString 方法和对象类型的有所不同,它将返回和执行 arr.join(',') 相同的结果。如 [1, 2, 3].toString() 将返回 “1,2,3”。下面进行测试:

<div id="app">
  <p v-bind:title="arr">content</p>
</div>
......
var vm = new Vue({
  el: '#app',
  data: {
    arr: [1, 2, 3]
  }
});

渲染结果如下:

<div id="app">
  <p title="1,2,3">content</p>
</div>

c.其它类型

  1. number 类型,正常执行 toString,包括数字0,结果都正常渲染成对应的字符串;
  2. boolean 类型,true 正常渲染成字符串 "true",但 false 虽然执行 toString 方法将返回 "false" 字符串,但是却没有渲染出来
    <div id="app">
        <p v-bind:title="aaa">content</p>
    </div>
    </body>
    <script type="text/javascript">
        var obj={
                a:null,//a:undefined,a:false
        };
    /*     obj.toString=function(){
            return false;
        }(); */
        var vm = new Vue({
            el:'#app',
            data:{
                aaa:obj.a
            }
        });
    </script>

    渲染结果:

    <div id="app">
        <p >aaaaa</p>
    </div>

    结果确实没有渲染出来。

  3. null / undefined 类型,二者没有 toString 方法,也没有渲染出来。

显然,在执行 toString 方法之前,vue 内部应该先做了类型校验,满足条件才输出。而且这里不是简单的真 / 假值校验,因为 、0 虽为假值,但最终却像真值一样渲染了出来。具体如何实现,可能需要参考 vue 的源码了,这里不再深究。

4、多 html 属性值绑定

一个的 html 属性值,可能包含许多内容,需要我们进行一些操作,将多个数据绑定到一个属性上,这里我们可以考虑像前面一样,通过如 “+” 等运算符号等实现字符串的连接操作。但是事实上,字符串连接麻烦又易错,不易于维护。于是我们可以考虑像前面一样向指令预期值中存入一个对象或数组,来实现多个数据绑定到一个属性上的作用。

(1)对象类型

<div id="app">
  <p v-bind:title="obj">content</p>
</div>
......
var obj = {
  name: 'Dale',
  age: 22
};
 
// 利用 for-in 循环遍历对象属性,拼接成字符串
obj.toString = function () {
  var str = '';
  for(var i in this) {
    str += i + ': ' + this[i] + '; ';
  }
  return str;
};
 
// 防止 toString 方法自身被遍历出来
Object.defineProperty(obj, 'toString', {'enumerable': false});
 
var vm = new Vue({
  el: '#app',
  data: {
    obj: obj
  }
});

渲染结果:

<div id="app">
  <p title="name: Dale; age: 22; ">content</p>
</div>

上面通过 for-in 循环在 toString 方法中得到所有可遍历的属性以及对应的属性值,然后将其拼接成字符串再进行输出,可以实现多属性值绑定,至于如何拼接,可以自己在 toString 方法中进行不同的实现 。

2.数组类型

<div id="app">
  <p v-bind:title="arr">content</p>
</div>
......
var arr = [1, 2, 3];
 
arr.toString = function () {
  return this.join(' ');
};
 
var vm = new Vue({
  el: '#app',
  data: {
    arr: arr
  }
});

渲染结果:

<div id="app">
  <p title="1 2 3">content</p>
</div>

相比于对象字符串拼接,数组的拼接操作则显得简单得多,可以直接在 toString 方法返回 join 方法的返回值,默认的 toString 方法的返回值其实就和 join(',') 的返回值相同。

二、关于v-if

1.v-if

v-if,里面这个show是个变量,如果是true就是显示,如果是false就不显示,这里是移除了dom

<div id='root'>
  <div v-if='show'>helle world</div>
  <button @click='handleClick'>toggle</button>
</div>
<script>
  new Vue({
    el:'#root',
    data:{
      show:true
    },
    methods:{
      handleClick:function(){
        this.show = !this.show;
      }
    }
  })
</script>

2.v-else

这里v-if,v-else要紧贴着使用,不然会报错,v-if显示,v-else就会隐藏。v-if隐藏,v-else就会显示

<div id='root'>
  <div v-if='show'>helle world</div>
  <div v-else>bye world</div>
</div>

<script>
  var vm = new Vue({
    el:'#root',
    data:{
      show:true
    }
  })
</script>

3.v-else-if

这里可以根据show的值进行不同的处理,这三个也要紧贴着写,中间不能被其他所分隔

<div id='root'>
  <div v-if='show==="a"'>this is a</div>
  <div v-else-if='show==="b"'>this is b</div>
  <div v-else>this is others</div>
</div>


<script>
  var vm = new Vue({
    el:'#root',
    data:{
      show:'b'
    }
  })
</script>

4.v-if使用的时候key值的用法

<div id='root'>
  <div v-if='show'>
    用户名:<input type="text" />
  </div>
  <div v-else>
    邮箱名:<input type="text" />
  </div>
</div>


<script>
  var vm = new Vue({
    el:'#root',
    data:{
      show:false
    }
  })
</script>

这个例子,在我们使用的时候,show的值变为true,发现邮箱名已经变成了用户名,但是input框里面的值却没变空,这是因为vuejs有一种尝试复用dom的机制,如果已经在的dom,会复用之前的dom,但是这并不是我们想要的效果,这个时候就可以给他加一个key值,告诉vue.js,这是唯一的,是不能复用的input

<div id='root'>
  <div v-if='show'>
    用户名:<input type="text" key='userName'/>
  </div>
  <div v-else>
    邮箱名:<input type="text" key='password' />
  </div>
</div>


<script>
  var vm = new Vue({
    el:'#root',
    data:{
      show:false
    }
  })
</script>

 三、关于v-for

1.在 v-for 指令的表达式中, news 是 data 内定义的数据, n 是当前数组元素的别名。

<div id="app">
    <ul>
        <li v-for="n in news">{{n.title}}</li>
    </ul>
</div>
...
<script>
    var app = new Vue({
        el: '#app',
        data: {
            news: [
                {title: '跑步'},
                {title: '绘画'},
                {title: '读书'}
            ]
        }
    });
</script>

结果:

关于Vue.js的认识(第一部分)[转载]

2.列表渲染指令的表达式也支持使用 of 作为分隔符。(同时支持当前项索引参数,索引从 0 开始,它是可选的

<div id="app">
    <ul>
       <li v-for="(n,index) of news">{{index}} - {{n.title}}</li>
    </ul>
</div>
...
<script>
    var app = new Vue({
        el: '#app',
        data: {
            news: [
                {title: '跑步'},
                {title: '绘画'},
                {title: '读书'}
            ]
        }
    });
</script>

结果:

关于Vue.js的认识(第一部分)[转载]

3.可以使用<template>标签,渲染多个元素

<div id="app">
            <dl>
                <template v-for="n in news">
                    <dt>{{n.title}}</dt>
                    <dd>{{n.content}}</dd>
                </template>
            </dl>
</div>
...
<script>
        var app = new Vue({
            el: '#app',
            data: {
                news: [
                    {title: '跑步',content:"runrunrunrn"},
                    {title: '绘画',content:"drawdrawdraw"},
                    {title: '读书',content:"readreadread"}
                ]
            }
        });
</script>

结果:

关于Vue.js的认识(第一部分)[转载]

4.遍历对象属性

<div id="app">
    <li v-for="val in account">{{val}}</li>
</div>
...
<script>
       var app = new Vue({
           el: '#app',
           data: {
               account: {
                   name: 'xusp',
                   messageCount: 100
               }
           }
       });
</script>

结果:

关于Vue.js的认识(第一部分)[转载]

4.1 遍历对象属性,可以带上两个可选参数,它们就是对象的属性名和索引:

<div id="app">
    <li v-for="(val,name,index) in account">{{index}} - {{name}} : {{val}}</li>
</div>
...
<script>
       var app = new Vue({
           el: '#app',
           data: {
               account: {
                   name: 'xusp',
                   messageCount: 100
               }
           }
       });
</script>

结果:

关于Vue.js的认识(第一部分)[转载]

5.迭代函数

<div id="app">
    <ul>
        <li v-for="i in 5">{{i}}</li>
    </ul>
</div>
...
<script>
      var app = new Vue({
          el: '#app'
      });
</script>

结果:

关于Vue.js的认识(第一部分)[转载]

6.更新数组

Vue.js 的核心是数据与视图的双向绑定。因此当我们修改数组时, Vue.js 就会检测到数据了变化,所以用 v-for 渲染的视图也会更新 。使用以下方法修改数组时,就会触发视图更新:

  • push()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

这些方法会改变原数组,所以又称为变异方法。

我们使用 push() 为 app 对象新增一个标题:

 app.news.push({
         title:'羽毛球'
});

结果:

关于Vue.js的认识(第一部分)[转载]

也有一些非变异方法,它们不会改变原数组,只会返回新数组:

  • filter()
  • concat()
  • slice()

我们在使用这些方法时,可以通过设置新数组的方式来更新视图。

    //非变异方法更新数组
    app.news = app.news.filter(function (item) {
        return item.title.match(/读/);
    });

结果:

关于Vue.js的认识(第一部分)[转载]

这个示例中,我们使用 filter 函数,把新闻标题中含有“读”字样的标题过滤出来。

Vue.js 在检测数组变化时,会最大化地复用 DOM 元素。 替换的数组,如果含有相同元素的项并不会被重新渲染,所以不用担心性能问题。

注意:通过以下方法来改变数组, Vue.js 是无法检测的,所以不会更新视图:

  1. 通过索引来设置项,比如 app.new[1]={...}
  2. 修改数组长度,比如 app.new.length=1

我们可以使用 Vue.js 内置的 set 方法(可指定索引)来更新数组:

<div id="app">
            <ul>
                <li v-for="n in news">{{n.title}}</li>
            </ul>
</div>
...
<script>
     var app = new Vue({
         el:'#app',
         data:{
            news:[
                {title:'跑步'},
                {title:'绘画'},
                {title:'读书'}
            ]
        }
     });
     //通过 set 的设置索引方式来更新数组
     Vue.set(app.news,1,{
         title: '游泳'
     });
</script>

结果:

关于Vue.js的认识(第一部分)[转载]

也可以使用 splice 指定索引来更新数组:

    //通过 splice 的设置索引方式来更新数组
    app.news.splice(1, 0, {
        title: '羽毛球'
    });

结果:关于Vue.js的认识(第一部分)[转载]

至于第二个问题,同样可以通过 splice 来实现:

//通过 splice 来删除数组元素
app.news.splice(1);

 以下三张结果图,分别是括号中的值为1,2,3的时候的结果:

关于Vue.js的认识(第一部分)[转载]关于Vue.js的认识(第一部分)[转载]关于Vue.js的认识(第一部分)[转载]

 7.过滤或排序

<div id="app">
            <h5>过滤出带“美元”的标题</h5>
            <ul>
                <li v-for="(n,index) in filterNews">{{index}} - {{n.title}}</li>
            </ul>
            <h5>按照标题长度,由短到长排序</h5>
            <ul>
                <li v-for="(n,index) in sortNews">{{index}} - {{n.title}}</li>
            </ul>
</div>
...
<script>
        var app = new Vue({
            el: '#app',
            data: {
                news: [
                    {title: '被智能手机绑架的i世代 爱熬夜、拒绝恋爱、不考驾照'},
                    {title: '黑莓宣布14亿美元收购网络安全公司Cylance'},
                    {title: '如何看待XXX开酒店赚美元这件事?'}
                ]
            },
            computed: {
                //过滤出带“美元”的标题
                filterNews: function () {
                    return this.news.filter(function (item) {
                        return item.title.match(/美元/);
                    })
                },
                //按照标题长度,由短到长排序
                sortNews: function () {
                    return this.news.sort(function (val1, val2) {
                        if(val1.title.length < val2.title.length){
                            return -1;
                        }
                    })
                }
            }
        });
</script>

结果:

关于Vue.js的认识(第一部分)[转载]

四、关于v-on

1.基础语法

v-on 指令绑定事件后,就会监听相应的事件。(注意: @click 是 v-on:click 的简写形式, @ 即表示 v-on:

<div id="app">
    <h3>已点击 {{count}} 次</h3>
    <button @click="count++">点我</button>
</div>
...
<script>
        var app = new Vue({
            el: '#app',
            data: {
                count:0
            }
        });
</script>

结果:

关于Vue.js的认识(第一部分)[转载]

1.1 :    @click 表达式即可以直接使用 js 语句,也可以是一个定义在 vue 实例中 methods 内的函数名。(注意: @click 调用的方法名如果不需要参数,那么可以不写括号。

<div id="app">
            <h3>已点击 {{count}} 次</h3>
           <button @click="quickAdd(3)">快速增长</button>
</div>
...
<script>
        var app = new Vue({
            el: '#app',
            data: {
                count:0
            },
            methods: {
                quickAdd: function (i) {
                    i = i || 1;//为避免参数为 null 或 undefined 值,这里设定了默认值 1
                    this.count += i;
                }
            }
        });
</script>

结果:

关于Vue.js的认识(第一部分)[转载]

2.调用DOM事件

Vue.js 还提供了一个 $event 变量,使用它可以访问原生 DOM 事件。$event 变量可以通过方法传入。

<div id="app2">
    <a href="www.baidu.com" @click="openUrl('被禁用咯',$event)">被禁用咯</a>
</div>
...
<script>
       var app2 = new Vue({
           el: '#app2',
           data: {
               count: 0
           },
           methods: {
               openUrl: function (param, event) {
                   event.preventDefault();
                   console.log("param:" + param);
               }
           }
       });
</script>

结果:

关于Vue.js的认识(第一部分)[转载]

这个示例利用传入的 event 参数,禁用了原有的链接跳转逻辑。

3.事件修饰符

Vue.js 支持以下事件修饰符:

事件修饰符 示例 示例说明
.stop @click.stop 阻止单击事件冒泡。
.prevent @submit.prevent 提交页面不再重载页面。
.capture @click.capture 添加事件监听器时使用事件捕获模式。
.self @click.self 只有当单击事件是元素的自身事件时,才会触发。
.once @click.once 只触发一次。

4.按键修饰符

可以使用按键修饰符,来监听表单元素上的键盘事件。

<div id="app3">
            <input @keyup.13="enterClick">
</div>
...
<script>
      var app3 = new Vue({
          el: '#app3',
          data: {},
          methods: {
              enterClick: function () {
                  console.log("enterClick");
              }
          }
      });
</script>

console控制台输出结果:

enterClick

这个示例演示了如何通过回车按键修饰符来绑定事件函数的过程。

除了使用 keycode 来指定按键之外,我们还可以使用以下这些按键别名:

  • .enter
  • .tab
  • .delete
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

用法示例:

<input @keyup.enter="enterClick">

还有一些按键修饰符可以组合使用,或者和鼠标一起使用:

  • .ctrl
  • .alt
  • .shift
  • .metaMac 下为 Command 键,Windows 下为窗口键。

用法示例:

<input @keyup.alt.83="enterClick">

 五、关于v-model(双向绑定)

1.lazy

v-model 指令默认会在 input 事件中加载输入框中的数据(中文输入法中输入拼音的过程除外)。我们可以使用 .lazy 懒加载修饰符,让其只在 change 事件中再加载输入框中的数据。

使用 .lazy 懒加载修饰符之后,只有在输入框失去焦点或者按回车键时才会更新 content 值。

<div id="app">
            <input type="text" v-model.lazy="content" placeholder="请输入" value="初始值">
            <p>输入框:{{content}}</p>
</div>
...
<script>
     var app = new Vue({
         el: '#app',
         data: {
             content: ''
         }
     });
</script>

结果:

关于Vue.js的认识(第一部分)[转载]

2.number

输入框输入的内容,即使是数字,默认也是 string 类型

关于Vue.js的认识(第一部分)[转载]

在此,我们可以使用 .number 修饰符让其转换为 number 类型

<div id="app2">
    <input type="number" v-model.number="content" placeholder="请输入" >
    <p>输入值:{{content}},输入类型:{{typeof content}}</p>
</div>
...
<script>
    var app2 = new Vue({
        el: '#app2',
        data: {
            content: 1
        }
    });
</script>

结果:

关于Vue.js的认识(第一部分)[转载]

3.trim

使用 .trim 修饰符可以自动过滤掉输入框的首尾空格。

<div id="app3">
            <input type="text" v-model.trim="content" placeholder="请输入" value="初始值">
            <p>输入框:{{content}}</p>
</div>
...
<script>
    var app3 = new Vue({
        el: '#app3',
        data: {
            content: ''
        }
    });
</script>

结果:

关于Vue.js的认识(第一部分)[转载]