Vue指令学习(v-for、v-cloak、自定义指令...)

Vue是什么?

Vue是一套用于构建用户界面的渐进式的MVVM框架,另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。

指令

指令 (Directives) 是带有 v- 前缀的特殊特性。指令特性的值预期是单个 JavaScript 表达式 (v-for 是例外情况)。指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM。

vue起步

下载vue

git clone https://github.com/vuejs/vue-syntax-highlight

vue实例

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Vue指令学习</title>
	<script src="vue.min.js"></script>
</head>
<body>
	<div id="app">
		<h1>{{msg}}</h1>
		<input type="text" v-bind:[]>
	</div>
</body>
<script src="vue.min.js"></script>
<script>
	var vm = new Vue({
		el:'#app',
		data:{
			msg:'一起学习vue指令'
		},
		methods:{

		}
	})
</script>
</html>

文章最后有代码和一些案例(隔行变色,搜索功能,文字滚动-跑马灯)代码

v-bind

  1. v-bind 指令可以用于响应式地更新 HTML 特性
  2. 将该元素的 属性特性与表达式 的值绑定。
  3. data数据
data:{
			msg:'一起学习vue指令',
			bind1:'使用v-bind指令'
		}
  1. #app容器里面放入
<input type="text" v-bind:value="bind1">
  1. 使用v-bind绑定属性,可以简写为一个冒号’:’
    app容器
<a :href="url">链接</a>

data数据

url:'https://blog.csdn.net/weixin_41105030'

v-cloak

使用 v-cloak 能够解决 插值表达式闪烁的问题

  1. 在app容器里面放入
<p>++++++++ {{ msg }} ----------</p>

结果把我们的插值表达式也显示出来了如下图浏览器刚渲染部分截图(浏览器可以把网速限制以便观察),然后才会渲染我们的数据
显示插值表达式
接着我们使用v-cloak,在style引入(这样p段落的内容都不会显示,直到插值表达式解析出来,解决了闪烁问题)

<p v-cloak>++++++++ {{ msg }} ----------</p>
 <style>
  [v-cloak] {
     display: none;
  }
</style>

v-text和v-html

  1. v-text和v-html 是没有闪烁问题的
  2. 会覆盖元素中原本的内容,只会替换自己的占位符,不会把整个元素的内容清空
<div v-text="msg2">122233</div>
<div v-html="msg2">1212112</div>
msg2:'<h2>使用v-html和v-text解析我的区别</h2>'
  1. 跟jquery的.html()和.text()一样的解析,v-html会解析html标签

v-on

它用于监听 DOM 事件,可以简写为合法字符@

  1. 在id为app的div里面放入
<!-- 完整语法 -->
<button v-on:click='handle'>v-on指令</button>
  1. 在methods方法里面放入
handle:function(){
				console.log('success')
}
  1. 缩写语法
<button @click='handle'>v-on</button>

v-model

  1. v-bind只能实现数据的单向绑定,从model到view
    在input后面插入一个p元素
<input type="text" v-bind:value="bind1">
<p>{{bind1}}</p>

我们怎么改变input的值,p段落都不变
效果
3. v-model 指令,可以实现数据的双向数据绑定
使用v-model,实现表单元素与model(data)层双向绑定

<p>{{bind1}}</p>
<!-- 在p元素放入使用v-model指令的p元素 -->
<input type="text" v-model="bind1">

改变输入框,效果如图

v-for

我们用 v-for 指令根据一组数组的选项列表进行渲染。v-for 指令需要使用 item in items 形式的特殊语法,items 是源数据数组并且 item 是数组元素迭代的别名。

  1. 新建一个新的容器(创建vue实例)
<div id="app1">
		<h1>{{msg}}</h1>
</div>
var vm1 = new Vue({
		el:'#app1',
		data:{
			msg: 'v-for循环指令',
			list: [1, 2, 3, 4, 5, 6],
			list1:[
	          { id: 1, name: 'zs1' },
	          { id: 2, name: 'zs2' },
	          { id: 3, name: 'zs3' },
	          { id: 4, name: 'zs4' }
	        ],
	        list2: {
	          id: 1,
	          name: '哈哈',
	          gender: '男'
	        }
		},
		methods:{

		}
	})
  1. v-for循环data数据的普通数组list
    在app1的容器进行循环
