APP开发-Vue.js学习教程(二)

八、Vue.js 样式绑定

Vue.js class

class 与 style 是 HTML 元素的属性,用于设置元素的样式,我们可以用 v-bind 来设置样式属性。

Vue.js v-bind 在处理 class 和 style 时, 专门增强了它。表达式的结果类型除了字符串之外,还可以是对象或数组。

class 属性绑定

我们可以为 v-bind:class 设置一个对象,从而动态的切换 class:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<script src="vue.js" type="text/javascript" charset="utf-8"></script>
	<style>
		.active{
			width: 150px;
			height: 200px;
			background: red;
		}
	</style>
	<body>
		<div id="app">
			<div v-bind:class="{ 'active': isActive }"></div>
		</div>
		<script>
			new Vue({
				el:'#app',
				data:{
					isActive:true
				}
			})
		</script>
	</body>
</html>

以上实例 div class 为:

<div class="active"></div>

我们也可以在对象中传入更多属性用来动态切换多个 class :

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<script src="vue.js" type="text/javascript" charset="utf-8"></script>
	<style>
		.active{
			width: 150px;
			height: 200px;
			background: green;
		}
		.text-danger{
			background: red;
		}
	</style>
	<body>
		<div id="app">
			<div class="static" v-bind:class="{ 'active': isActive, 'text-danger':hasError }"></div>
		</div>
		<script>
			new Vue({
				el:'#app',
				data:{
					isActive:true,
					hasError:false
				}
			})
		</script>
	</body>
</html>

以上实例 div class 为:

<div class="static active text-danger "></div>

我们也可以直接绑定数据里的一个对象:

<div id="app">
			<div v-bind:class="classObject"></div>
		</div>
		<script>
			new Vue({
				el:'#app',
				data:{
					classObject:{
						active:true,
						'text-danger':true
					}
				}
			})
		</script>

此外,我们也可以在这里绑定返回对象的计算属性。这是一个常用且强大的模式:

<style>
		.base{
			width: 100px;
			height: 100px;
		}
		.active{
			width: 150px;
			height: 200px;
			background: green;
		}
		.text-danger{
			background: red;
		}
	</style>
	
	<script>
			new Vue({
			  el: '#app',
			  data: {
			    isActive: true,
			    error: {
			      value: true,
			      type: 'fatal'
			    }
			  },
			  computed: {
			    classObject: function () {
			      return {
					base: true,
			        active: this.isActive && !this.error.value,
			        'text-danger': this.error.value && this.error.type === 'fatal',
			      }
			    }
			  }
			})
		</script>

数组语法

我们可以把一个数组传给 v-bind:class ,实例如下:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<script src="vue.js" type="text/javascript" charset="utf-8"></script>
	<style>
		.active{
			width: 150px;
			height: 200px;
			background: green;
		}
		.text-danger{
			background: red;
		}
	</style>
	<body>
		<div id="app">
			<div v-bind:class="activeclass,errorclass"></div>
		</div>
		<script>
			new Vue({
				el:'#app',
				data:{
					activeclass:'active',
					errorclass:'text-danger'
				}
			})
		</script>
	</body>
</html>

还可以使用三元表达式来切换列表中的 class :

		<div id="app">
			<!--<div v-bind:class="activeclass,errorclass"></div>-->
			<div v-bind:class="[errorclass ,isActive ? activeclass : '']"></div>
		</div>

errorClass 是始终存在的,isActive 为 true 时添加 activeClass 类。

Vue.js style(内联样式)

我们可以在 v-bind:style 直接设置样式:

<body>
		<div id="app">
			<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }">阿饼教学</div>
		</div>
		<script>
			new Vue({
				el:'#app',
				data:{
					activeColor:'green',
					fontSize:30
				}
			})
		</script>
	</body>

也可以直接绑定到一个样式对象,让模板更清晰:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<script src="vue.js" type="text/javascript" charset="utf-8"></script>
	<body>
		<div id="app">
			<div v-bind:style="styleObject">1234</div>
		</div>
		<script>
			new Vue({
				el:'#app',
				data:{
					styleObject:{
						color:'green',
						fontSize:'30px'
					}
				}
			})
		</script>
	</body>
</html>

v-bind:style 可以使用数组将多个样式对象应用到一个元素上:

