Vue.js学习笔记

个人博客:小景哥哥

Vue.js学习笔记


简介

Vue.js采用MVVM(Model-View-View-Model)模式,当View(视图层)变化时,会自动更新到ViewModel(视图模型),反之亦然。View和ViewModel之间通过双向绑定建立联系。

有一个比较不错的技术栈:jQuery + RequireJS(SeaJS) + artTemplate(doT) + Gulp(Grunt)

vue第一个示例

<!DOCTYPE html>
<html>
<head>
        <meta charset="utf-8">
        <title>Vue Demo</title>
</head>
<body>
        <div id="app">
             <input type="text" name="" v-model="name" placeholder="你的名字">   
             <h1>Hello, {{name}}</h1>
        </div>
        <script src="https://unpkg.com/vue/dist/vue.min.js"></script>
        <script type="text/javascript">
                var app = new Vue({
                        el:'#app',
                        data:{
                                name:'Jason'
                        }
                })
        </script>
</body>
</html>

Vue.js可以通过构造函数Vue创建一个Vue的根实例,并启动Vue应用:

var app = new Vue({
		//options
})

变量app代表这个Vue实例。几乎所有的代码都是一个对象,写入Vue实例的选项内的。必不可少的一个选项就是el。el用于指定一个页面中已存在的DOM元素来挂载Vue实例,它可以是HTMLElement,也可以是CSS选择器。例如:

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

var app = new Vue({
		el:document.getElementById('app')
})

Vue的生命周期

created: 实例创建完成后调用,此阶段完成了数据的观测等,但尚未挂载,$el还不可用。需要初始化处理一些数据时会比较有用。
mounted: el挂载到实例上后调用,一般我们的第一个业务逻辑会在这里开始。
beforeDestory: 实例销毁之前调用。主要解绑一些使用addEventListener监听的事件等。

这些钩子与el、data类似,也是作为选项写入Vue实例内,并且钩子的this指向的是调用它的Vue实例。

使用双大括号(Mustache语法)“{{ }}”是最基本的文本插值方法,它会自动将我们双向绑定的数据实时显示出来。

<div id="app" >
		{{book}}
</div>
<script>
		var app = new Vue({
			el:'#app',
			data:{
				book:'《Vue.js实战》'
			}
		})
</script>

大括号里的内容会被替换成《Vue.js实战》,通过任何方法修改数据book,大括号的内容都会被实时替换。

如果有时候想输出HTML,而不是将数据解析成纯文本,可以使用v-html:

<div id="app" >
		<span v-html="link"></span>
</div>
<script>
		var app = new Vue({
			el:'#app',
			data:{
				link:'<a href="#">this is a link</a>'
			}
		})
</script>

link的内容会被渲染成一个具有点击功能的a标签,而不是纯文本。

如果想显示{{}}标签,而不进行替换,使用v-pre即可跳过这个元素和它的子元素的编译过程。

过滤器

Vue.js支持在{{ }}插值的尾部添加一个管道符“|”对数据进行过滤,经常用于格式化文本,比如字幕全部大写、货币千位使用逗号分隔等。过滤的规则是自定义的,通过给Vue实例添加选项filters来设置。比如时间格式:

<div id="app" >
  {{ date | formatDate}}
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
		var padDate = function(value){
      return value < 10 ? '0' + value : value;
    }
    var app = new Vue({
      el:'#app',
      data:{
        date: new Date()
      },
      filters: {
        formatDate: function(value){
          var date = new Date(value);
          var year = date.getFullYear();
          var month = padDate(date.getMonth() + 1);
          var day = padDate(date.getDate());
          var hours = padDate(date.getHours());
          var minutes = padDate(date.getMinutes());
          var seconds = padDate(date.getSeconds());
          
          return year + '-' + month + "-" + day + ' ' + hours + ':' + minutes + ':' + seconds;
        }
      },
      
      mounted: function(){
        var _this = this;
        this.timer = setInterval(function(){
          _this.date = new Date();
        },1000)
      },
      beforeDestroy:function(){
        if(this.timer){
          clearInterval(this.timer);
        }
      }
    })
</script>

过滤器也可以串联,而且可以接收参数。

指令与事件

