Vue的指令系统、计算属性和表单输入绑定

指令系统

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

1.条件渲染:v-if

<p v-if="seen">现在你看到我了</p>

这里,v-if 指令将根据表达式 seen 的值的真假来插入/移除 <p> 元素

2.事件绑定:v-bind

一些指令能够接收一个“参数”,在指令名称之后以冒号表示。例如,v-bind 指令可以用于响应式地更新 HTML 特性:

<a v-bind:href="url">...</a>

在这里 href 是参数,告知 v-bind 指令将该元素的 href 特性与表达式 url 的值绑定。

3.监听事件:v-on

另一个例子是 v-on 指令,它用于监听 DOM 事件:

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

在这里参数是监听的事件名。我们也会更详细地讨论事件处理。

4.v-bind和v-on的缩写

 v-bind 渐变写法 : 
<!-- 完整语法 -->
<a v-bind:href="url">...</a>

<!-- 缩写 -->
<a :href="url">...</a>
 v-on 简便写法 @click
<!-- 完整语法 -->
<a v-on:click="doSomething">...</a>

<!-- 缩写 -->
<a @click="doSomething">...</a>

5. 列表渲染:v-for

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

<ul id="example-1">
  <li v-for="item in items">
    {{ item.message }}
  </li>
</ul>
var example1 = new Vue({
  el: '#example-1',
  data: {
    items: [
      { message: 'Foo' },
      { message: 'Bar' }
    ]
  }
})

结果:

  • Foo
  • Bar
你也可以用 of 替代 in 作为分隔符,因为它是最接近 JavaScript 迭代器的语法:

<div v-for="item of items"></div>

6.v-show

   另一个用于根据条件展示元素的选项是 v-show 指令。用法大致一样:

<h1 v-show="ok">Hello!</h1>

注意,v-show 不支持 <template> 元素,也不支持 v-else。不同的是带有 v-show 的元素始终会被渲染并保留在 DOM 中。v-show 只是简单地切换元素的 CSS 属性 display

7. v-if vs v-show

v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。

v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。

相比之下,v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。

一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。
 

8.v-html:模板渲染

<div id="app">
	 <div v-html='str'></div>
</div>


var app = new Vue({
        el:'#app',
	    data:{
	        str:'<p>嘿嘿嘿</p>',
	    },
}

指令系统、对象的单体模式、vue的生命周期练习、轮播图示例

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <style>
    	*{
    		margin: 0;
    		padding:0;
    	}
    	#app{
    		 600px;
    		margin: 100px auto;
    	}
    	.box{
    		 100px;
    		height:100px;
    		background-color: red;
    	}
    	.box2{
    		background-color: green;
    	}
    	.box3{
    		background-color: yellow;
    	}
		ul{
			 180px;
			list-style: none;
			overflow: hidden;
		}
		ul li{
			background-color: purple;
			margin-left: 10px;
			float: left;
			 30px;
			height: 30px;
			text-align: center;
			color: white;
		}

    </style>
    <title>Document</title>
</head>
<body>
<div id="app">
    <!-- 插值语法 react {} angular {{}} {%%} <%%> -->
    <h3>{{msg}}</h3>
    <h3>{{1>2?"真的":"假的"}}</h3>
    <h3>{{1+1}}</h3>
    <div v-if="show">哈哈指令系统</div>
    <div v-if="Math.random()>0.5">
        Now you see me
    </div>
    <div v-else-if="Math.random()>0.3">
        Now you do
    </div>
    <div v-else>
        Now you don't
    </div>
	
	<h3 v-show="isShow" v-bind:title='title'>这是一个三级标题</h3>

	<img v-bind:src="imgSrc" v-bind:alt="time">

	<!-- v-bind 渐变写法 : -->
	<!-- v-on 简便写法 @click -->

    <button v-on:click="clickHandler">切换</button>

	<div class="box" :class="{box2:isGreen,box3:isYellow}"></div>
    <button @click="changeColor">切换颜色</button>

	<button @click='count+=1'>加{{count}}</button>
	
	<!-- 
	声明式的指令
	命令式
	 -->

	 <div class="lunbo">
	 	<img :src="currentSrc" alt="" @mouseenter='closeTimer' @mouseleave='openTimer'>

	 	<ul>
	 		<li v-for="(item,index) in imgArr" @click='currentHandler(item)'>{{index+1}}</li>
	 	</ul>
	 	<button @click="lastImg">上一张</button>
	 	<button @click="nextImg">下一张</button>
	 </div>
	 <div v-html='str'></div>