<body>
		<div id="app">
			<div v-bind:style="[baseStyles, overridingStyles]">1234</div>
		</div>
		<script>
			new Vue({
				el:'#app',
				data:{
					baseStyles:{
						color:'green',
						fontSize:'30px'
					},
					overridingStyles:{
						'font-weight':'bold'//字体加粗
					}
				}
			})
		</script>
	</body>

注意:当 v-bind:style 使用需要特定前缀的 CSS 属性时,如 transform ,Vue.js 会自动侦测并添加相应的前缀。

九、Vue.js 事件处理器

回归到之前所说的 v-on 指令,可以进行事件监听:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<script src="vue.js" type="text/javascript" charset="utf-8"></script>
	<body>
		<div id="app">
			<p>按钮被点击了{{counter}}次</p>
			<button v-on:click="counter+=1">增加1</button>
		</div>
		<script>
			new Vue({
				el:'#app',
				data:{
					counter:0
				}
			})
		</script>
	</body>
</html>

通常情况下,我们需要使用一个方法来调用 JavaScript 方法。

v-on 可以接收一个定义的方法来调用。

<div id="app">
		   <!-- `greet` 是在下面定义的方法名 -->
		  <button v-on:click="greet">Greet</button>
		</div>
		
		<script>
		var app = new Vue({
		  el: '#app',
		  data: {
		    name: 'Vue.js'
		  },
		  // 在 `methods` 对象中定义方法
		  methods: {
		    greet: function (event) {
		      // `this` 在方法里指当前 Vue 实例
		      alert('Hello ' + this.name + '!')
		      // `event` 是原生 DOM 事件
			  if (event) {
				  alert(event.target.tagName)
			  }
		    }
		  }
		})
		// 也可以用 JavaScript 直接调用方法
		app.greet() // -> 'Hello Vue.js!'
		</script>

除了直接绑定到一个方法,也可以用内联 JavaScript 语句:

<div id="app">
			<button v-on:click="say('hi')">Say hi</button>
		    <button v-on:click="say('what')">Say what</button>
		</div>
		
		<script>
		var app = new Vue({
		  el: '#app',
		  methods:{
			  say:function(message){
				  alert(message)
				}
			}
		})

事件修饰符

Vue.js 为 v-on 提供了事件修饰符来处理 DOM 事件细节,如:event.preventDefault() 或 event.stopPropagation()。

Vue.js 通过由点 . 表示的指令后缀来调用修饰符。

  • .stop - 阻止冒泡
  • .prevent - 阻止默认事件
  • .capture - 阻止捕获
  • .self - 只监听触发该元素的事件
  • .once - 只触发一次
  • .left - 左键事件
  • .right - 右键事件
  • .middle - 中间滚轮事件
<!-- 阻止单击事件冒泡 -->
<a v-on:click.stop="doThis"></a>
<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修饰符可以串联  -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>
<!-- 添加事件侦听器时使用事件捕获模式 -->
<div v-on:click.capture="doThis">...</div>
<!-- 只当事件在该元素本身(而不是子元素)触发时触发回调 -->
<div v-on:click.self="doThat">...</div>

<!-- click 事件只能点击一次,2.1.4版本新增 -->
<a v-on:click.once="doThis"></a>

按键修饰符

Vue 允许为 v-on 在监听键盘事件时添加按键修饰符:

<!-- 只有在 keyCode 是 13 时调用 vm.submit() -->
<input v-on:keyup.13="submit">

记住所有的 keyCode 比较困难,所以 Vue 为最常用的按键提供了别名:

<!-- 同上 -->
<input v-on:keyup.enter="submit">
<!-- 缩写语法 -->
<input @keyup.enter="submit">

全部的按键别名:

  • .enter
  • .tab
  • .delete (捕获 "删除" 和 "退格" 键)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right
  • .ctrl
  • .alt
  • .shift
  • .meta

实例:

<p><!-- Alt + C -->
<input @keyup.alt.67="clear">
<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>

十、Vue.js 表单

这节我们为大家介绍 Vue.js 表单上的应用。

你可以用 v-model 指令在表单控件元素上创建双向数据绑定。

img

v-model 会根据控件类型自动选取正确的方法来更新元素。

输入框