指令(directives)是Vue.js模板中最常用的一项技能,比如v-if、v-html、v-pre等,它的主要职责是当表达式的值改变时,相应地将某些行为应用到DOM上。

v-if:用于判断

v-bind:基本用途是动态更新HTML元素上的属性,比如id、class等。

<div id="app" >
  <a v-bind:href="url" >click me</a><br/>
  <img v-bind:src="imgUrl">
</div>
<script >
		var app = new Vue({
      el:'#app',
      data: {
        url: 'http:www.jinglisen.top',
        imgUrl: 'http:www.jinglisen.top/image_upload/file_1515078253977.jpg'
      }
    })
</script>

V-on: 用来绑定事件监听器,从而做一些事件交互。

<div id="app" >
  <p v-if = "show">
    This is a segment of text.
  </p>
  <button v-on:click="handleClose" >
     click to hide
  </button>
</div>
<script>
	var app = new Vue({
    el:'#app',
    data: {
      show: true
    },
    methods: {
      handleClose: function(){
        this.show = !this.show;
      }
    }
  })
</script>
在button按钮上,除了click还有dblclick、keyup、mousemove等。

语法糖

语法糖可以理解为缩写,是指在不影响功能的情况下,添加某种方法实现同样的效果,从而方便程序开发。Vue.js的v-bind和v-on指令都提供了语法糖,也可以说是缩写,比如v-bind可以省略v-bind,直接写一个冒号":",v-on可以用@来缩写,使用语法糖可以简化代码的开发。

<a :href="url" >click me</a>
<button @click="handleClose">click me to show and hide</button>

计算属性

计算属性是为了解决模板内的表达式过长或逻辑复杂,从而提供代码可读性。在一个计算属性里可以完成各种复杂的逻辑,包括运算、函数调用等,只要最终返回一个结果就可以。计算属性还可以依赖多个Vue实例的数据,只要其中任一数据变化,计算属性就会重新执行,视图也会更新。计算属性除了设置文本插值外,还经常用于动态地设置元素的样式名称class和内联样式style。当使用组件时,计算属性也经常用来动态传递props。计算属性可以依赖其他计算属性,计算属性不仅可以依赖当前Vue实例的数据,还可以依赖其他实例的数据。

v-bind绑定class、style

在数据绑定中,最常见的两个需求就是元素的样式名称class和内联样式style的动态绑定,它们也是HTML的属性,因此可以使用v-bind指令。只需要v-bind计算出表达式最终的字符串即可,不过有时候表达式的逻辑较复杂,使用字符串拼接方法较难阅读和维护,所以vue.js增强了对class和style的绑定。

v-bind:class的语法糖是:class,可设置一个对象动态地切换class。

当需要应用多个class时,可以使用数组语法,给:class绑定一个数组,应用一个class列表。

<div id = "app" >
  <div :class="[activeCls, errorCls]" ></div>
</div>
<script>
	var app = new Vue({
    el:'#app',
    data: {
      activeCls: 'active',
      errorCls: 'error'
    }
  })
</script>
//渲染后的效果为:
<div class="active error">
</div>

也可以使用三元表达式来根据条件切换class,例如:

<div id="app" >
  <div :class="[isActive ? activeCls : '', errorCls]"></div>
</div>
<script>
	var app = new Vue({
    el:'#app',
    data: {
      isActive: true,
      activeCls: 'active',
      errorCls: 'error'
    }
  })
</script>

样式error会始终使用,当数据isActive为真时,样式active才会被应用。

class有多个条件时,这样写较为繁琐,可以在数组语法中使用对象语法:

<div id="app" >
  <div :class="[{'active': isActive}, errorCls]"></div>
</div>
<script>
	var app = new Vue({
    el:'#app',
    data: {
      isActive: true,
      errorCls: 'error'
    }
  })
</script>

使用v-bind:style(或 :style)可以给元素绑定内联样式,方法与:class类似,也有对象语法和数组语法,看起来很像直接在元素上写css。

<div id="app" >
  <div :style="{'color':color,'frontSize':fontSize + 'px'}">
    text
  </div>
</div>
<script>
	var app = new Vue({
    el:'#app',
    data:{
      color:'red',
      fontSize:14
    }
  })
</script>

CSS属性名称使用驼峰命名或短横线命名,渲染后的结果为:

<div style="color:red; front-size:14px;">text</div>