</div>



<script src="vue.js"></script>
<script type="text/javascript">
    // vue的实例化对象
    // MVVM Model View ViewModel

    // MTV Model Template View
    
    // 指令系统

    // 核心思想概念:数据驱动视图

    var app = new Vue({
        el:'#app',
	    data:{
	        msg:'今天学习vue',
	        msg2:'今天学vue2',
	        title:'三级标题',
	        show:false,
	        isShow:true,
	        imgSrc:'石原.jpg',
	        time:`页面加载于${new Date().toLocaleString()}`,
	        isGreen:false,
	        isYellow:false,
	        count:0,
	        currentSrc:'1.jpg',
	        imgArr:[
	        	{'id':1,'src':'1.jpg'},
	        	{'id':2,'src':'2.jpg'},
	        	{'id':3,'src':'3.jpg'},
	        	{'id':4,'src':'4.jpg'},
	        ],
	        currentIndex:0,
	        timer: null,
	        str:'<p>嘿嘿嘿</p>',
	    },
	    created(){
	    	// 提前获取cookie和session
            this.timer = setInterval(this.nextImg,2000)
            },

        methods:{
            // 对象的单体模式
            // clickHandler:function(){
            clickHandler(){
                // alert('111')
                console.log(this);
                this.show = !this.show;
            },
            changeColor(){
            	this.isGreen = !this.isGreen
            },
            currentHandler(item){
            	this.currentSrc = item.src
            },
            nextImg(){
            	if (this.currentIndex == this.imgArr.length) {
            		this.currentIndex=1
            	}else{
            	this.currentIndex++;
            	}
            	console.log(this.currentIndex, this.imgArr.length);
            	this.currentSrc = this.imgArr[this.currentIndex-1].src
            },
            lastImg(){
            	if (this.currentIndex == 1) {
            		this.currentIndex=this.imgArr.length
            	}else{
            	this.currentIndex--;
            }
            	this.currentSrc = this.imgArr[this.currentIndex-1].src
            },
            closeTimer(){
            	clearInterval(this.timer)
            },
            openTimer(){
	            this.timer = setInterval(this.nextImg,2000)
            }

        }
    })
    console.log(app);
    console.log(app.$data.msg);
    console.log(app.msg);

</script>
</body>
</html>

  

计算属性

你可能已经注意到我们可以通过在表达式中调用方法来达到同样的效果:

<p>Reversed message: "{{ reversedMessage() }}"</p>
  // 在组件中
methods: {
  reversedMessage: function () {
    return this.message.split('').reverse().join('')
  }
}

这也同样意味着下面的计算属性将不再更新,因为 Date.now() 不是响应式依赖:我们可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。然而,不同的是计算属性是基于它们的依赖进行缓存的。只在相关依赖发生改变时它们才会重新求值。这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。

computed: {
  now: function () {
    return Date.now()
  }
}

我们为什么需要缓存?假设我们有一个性能开销比较大的计算属性 A,它需要遍历一个巨大的数组并做大量的计算。然后我们可能有其他的计算属性依赖于 A 。如果没有缓存,我们将不可避免的多次执行 A 的 getter!如果你不希望有缓存,请用方法来替相比之下,每当触发重新渲染时,调用方法将总会再次执行函数。

<div id="computed">
	<div>
	<!-- 字符串反转 -->
	<!-- {{msg.split('').reverse().join('')}} -->
	{{reverseStr}}
	</div>
	<button @click="clickHandler">修改</button>