实例中演示了 input 和 textarea 元素中使用 v-model 实现双向数据绑定:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<script src="vue.js" type="text/javascript" charset="utf-8"></script>
	<body>
		<div id="app">
		  <p>input 元素:</p>
		  <input v-model="message" placeholder="编辑我……">
		  <p>消息是: {{ message }}</p>
		    
		  <p>textarea 元素:</p>
		  <p style="white-space: pre">{{ message2 }}</p>
		  <textarea v-model="message2" placeholder="多行文本输入……"></textarea>
		</div>
		<script>
		new Vue({
		  el: '#app',
		  data: {
		    message: '阿饼',
		    message2: 'https://www.cnblogs.com/knight-errant-dr/'
		  }
		})
		</script>
	</body>
</html>

复选框

复选框如果是一个为逻辑值,如果是多个则绑定到同一个数组,以下实例中演示了复选框的双向数据绑定:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<script src="vue.js" type="text/javascript" charset="utf-8"></script>
	<body>
		<div id="app">
		  <p>单个复选框:</p>
		  <input type="checkbox" id="checkbox" v-model="checked">
		  <label for="checkbox">{{ checked }}</label>
		    
		  <p>多个复选框:</p>
		  <input type="checkbox" id="runoob" value="Runoob" v-model="checkedNames">
		  <label for="runoob">Runoob</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>
	</body>
</html>

单选按钮

以下实例中演示了单选按钮的双向数据绑定:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<script src="vue.js" type="text/javascript" charset="utf-8"></script>
	<body>
		<div id="app">
		  <input type="radio" id="runoob" value="Runoob" v-model="picked">
		  <label for="runoob">Runoob</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>
	</body>
</html>

select 列表

以下实例中演示了下拉列表的双向数据绑定:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<script src="vue.js" type="text/javascript" charset="utf-8"></script>
	<body>
		<div id="app">
		  <select v-model="selected" name="fruit">
		    <option value="">选择一个网站</option>
		    <option value="www.runoob.com">Runoob</option>
		    <option value="www.google.com">Google</option>
		  </select>
		
		  <div id="output">
		      选择的网站是: {{selected}}
		  </div>
		</div>
		 
		<script>
		new Vue({
		  el: '#app',
		  data: {
		    selected: '' 
		  }
		})
		</script>
	</body>
</html>

修饰符

.lazy

在默认情况下, v-model 在 input 事件中同步输入框的值与数据,但你可以添加一个修饰符 lazy ,从而转变为在 change 事件中同步:

<!-- 在 "change" 而不是 "input" 事件中更新 -->
<input v-model.lazy="msg" >

.number

如果想自动将用户的输入值转为 Number 类型(如果原值的转换结果为 NaN 则返回原值),可以添加一个修饰符 number 给 v-model 来处理输入值:

<input v-model.number="age" type="number">

这通常很有用,因为在 type="number" 时 HTML 中输入的值也总是会返回字符串类型。

.trim

如果要自动过滤用户输入的首尾空格,可以添加 trim 修饰符到 v-model 上过滤输入:

<input v-model.trim="msg">

十一、Vue.js 组件

组件(Component)是 Vue.js 最强大的功能之一。

组件可以扩展 HTML 元素,封装可重用的代码。

组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树:

img

注册一个全局组件语法格式如下:

Vue.component(tagName, options)

tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件:

<tagName></tagName>

全局组件

所有实例都能用全局组件。

全局组件实例

注册一个简单的全局组件 runoob,并使用它:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<script src="vue.js" type="text/javascript" charset="utf-8"></script>
	<body>
		<div id="app">
		    <runoob></runoob>
		</div>
		 
		<script>
		// 注册
		Vue.component('runoob', {
		  template: '<h1>自定义组件!</h1>'
		})
		// 创建根实例
		new Vue({
		  el: '#app'
		})
		</script>
	</body>
</html>

局部组件

我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<script src="vue.js" type="text/javascript" charset="utf-8"></script>
	<body>
		<div id="app">
		    <runoob></runoob>
		</div>
		 
		<script>
		var Child = {
		  template: '<h1>自定义组件!</h1>'
		}
		 
		// 创建根实例
		new Vue({
		  el: '#app',
		  components: {
		    // <runoob> 将只在父模板可用
		    'runoob': Child
		  }
		})
		</script>
	</body>