<p v-for="(item,i) in list">第{{i+1}}个索引的值是:{{item}}</p>
  1. v-for循环data数据的对象数组list1
<table border="1" cellpadding="0" cellspacing="0">
			<thead>
				<tr>
					<td>id</td>
					<td>name</td>
				</tr>
			</thead>
			<tbody>
				<!-- 可以和上面一样加入索引 -->
				<tr v-for="item in list1">
					<td>{{item.id}}</td>
					<td>{{item.name}}</td>
				</tr>
			</tbody>
		</table>
  1. v-for循环data数据的对象list2
<!-- 除了键值,第三个位置还有索引 -->
		<p v-for="(val, key, i) in list2">键是:{{key}},值是:{{val}},索引是:{{i}}</p>
  1. v-for迭代数字
<!-- 从1开始而不是从0 -->
		<ul>
			<li v-for="num in 10">第{{num}}li</li>
		</ul>

部分截图
6. 技巧:使用v-for循环methods的数据

<p v-for="(item,i) in circulation()">使用methods:第{{i+1}}个索引的值是:{{item}}</p>
methods:{
			circulation(){
				return this.list
			}
		}
  1. :key
    组件中,使用v-for循环的时候,或者在一些特殊情况中,如果 v-for 有问题,必须 在使用 v-for 的同时,指定 唯一的 字符串/数字 类型 :key 值
<div v-for="item in items" :key="item.id">
  <!-- 内容 -->
</div>

当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。建议尽可能在使用 v-for 时提供 key

v-if、 v-show、v-else

  1. v-if 的特点:每次都会重新删除或创建元素
  2. v-show 的特点: 每次不会重新进行DOM的删除和创建操作,只是切换了元素的 display:none 样式
  3. v-if 有较高的切换性能消耗
  4. v-show 有较高的初始渲染消耗
  5. 如果元素涉及到频繁的切换,最好不要使用 v-if, 而是推荐使用 v-show
  6. 如果元素可能永远也不会被显示出来被用户看到,则推荐使用 v-if
<div id="app2">
		<h2>{{msg}}</h2>
		<div v-show='flag'>v-show指令</div>
		<div v-if='flag'>v-if指令</div>
		<div v-else='flag'>v-else指令</div>
		<!-- v-else紧跟在v-if或者v-show后边,否则将不被识别 -->
		<button @click='flag=!flag'>切换</button>
	</div>
var vm2 = new Vue({
		el:'#app2',
		data:{
			msg:'v-if,v-show,v-else,v-hide',
			flag:true,
		},
		methods:{

		}
	})

操作
可以查看一下elements

自定义指令

除了核心功能默认内置的指令 (v-model 和 v-show),Vue 也允许注册自定义指令。注意,在 Vue2.0 中,代码复用和抽象的主要形式是组件。然而,有的情况下,你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令。

全局指令
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>自定义指令</title>
	<script src="vue.min.js"></script>
</head>
<body>
	<div id="app">
		<input type="text" width="300px" v-focus>
	</div>
</body>
<script>
	// Vue.directive()定义全局的指令,聚焦输入框
	// 1.参数一:指令的名称,在定义的时候,指令的名称前面,不需要加 v- 前缀,在调用的时候,必须在指令名称前 加上 v- 前缀来进行调用、
	// 2.参数二:是一个对象,有一些指令相关的函数,这些函数可以在特定的阶段,执行相关的操作
	Vue.directive('focus',{
		bind:function(el){
			el.style.color = 'red'
		},
		inserted:function(el){
			el.focus()
		}
	})
	var vm = new Vue({
		el:'#app',
		data:{

		},
		methods:{

		}
	})
</script>
</html>
  1. Vue.directvie(指令名称,对象)定义全局指令,注意directive是没有s的,局部指令才有
    效果
  2. 钩子函数
    bind

只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。

如果在bind使用聚焦输入框,刷新浏览器会发生并没有生效

bind:function(el){
			el.focus()
			el.style.color = 'red'
		},
		inserted:function(ele){
			// ele.focus()
		}