内置指令

v-cloak不需要表达式,它会在Vue实例结束编译时从绑定的HTML元素上移除,经常和CSS的display:none;配合使用:

<div id = "app" v-cloak>
  {{ message }}
</div>
<script>
	var app = new Vue({
    el:'#app',
    data:{
      message: 'This a segment of text.'
    }
  })
</script>

v-once也是一个不需要表达式的指令,作用是定义它的元素或数组只渲染一次,包括元素或组件的所有子节点。首次渲染后,不再随数据的变化重新渲染,将视为静态内容。

v-if、v-else-if、v-else对应于js的条件语句if、else-if、else,Vue.js的条件指令可以根据表达式的值在DOM中渲染或销毁元素/组件。

<div id="app" >
  <p v-if="status === 1">当status为1时显示该行</p>
  <p v-else-if="status === 2">当status为2时显示该行</p>
  <p v-else>否则显示该行</p>
</div>
<script>
	var app = new Vue({
    el:'#app',
    data:{
      status:1
    }
  })
</script>

v-show的用法与v-if基本一致,只不过v-show是改变元素的CSS属性display。当v-show表达式的值为false时,元素会被隐藏,DOM元素上会加载内联样式display:none,v-show不能用在<template>上使用。v-if适合用在条件不经常改变的场景,因为它切换开销较大,而v-show适用于频繁切换的场景。

<div id = "app" >
  <p v-show="status === 1" >
   	当status为1时显示
  </p>
</div>
<script>
	var app = new Vue({
    el:'#app',
    data{
    status:2
  }
  })
</script>

v-for主要用于循环遍历数据或者对象,它的表达式需要结合in来使用,类似item in items的形式,也可以用item of items的形式。

<div id="app">
  <ul>
    <li v-for="(book, index) in books">{{ index }}--{{ book.name }}--{{book.author}}</li>
  </ul>
</div>
<script>
	var app = new Vue({
    el:'#app',
    data: {
      books:[
        {name:'Race Against time.',author:'Jason'},
        {name:'MySql',author:'Bro J'},
        {name:'Discrete Mathematics and Its Applications',author:'KHR'}
      ]
    }
  })
</script>

与v-if一样,v-for也可以使用在内置标签<template>上,将多个元素进行渲染。

<div id="app">
  <ul>
    <template v-for="book in books">
    	<li>book name:{{book.name}}</li>
      <li>book author:{{book.author}}</li>
    </template>
  </ul>
</div>
<script>
	var app = new Vue({
    el:'#app',
    data: {
      books:[
        {name:'Race Against time.',author:'Jason'},
        {name:'MySql',author:'Bro J'},
        {name:'Discrete Mathematics and Its Applications',author:'KHR'}
      ]
    }
  })
</script>

除了数组外,对象的属性也是可以遍历的。

<div id="app">
  <span v-for="(val,key,index) in user">{{index}} - {{key}} - {{ val }}<br/></span>
</div>
<script>
	var app = new Vue({
    el:'#app',
    data:{
      user:{
        name:'Jason',
        gender:'male',
        age:'23'
      }
    }
  })
</script>

v-for还可以迭代整数:

<div id="app" >
  <span v-for="i in 100" >{{i}}   </span>
</div>
<script>
	var app = new Vue({
    el:'#app'
  })
</script>

Vue的核心是数据和视图的双向绑定,当修改数组时,Vue会检测到数据变化,所以用v-for渲染的视图也会立即更新。Vue包含了一组观察数据变化的方法,使用它们改变数组也会触发视图更新。

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

例如:

app.books.push({
	name:'Linux',
	author:'Bro bird'
})

方法和事件

点击事件v-on,类似于JS中的onclick事件。

<div id="app" >
  click num: {{counter}}
	<button @click="counter++" > + 1</button>
</div>
<script>
new Vue({
  el:'#app',
  data:{
    counter:0
  }
})
</script>

Vue提供了一个特殊变量$event,用于访问原生DOM事件,例如下面实例可以阻止链接打开。

<div id="app" >
  <a href="http://www.jinglisen.top" @click="handleClick('禁止打开',$event)">
  open click</a>
</div>
<script>
new Vue({
  el:'#app',
  methods:{
    handleClick: function(message,event){
      event.preventDefault();
      window.alert(message);
    }
  }
})
</script>