</html>

Prop

prop 是子组件用来接受父组件传递过来的数据的一个自定义属性。

父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop":

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<script src="vue.js" type="text/javascript" charset="utf-8"></script>
	<body>
		<div id="app">
			<child message="hello"></child>
		</div>
		<script>
			Vue.component('child',{
				//声明props
				props:['message'],
				//同样也可以在 vm 实例中像 "this.message" 这样使用
				template:'<span>{{message}}</span>'
			})
			// 创建根实例
			new Vue({
				el:'#app'
			})
		</script>
	</body>
</html>

动态 Prop

类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<script src="vue.js" type="text/javascript" charset="utf-8"></script>
	<body>
		<div id="app">
		    <div>
		      <input v-model="parentMsg">
		      <br>
		      <child v-bind:message="parentMsg"></child>
		    </div>
		</div>
		<script>
			Vue.component('child',{
				//声明props
				props:['message'],
				//同样也可以在 vm 实例中像 "this.message" 这样使用
				template:'<span>{{message}}</span>'
			})
			// 创建根实例
			new Vue({
				el:'#app',
				data:{
					parentMsg:'父组件内容'
				}
			})
		</script>
	</body>
</html>

以下实例中使用 v-bind 指令将 todo 传到每一个重复的组件中:

<div id="app">
		    <ol>
		    <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>
		      </ol>
		</div>
		 
		<script>
		Vue.component('todo-item', {
		  props: ['todo'],
		  template: '<li>{{ todo.text }}</li>'
		})
		new Vue({
		  el: '#app',
		  data: {
		    sites: [
		      { text: 'Runoob' },
		      { text: 'Google' },
		      { text: 'Taobao' }
		    ]
		  }
		})
		</script>

注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。

Prop 验证

组件可以为 props 指定验证要求。

为了定制 prop 的验证方式,你可以为 props 中的值提供一个带有验证需求的对象,而不是一个字符串数组。例如:

Vue.component('my-component', {
  props: {
    // 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
    propA: Number,
    // 多个可能的类型
    propB: [String, Number],
    // 必填的字符串
    propC: {
      type: String,
      required: true
    },
    // 带有默认值的数字
    propD: {
      type: Number,
      default: 100
    },
    // 带有默认值的对象
    propE: {
      type: Object,
      // 对象或数组默认值必须从一个工厂函数获取
      default: function () {
        return { message: 'hello' }
      }
    },
    // 自定义验证函数
    propF: {
      validator: function (value) {
        // 这个值必须匹配下列字符串中的一个
        return ['success', 'warning', 'danger'].indexOf(value) !== -1
      }
    }
  }
})

prop 验证失败的时候,(开发环境构建版本的) Vue 将会产生一个控制台的警告。

type 可以是下面原生构造器:

  • String
  • Number
  • Boolean
  • Array
  • Object
  • Date
  • Function
  • Symbol

type 也可以是一个自定义构造器,使用 instanceof 检测。

十二、Vue.js 组件 - 自定义事件

父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!

我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:

  • 使用 $on(eventName) 监听事件
  • 使用 $emit(eventName) 触发事件

另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。

以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<script src="vue.js" type="text/javascript" charset="utf-8"></script>
	<body>
		<div id="app">
		    <div id="counter-event-example">
		      <p>{{ total }}</p>
		      <button-counter v-on:increment="incrementTotal"></button-counter>
		      <button-counter v-on:increment="incrementTotal"></button-counter>
		    </div>
		</div>
		 
		<script>
		Vue.component('button-counter', {
		  template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
		  data: function () {
		    return {
		      counter: 0
		    }
		  },
		  methods: {
		    incrementHandler: function () {
		      this.counter += 1
		      this.$emit('increment')
		    }
		  },
		})
		new Vue({
		  el: '#counter-event-example',
		  data: {
		    total: 0
		  },
		  methods: {
		    incrementTotal: function () {
		      this.total += 1
		    }
		  }
		})
		</script>
	</body>
</html>

如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如:

<my-component v-on:click.native="doTheThing"></my-component>

data 必须是一个函数