因为:每当指令绑定到元素上的时候,会立即执行这个 bind 函数,只执行一次,但还没有 插入到 DOM中去,这时候,调用 focus 方法没有作用。只有在dom插入了input节点之后,才会聚焦
?为什么在bind使用‘el.style.color = ‘red’’
和样式相关的操作,一般都可以在 bind 执行:只要通过指令绑定给了元素,不管这个元素有没有被插入到页面中去,这个元素肯定有了一个内联的样式。浏览器的渲染引擎必然会解析样式,应用给这个元素


inserted

被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。

update
当VNode(Vue 编译生成的虚拟节点)更新的时候,会执行 updated, 可能会触发多次
componentUpdated
指令所在组件的 VNode 及其子 VNode 全部更新后调用。
unbind
只调用一次,指令与元素解绑时调用。


  1. 在每个 函数中,第一个参数,永远是 el ,表示 被绑定了指令的那个元素,这个 el 参数,是一个原生的JS对象,当然,也可以写成ele等别名,但第一个表示被绑定的dom对象
inserted:function(ele){
			ele.focus()
}
  1. 先了解下钩子函数的参数
  • el:指令所绑定的元素,可以用来直接操作 DOM 。
  • binding:一个对象
  • vnode:Vue 编译生成的虚拟节点。
  • oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
局部指令了解钩子函数的参数
<p v-size='"50px"'>这是用来使用私有指令的</p>
var vm = new Vue({
		el:'#app',
		data:{

		},
		methods:{

		},
		directives:{//自定义私有指令
			'size':{
				bind(el,binding){
					el.style.fontSize = binding.value
					console.log(binding)
				}
			}
		}
	})

页面显示和结果打印
打印是binding包含的属性(有些只能在其他钩子函数可用):

  • name:指令名,可以看出不包括 v- 前缀。
  • value:指令的绑定值,可以像v-html、v-if等放一个插值表达式
  • modifiers:一个包含修饰符的对象。
  • oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
  • arg:传给指令的参数
  • expression:字符串形式的指令表达式
全局指令和局部指令的缩写

在 bind 和 update 时触发相同行为,而不关心其它的钩子,可以将对象改为function;这个 function 等同于 把 代码写到了 bind 和 update 中去

Vue.directive('color-swatch', function (el, binding) {
  el.style.backgroundColor = binding.value
})
directives:{
'fontsize': function (el, binding) { 
          el.style.fontSize = parseInt(binding.value) + 'px'
        }
}

跑马灯案例(这里使用vue组件)

<template>
	<div>
		<button @click="lang">跑起来</button>
		<button @click="stop">停止</button>
		<p>{{msg}}</p>
	</div>
</template>
<script>
export default{
	// data必须是一个function
	data(){
		return{
			msg:"这是vue跑马灯案例,让文字跑起来",
			timer:null
		}
	},
	methods:{
		// 1.两个按钮:一个点击跑动
		// 2.一个点击停止
		// 3.点击跑动:开启定时器;每次将第一个字放在最后
		lang(){
			if(this.timer!=null) return;
			this.timer = setInterval(()=>{
				// 改为箭头函数,或则使用bind改变this指向
				var langArr = this.msg.split('')
				var arrOne = langArr.splice(0,1)
				langArr.push(arrOne)
				this.msg = langArr.join('')
				// 这里使用数组,或则使用substring
			},500)
		},
		stop(){
			clearInterval(this.timer)
			this.timer = null
		}
	}
};
</script>
<style lang="less">
	div{
		p{
			color: red;
			width: 180px;
			white-space: nowrap;
			overflow: hidden;
		}
	}
</style>

搜索功能案例(使用bootstrap)

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
	<script src="vue.min.js"></script>
	<link rel="stylesheet" href="bootstrap.css">
	<title>search</title>
</head>
<body>
<div id="app">
	<div class="container" :style="{paddingTop:'30px'}">
		<div class="form-group">
		    <input type="search" class="form-control" placeholder="搜索" :style="{textAlign:'center'}" v-model="keywords">
		 </div>
		 <table class="table table-bordered text-center">
	  		<thead>
	  			<tr>
	  				<td>id</td>
	  				<td>name</td>
	  			</tr>
	  		</thead>
	  		<tbody>
	  			<tr v-for="item in search(keywords)">
	  				<td>{{item.id}}</td>
	  				<td>{{item.name}}</td>
	  			</tr>
	  		</tbody>
		</table>
	</div>