</div>

<script type="text/javascript" src="vue.js"></script>
<script type="text/javascript">
	var com = new Vue({
		el:'#computed',
		data:{
			msg:'hello world',
		},
		methods:{
			clickHandler(){
				// this.msg = 'hello zhangyafei'
				console.log(this.reverseStr);
				this.reverseStr = 'hello zhangyafei'
			}
		},
		computed:{
			// 默认只有getattr方法
			// reverseStr(){
			// 	return this.msg.split('').reverse().join('');
			// }
			// set方法
			reverseStr:{
				set:function(newValue){
					this.msg = newValue
				},
				get:function(){
					return this.msg.split('').reverse().join('')
				}
			}
		}
	})

</script> 

表单输入绑定

表单输入绑定的应用

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
</head>
<body>
	<form id="computed" @submit.prevent>
		<!-- 双向绑定 -->
		文本
		<input type="text" name="" v-model='msg'>
		<!-- <input type="text" v-bind:value='getValue' @input='msgChange'> -->
		<input type="text" v-model.lazy='msg'>
		<input type="number" v-model.number='msg'>
		<br>
		多行文本
		<textarea v-model="msg" placeholder="add multiple lines"></textarea>
		</br>
		<input type="submit" name="" value="提交">
		<h3>{{msg}}</h3>
	<div>单选框<br>
		<input type="checkbox" id="checkbox" v-model="checked">
		<label for="checkbox">{{ checked }}</label>
</div>
	<div> 多选框<br>
		<input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
		  <label for="jack">Jack</label>
		  <input type="checkbox" id="john" value="John" v-model="checkedNames">
		  <label for="john">John</label>
		  <input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
		  <label for="mike">Mike</label>
		  <br>
		  <span>Checked names: {{ checkedNames }}</span>
	</div>

	<div id="example-4">单选按钮<br>
  <input type="radio" id="one" value="One" v-model="picked">
  <label for="one">One</label>
  <br>
  <input type="radio" id="two" value="Two" v-model="picked">
  <label for="two">Two</label>
  <br>
  <span>Picked: {{ picked }}</span>
</div>

<div id="example-5">选择下拉框<br>
  <select v-model="selected">
    <option disabled value="">请选择</option>
    <option>A</option>
    <option>B</option>
    <option>C</option>
  </select>
  <span>Selected: {{ selected }}</span>
</div>

<div id="example-6"> 多选情况<br>
  <select v-model="mul_selected" multiple style=" 50px;">
    <option>A</option>
    <option>B</option>
    <option>C</option>
  </select>
  <br>
  <span>Selected: {{ mul_selected }}</span>
</div>

<select v-model="for_selected">v-for渲染的动态情况<br>
  <option v-for="option in options" v-bind:value="option.value">
    {{ option.text }}
  </option>
</select>
<span>Selected: {{ for_selected }}</span>

	</form>
	
	<script type="text/javascript" src="vue.js"></script>
	<script type="text/javascript">
		var com = new Vue({
			el:'#computed',
			data:{
				msg:'123',
				checked:false,
				checkedNames:[],
				picked:'',
				selected:'',
				for_selected:'',
				mul_selected:'',
				options: [
			      { text: 'One', value: 'A' },
			      { text: 'Two', value: 'B' },
			      { text: 'Three', value: 'C' }
			    ],
			},
			methods:{
				msgChange(e){
					console.log(e.target.value)
					this.getValue = e.target.value;
				}
				// $.ajax() xmlhttpRequest 
			},
			computed:{
				getValue:{
					set:function(newValue){
						self.msg = newValue;
					},
					get:function(){
						return self.msg
					}
				}
			}
		})

	</script>
</body>
</html>

 

更多内容请访问:https://cn.vuejs.org/v2/guide/forms.html

原文地址:https://www.cnblogs.com/zhangyafei/p/10270903.html