上面例子中,可以看到 button-counter 组件中的 data 不是一个对象,而是一个函数,这样的好处就是每个实例可以维护一份被返回对象的独立的拷贝,如果 data 是一个对象则会影响到其他实例,如下所示:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<script src="vue.js" type="text/javascript" charset="utf-8"></script>
	<body>
		<div id="components-demo3" class="demo">
		    <button-counter2></button-counter2>
		    <button-counter2></button-counter2>
		    <button-counter2></button-counter2>
		</div>
		 
		<script>
		var buttonCounter2Data = {
		  count: 0
		}
		Vue.component('button-counter2', {
		    /*
		    data: function () {
		        // data 选项是一个函数,组件不相互影响
		        return {
		            count: 0
		        }
		    },
		    */
		    data: function () {
		        // data 选项是一个对象,会影响到其他实例
		        return buttonCounter2Data
		    },
		    template: '<button v-on:click="count++">点击了 {{ count }} 次。</button>'
		})
		new Vue({ el: '#components-demo3' })
		</script>

	</body>
</html>

自定义组件的 v-model

组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件。

<input v-model="parentData">

等价于:

<input 
    :value="parentData"
    @input="parentData = $event.target.value"
>

以下实例自定义组件 runoob-input,父组件的 num 的初始值是 100,更改子组件的值能实时更新父组件的 num:

<div id="app">
		    <runoob-input v-model="num"></runoob-input>
		    <p>输入的数字为:{{num}}</p>
		</div>
		<script>
		Vue.component('runoob-input', {
		    template: `
		    <p>   <!-- 包含了名为 input 的事件 -->
		      <input
		       ref="input"
		       :value="value" 
		       @input="$emit('input', $event.target.value)"
		      >
		    </p>
		    `,
		    props: ['value'], // 名为 value 的 prop
		})
		   
		new Vue({
		    el: '#app',
		    data: {
		        num: 100,
		    }
		})
		</script>

由于 v-model 默认传的是 value,不是 checked,所以对于复选框或者单选框的组件时,我们需要使用 model 选项,model 选项可以指定当前的事件类型和传入的 props。

<div id="app">
    <base-checkbox v-model="lovingVue"></base-checkbox> 
     <div v-show="lovingVue"> 
        如果选择框打勾我就会显示。 
    </div>
</div> 
<script>
// 注册
Vue.component('base-checkbox', {
 
  model: {
    prop: 'checked',
    event: 'change'  // onchange 事件
  },
  props: {
    checked: Boolean
  },
   
  template: `
    <input
      type="checkbox"
      v-bind:checked="checked"
      v-on:change="$emit('change', $event.target.checked)"
    >
  `
})
// 创建根实例
new Vue({
  el: '#app',
  data: {
    lovingVue: true
  }
})
</script>

实例中 lovingVue 的值会传给 checked 的 prop,同时当 触发 change 事件时, lovingVue 的值也会更新。

十三、Vue.js 自定义指令

除了默认设置的核心指令( v-model 和 v-show ), Vue 也允许注册自定义指令。

下面我们注册一个全局指令 v-focus, 该指令的功能是在页面加载时,元素获得焦点:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<script src="vue.js" type="text/javascript" charset="utf-8"></script>
	<body>
		<div id="app">
		    <p>页面载入时,input 元素自动获取焦点:</p>
		    <input v-focus>
		</div>
		 
		<script>
		// 注册一个全局自定义指令 v-focus
		Vue.directive('focus', {
		  // 当绑定元素插入到 DOM 中。
		  inserted: function (el) {
		    // 聚焦元素
		    el.focus()
		  }
		})
		// 创建根实例
		new Vue({
		  el: '#app'
		})
		</script>
	</body>
</html>

我们也可以在实例使用 directives 选项来注册局部指令,这样指令只能在这个实例中使用:

<div id="app">
		  <p>页面载入时,input 元素自动获取焦点:</p>
		  <input v-focus>
		</div>
		 
		<script>
		// 创建根实例
		new Vue({
		  el: '#app',
		  directives: {
		    // 注册一个局部的自定义指令 v-focus
		    focus: {
		      // 指令的定义
		      inserted: function (el) {
		        // 聚焦元素
		        el.focus()
		      }
		    }
		  }
		})
		</script>

钩子

钩子函数