小案例

//index.html

<!DOCTYPE html>
<html>
<head>
        <meta charset="utf-8">
        <title>购物车示例</title>
        <link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
        <div id="app" v-cloak>
             <template v-if="list.length">
                 <table>
                     <thead>
                         <tr>
                             <th></th>
                             <th>商品名称</th>
                             <th>商品单价</th>
                             <th>购买数量</th>
                             <th>操作</th>
                         </tr>
                     </thead>
                     <tbody>
                         <tr v-for="(item, index) in list">
                             <td>{{index + 1}}</td>
                             <td>{{item.name}}</td>
                            <td>{{item.price}}</td>
                            <td>
                                <button @click="handleReduce(index)"
                                :disabled="item.count === 1">-</button>
                                {{item.count}}
                                <button @click="handleAdd(index)">+</button>
                            </td>
                            <td>
                                <button @click="handleRemove(index)">移除</button>
                            </td>
                         </tr>
                     </tbody>
                 </table>
                 <div>total price: ¥ {{ totalPrice }}</div>
             </template>
             <div v-else>购物车为空</div>
        </div>
        <script src="https://unpkg.com/vue/dist/vue.min.js"></script>
        <script type="text/javascript" src="index.js"></script>
</body>
</html>
//index.js
var app = new Vue({
  el: '#app',
  data:{
      list:[
          {
            id:1,
            name:'iPhone 11 Pro',
            price:9599,
            count:1
          },
          {
            id:2,
            name:'iPad Pro',
            price:7999,
            count:1
          },
          {
            id:3,
            name:'MacBook Pro',
            price:18999,
            count:1
          }
      ]
  },
  computed:{
      totalPrice: function(){
        var total = 0;
        for(var i = 0; i < this.list.length; i++){
          var item = this.list[i];
          total += item.price * item.count;
        }
        return total.toString().replace(/\B(?=(\d{3})+$)/g,',');
      }
  },
  methods:{
      handleReduce: function(index){
        if(this.list[index].count === 1) return;
        this.list[index].count--;
      },
      handleAdd:function(index){
        this.list[index].count++;
      },
      handleRemove:function(index){
        this.list.splice(index,1);
      }
  }
})
//style.css
[v-cloak]{
  display: none,
}
table{
  border:1px solid #e9e9e9;
  border-collapse: collapse;
  border-spacing: 0;
  empty-cells: show;
}
th,td{
  padding: 8px 16px;
  border: 1px solic #e9e9e9;
  text-align: left;
}
th{
  background: #f7f7f7;
  color:#5c6b77;
  font-weight: 600;
  white-space: nowrap;
}

表单与v-model

Vue.js提供了v-model指令,用于表单数据双向绑定。例如下面例子,在输入框输入数据的同时,{{message}}也会实时将内容渲染在视图中。

<div id="app" >
  <input type="text" v-model="message" placeholder="请输入">
  <p>
    输入的内容是: {{message}}
  </p>
</div>
<script>
new Vue({
  el:'#app',
  data:{
    message:''
  }
})
</script>

如果希望总是实时更新数据,而不是输入法敲击回车之后才显示,可以使用@input来代替v-model。

<div id="app" >
  <input type="text" @input="handleInput" placeholder="请输入">
  <p>
    输入的内容是: {{message}}
  </p>
</div>
<script>
new Vue({
  el:'#app',
  data:{
    message:''
  },
  methods:{
    handleInput: function(e){
      this.message = e.target.value;
    }
  }
})
</script>

单选

单选按钮在单独使用时,不需要v-model,直接使用v-bind绑定一个布尔值,为真时选中,为否时不选中。

<div id="app" >
  <input type="radio" :checked="picked">
  <label>单选按钮</label>
</div>
<script>
new Vue({
  el:'#app',
  data:{
    picked: true
  }
})
</script>

如果是组合使用来实现互斥选择的效果,就需要v-model配合value来使用。

<div id="app" >
  <input type="radio" v-model="picked" value="html" id="html">
  <label for="html">html</label>
  <br>
  <input type="radio" v-model="picked" value="js" id="js">
  <label for="js">js</label>
  <br>
  <input type="radio" v-model="picked" value="css" id="css">
  <label for="css">css</label>
  <br>
  <p>
    选择的项是: {{ picked }}
  </p>