</div>
</body>
<script>
	var vm = new Vue({
		el:'#app',
		data:{
			keywords:'',
			list:[
				{ id: 1, name: '奔驰' },
          		{ id: 2, name: '宝马'},
          		{ id: 3, name: '劳斯莱斯'},
          		{ id: 4, name: '悍马'},
          		{ id: 5, name: '捷豹'},
          		{ id: 6, name: '路虎'},
          		{ id: 7, name: '本田'},
          		{ id: 8, name: '保时捷'},
			]
		},
		methods:{
			search(keywords){
				let newList = this.list.filter((item)=>{
					return item.name.includes(keywords)
				})
				return newList
			}
		}
	})
</script>
</html>

search

class实现隔行变色(使用v-bind绑定class)

将上面的tbody>tr改为一个三元表达式,即可实现隔行变色,success是bootstrap为我们提供的类

<tr v-for="(item,i) in search(keywords)" :class="i%2==0?'':'success'">

指令的代码整合

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Vue指令学习</title>
	<script src="vue.min.js"></script>
</head>
<body>
	<div id="app">
		<h1>{{msg}}</h1>
		<input type="text" v-bind:value="bind1">
		<!-- 绑定了值 -->
		<p>{{bind1}}</p>
		<!-- 在p元素放入使用v-model指令的p元素 -->
		<input type="text" v-model="bind1">
		<a :href="url">链接</a>
		<p v-cloak>++++++++ {{ msg }} ----------</p>
		<div v-text="msg2">122233</div>
    	<div v-html="msg2">1212112</div>
    	<button v-on:click='handle'>v-on指令</button>
    	<button @click='handle'>v-on</button>
	</div>
	<div id="app1">
		<h1>{{msg}}</h1>
		<hr>
		<p v-for="(item,i) in list">第{{i+1}}个索引的值是:{{item}}</p>
		<table border="1" cellpadding="0" cellspacing="0">
			<thead>
				<tr>
					<td>id</td>
					<td>name</td>
				</tr>
			</thead>
			<tbody>
				<!-- 可以和上面一样加入索引 -->
				<tr v-for="item in list1">
					<td>{{item.id}}</td>
					<td>{{item.name}}</td>
				</tr>
			</tbody>
		</table>
		<!-- 除了键值,第三个位置还有索引 -->
		<p v-for="(val, key, i) in list2">键是:{{key}},值是:{{val}},索引是:{{i}}</p>
		<!-- 从1开始而不是从0 -->
		<ul>
			<li v-for="num in 10">第{{num}}li</li>
		</ul>
		<p v-for="(item,i) in circulation()">使用methods:第{{i+1}}个索引的值是:{{item}}</p>
	</div>
	<div id="app2">
		<h2>{{msg}}</h2>
		<div v-show='flag'>v-show指令</div>
		<div v-if='flag'>v-if指令</div>
		<div v-else='flag'>v-else指令</div>
		<!-- v-else紧跟在v-if或者v-show后边,否则将不被识别 -->
		<button @click='flag=!flag'>切换</button>
	</div>
</body>
<script src="vue.min.js"></script>
<script>
	var vm = new Vue({
		el:'#app',
		data:{
			msg:'一起学习vue指令',
			bind1:'使用v-bind指令',
			url:'https://blog.csdn.net/weixin_41105030',
			msg2:'<h2>使用v-html和v-text解析我的区别</h2>'
		},
		methods:{
			handle:function(){
				console.log('success')
			}
		}
	})
	var vm1 = new Vue({
		el:'#app1',
		data:{
			msg: 'v-for循环指令',
			list: [1, 2, 3, 4, 5, 6],
			list1:[
	          { id: 1, name: 'zs1' },
	          { id: 2, name: 'zs2' },
	          { id: 3, name: 'zs3' },
	          { id: 4, name: 'zs4' }
	        ],
	        list2: {
	          id: 1,
	          name: '哈哈',
	          gender: '男'
	        }
		},
		methods:{
			circulation(){
				return this.list
			}
		}
	})
	var vm2 = new Vue({
		el:'#app2',
		data:{
			msg:'v-if,v-show,v-else,v-hide',
			flag:true,
		},
		methods:{

		}
	})
</script>
</html>

猜你喜欢

转载自blog.csdn.net/weixin_41105030/article/details/87645238