指令定义函数提供了几个钩子函数(可选):

  • bind: 只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。
  • inserted: 被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document 中)。
  • update: 被绑定元素所在的模板更新时调用,而不论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新(详细的钩子函数参数见下)。
  • componentUpdated: 被绑定元素所在模板完成一次更新周期时调用。
  • unbind: 只调用一次, 指令与元素解绑时调用。

钩子函数参数

钩子函数的参数有:

  • el: 指令所绑定的元素,可以用来直接操作 DOM 。

  • binding
    一个对象,包含以下属性:
    • name: 指令名,不包括 v- 前缀。
    • value: 指令的绑定值, 例如: v-my-directive="1 + 1", value 的值是 2
    • oldValue: 指令绑定的前一个值,仅在 updatecomponentUpdated 钩子中可用。无论值是否改变都可用。
    • expression: 绑定值的表达式或变量名。 例如 v-my-directive="1 + 1" , expression 的值是 "1 + 1"
    • arg: 传给指令的参数。例如 v-my-directive:foo, arg 的值是 "foo"
    • modifiers: 一个包含修饰符的对象。 例如: v-my-directive.foo.bar, 修饰符对象 modifiers 的值是 { foo: true, bar: true }
  • vnode: Vue 编译生成的虚拟节点。

  • oldVnode: 上一个虚拟节点,仅在 updatecomponentUpdated 钩子中可用。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<script src="vue.js" type="text/javascript" charset="utf-8"></script>
	<body>
		<div id="app"  v-runoob:hello.a.b="message">
		</div>
		 
		<script>
		Vue.directive('runoob', {
		  bind: function (el, binding, vnode) {
		    var s = JSON.stringify
		    el.innerHTML =
		      'name: '       + s(binding.name) + '<br>' +
		      'value: '      + s(binding.value) + '<br>' +
		      'expression: ' + s(binding.expression) + '<br>' +
		      'argument: '   + s(binding.arg) + '<br>' +
		      'modifiers: '  + s(binding.modifiers) + '<br>' +
		      'vnode keys: ' + Object.keys(vnode).join(', ')
		  }
		})
		new Vue({
		  el: '#app',
		  data: {
		    message: '1234!'
		  }
		})
		</script>
	</body>
</html>

有时候我们不需要其他钩子函数,我们可以简写函数,如下格式:

Vue.directive('runoob', function (el, binding) {
  // 设置指令的背景颜色
  el.style.backgroundColor = binding.value.color
})

指令函数可接受所有合法的 JavaScript 表达式,以下实例传入了 JavaScript 对象:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<script src="vue.js" type="text/javascript" charset="utf-8"></script>
	<body>
		<div id="app">
		    <div v-runoob="{ color: 'green', text: '1234!' }"></div>
		</div>
		 
		<script>
		Vue.directive('runoob', function (el, binding) {
		    // 简写方式设置文本及背景颜色
		    el.innerHTML = binding.value.text
		    el.style.backgroundColor = binding.value.color
		})
		new Vue({
		  el: '#app'
		})
		</script>
	</body>
</html>

十四、Vue.js 路由

本章节我们将为大家介绍 Vue.js 路由。

Vue.js 路由允许我们通过不同的 URL 访问不同的内容。

通过 Vue.js 可以实现多视图的单页Web应用(single page web application,SPA)。

Vue.js 路由需要载入 vue-router 库

中文文档地址:vue-router文档

安装

1、直接下载 / CDN

https://unpkg.com/vue-router/dist/vue-router.js

NPM

推荐使用淘宝镜像:

cnpm install vue-router

简单实例

Vue.js + vue-router 可以很简单的实现单页应用。

是一个组件,该组件用于设置一个导航链接,切换不同 HTML 内容。 to 属性为目标地址, 即要显示的内容。

以下实例中我们将 vue-router 加进来,然后配置组件和路由映射,再告诉 vue-router 在哪里渲染它们。代码如下所示:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>
<script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script>
<script src="https://cdn.staticfile.org/vue-router/2.7.0/vue-router.min.js"></script>
</head>
<body>
<div id="app">
  <h1>Hello App!</h1>
  <p>
    <!-- 使用 router-link 组件来导航. -->
    <!-- 通过传入 `to` 属性指定链接. -->
    <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
    <router-link to="/foo">Go to Foo</router-link>
    <router-link to="/bar">Go to Bar</router-link>
  </p>
  <!-- 路由出口 -->
  <!-- 路由匹配到的组件将渲染在这里 -->
  <router-view></router-view>