</div>
<script>
new Vue({
  el:'#app',
  data:{
    picked:'js'
  }
})
</script>

复选框

复选框也分单选使用和组合使用,不过用法稍微与单选不同。复选框单独使用时,也是用v-model来绑定一个布尔值。

<div id="app" >
  <input type="checkbox" v-model="checked" id="checked">
  <label for="checked">选择状态: {{ checked }}</label>
</div>
<script>
new Vue({
  el:'#app',
  data:{
    checked: false
  }
})
</script>

组合使用时,也是v-model与value一起,多个勾选框都绑定到同一个数组类型的数据,value的值在数组当中,就会选中这一项。这一过程也是双向的,在勾选时,value的值也会自动push到这个数组中。

<div id="app" >
  <input type="checkbox" v-model="checked" value="html" id="html">
  <label for="html">html</label>
  <br>
  <input type="checkbox" v-model="checked" value="js" id="js">
  <label for="js">js</label>
  <br>
  <input type="checkbox" v-model="checked" value="css" id="css">
  <label for="css">css</label>
</div>
<script>
new Vue({
  el:'#app',
  data:{
    checked:['js','css']
  }
})
</script>

选中列表

选择列表就是下拉选择器,也是常用的表单控件,同样也分单选和多选两种方式。

<div id="app" >
  <select v-model="selected">
    <option>html</option>
    <option value="js">JavaStript</option>
    <option>css</option>
  </select>
  <p>
    选择的选项是: {{selected}}
  </p>
</div>
<script>
new Vue({
  el:'#app',
  data:{
    selected: 'html'
  }
})
</script>

<option>是备选项,如果含有value属性,v-model就会优先匹配value;如果没有,就会直接匹配<option>的text,比如选中第二项时,selected的值是js而不是JavaScript。

给selected添加属性multiple就可以多选了,此时v-model绑定的是一个数组,与复选框用法类似。

<div id="app" >
  <select v-model="selected" multiple>
    <option>html</option>
    <option value="js">JavaStript</option>
    <option>css</option>
  </select>
  <p>
    选中的项是: {{selected}}
  </p>
</div>
<script>
new Vue({
  el:'#app',
  data:{
    selected:['html','js']
  }
})
</script>

在业务中,<option>经常用v-for动态输出,value和text也是用v-bind来动态输出的。

<div id="app" >
  <select v-model="selected">
    <option v-for="option in options"
            :value="option.value">{{option.text}}</option>
  </select>
  <p>
    选择的项是: {{selected}}
  </p>
</div>
<script>
new Vue({
  el:'#app',
  data:{
    selected:'html',
    options:[
      {
        text:'HTML',
        value:'html'
      },
      {
        text:'JavaScript',
        value:'js'
      },
      {
        text:'CSS',
        value:'css'
      }
    ]
  }
})
</script>

单选框、复选框和选择列表在单独使用或单选的模式下,v-model绑定的值是一个静态字符串或布尔值,但在业务中,有时需要绑定一个动态的数据,这是可以用v-bind来实现。

//单选框
<div id="app" >
  <input type="radio" v-model="picked" :value="value">
  <label>单选按钮</label>
  <p>
    {{picked}}
  </p>
  <p>
    {{value}}
  </p>
</div>
<script>
new Vue({
  el:'#app',
  data:{
    picked:false,
    value:23
  }
})
</script>
//复选框
<div id="app" >
  <input type="checkbox" v-model="toggle" :true-value="value1" :false-value="value2">
  <label>复选框</label>
  <p>
    {{toggle}}
  </p>
  <p>
    {{ value1}}
  </p>
  <p>
    {{value2}}
  </p>
</div>
  
<script>
new Vue({
  el:'#app',
  data:{
    toggle:false,
    value1:'a',
    value2:'b'
  }
})
</script>
//选择列表
<div id="app" >
  <select v-model="selected">
    <option :value="{number: 123}">123</option>
  </select>  
  {{selected.number}}
</div>
<script>
new Vue({
  el:'#app',
  data:{
    selected: ''
  }
})
</script>
<div id="app" >
  
</div>
<script>
new Vue({
  el:'#app',
  data:{
    
  }
})
</script>
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页