</div>

<script>
// 0. 如果使用模块化机制编程,導入Vue和VueRouter,要调用 Vue.use(VueRouter)

// 1. 定义(路由)组件。
// 可以从其他文件 import 进来
const Foo = { template: '<div>foo</div>' }
const Bar = { template: '<div>bar</div>' }

// 2. 定义路由
// 每个路由应该映射一个组件。 其中"component" 可以是
// 通过 Vue.extend() 创建的组件构造器,
// 或者,只是一个组件配置对象。
// 我们晚点再讨论嵌套路由。
const routes = [
  { path: '/foo', component: Foo },
  { path: '/bar', component: Bar }
]

// 3. 创建 router 实例,然后传 `routes` 配置
// 你还可以传别的配置参数, 不过先这么简单着吧。
const router = new VueRouter({
  routes // (缩写)相当于 routes: routes
})

// 4. 创建和挂载根实例。
// 记得要通过 router 配置参数注入路由,
// 从而让整个应用都有路由功能
const app = new Vue({
  router
}).$mount('#app')

// 现在,应用已经启动了!
</script>
</body>
</html>

点击过的导航链接都会加上样式 class ="router-link-exact-active router-link-active"


相关属性

接下来我们可以了解下更多关于 的属性。

to

表示目标路由的链接。 当被点击后,内部会立刻把 to 的值传到 router.push(),所以这个值可以是一个字符串或者是描述目标位置的对象。

<!-- 字符串 -->
<router-link to="home">Home</router-link>
<!-- 渲染结果 -->
<a href="home">Home</a>

<!-- 使用 v-bind 的 JS 表达式 -->
<router-link v-bind:to="'home'">Home</router-link>

<!-- 不写 v-bind 也可以,就像绑定别的属性一样 -->
<router-link :to="'home'">Home</router-link>

<!-- 同上 -->
<router-link :to="{ path: 'home' }">Home</router-link>

<!-- 命名的路由 -->
<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>

<!-- 带查询参数,下面的结果为 /register?plan=private -->
<router-link :to="{ path: 'register', query: { plan: 'private' }}">Register</router-link>

replace

设置 replace 属性的话,当点击时,会调用 router.replace() 而不是 router.push(),导航后不会留下 history 记录。

<router-link :to="{ path: '/abc'}" replace></router-link>

append

设置 append 属性后,则在当前 (相对) 路径前添加其路径。例如,我们从 /a 导航到一个相对路径 b,如果没有配置 append,则路径为 /b,如果配了,则为 /a/b

<router-link :to="{ path: 'relative/path'}" append></router-link>

tag

有时候想要 <router-link> 渲染成某种标签,例如 <li>。 于是我们使用 tag prop 类指定何种标签,同样它还是会监听点击,触发导航。

<router-link to="/foo" tag="li">foo</router-link>
<!-- 渲染结果 -->
<li>foo</li>

active-class

设置 链接激活时使用的 CSS 类名。可以通过以下代码来替代。

<style>
   ._active{
      background-color : red;
   }
</style>
<p>
   <router-link v-bind:to = "{ path: '/route1'}" active-class = "_active">Router Link 1</router-link>
   <router-link v-bind:to = "{ path: '/route2'}" tag = "span">Router Link 2</router-link>
</p>

注意这里 class 使用 active-class="_active"

exact-active-class

配置当链接被精确匹配的时候应该激活的 class。可以通过以下代码来替代。

<p>
   <router-link v-bind:to = "{ path: '/route1'}" exact-active-class = "_active">Router Link 1</router-link>
   <router-link v-bind:to = "{ path: '/route2'}" tag = "span">Router Link 2</router-link>
</p>

event

声明可以用来触发导航的事件。可以是一个字符串或是一个包含字符串的数组。

<router-link v-bind:to = "{ path: '/route1'}" event = "mouseover">Router Link 1</router-link>

以上代码设置了 event 为 mouseover ,及在鼠标移动到 Router Link 1 上时导航的 HTML 内容会发生改变。

posted @ 2022-06-23 20:09  bingbingge  阅读(174)  评论(0)    收藏  举报