vue模板语法
本章主要包含以下知识点:
1:插值
(1)文本
(2)原始HTML
(3)特性
(4)动态参数
(5)缩写
2:计算属性和侦听器
(1)计算属性
(1-1)计算属性缓存 和方法对比
(1-2)计算属性的setter
(2)数据观察
插值:
(1)文本
文本插值是最基本的渲染方式,数据是什么样的,渲染在页面中就是什么样的
<body>
<div id="app">
<p>my name is {{ name }}</p>
<p v-once>my name is {{ name }}</p>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
name: 'mulian'
}
})
</script>
</body>
Vue 还提供了一个 v-cloak 指令,用于控制数据还未渲染出来时,是否显示未渲染的临时内容。
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
[v-cloak] {
display: none;
}
</style>
</head>
<body>
<!-- 当网速慢速时不会显示 {{ mess }},但是要和 display:none 配合使用,不然还是会显示 {{ mess }} -->
<div id="app" v-cloak>
{{ mess }}
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
mess: '这是临时内容'
}
});
</script>
</body>
(2)原始HTML
如果要渲染的数据含有 html 标签,在渲染的时候也会原样输出。如果要作为 html 代码进行渲染,可以添加指令 v-html
<body>
<div id="app">
<!-- 第一行会原样输出 , 第二行可以作为 HTML 渲染出来 -->
<div>{{htmlCode}}</div>
<div v-html="htmlCode"></div>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
htmlCode: '<span style="color:red">this is a test</span>'
}
})
</script>
</body>
(3)特性
特性,又被称之为属性。我们知道,一个 html 标签可以含有多个属性,如果需要将属性和 data 数据进行绑定,达到通过 data 数据来控制属性值的话,可以使用 v-bind 指令进行属性的绑定。
<body>
<div id="app">
<div v-bind:title="one" v-bind:class="two">动态绑定属性</div>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
one: 'this is a title',
two: 'topContent abc'
}
})
</script>
</body>
(4)动态参数
从 2.6.0 开始,可以用方括号括起来的 JavaScript 表达式作为一个动态参数,这样就增大了属性或者事件的灵活性。
<body>
<div id="app">
<!-- 这里为 span 绑定了一个动态事件 , 具体是什么事件取决于 abc 的值 -->
<span v-on:[abc]="test2">动态参数</span>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
abc: 'mouseenter'
}
})
</script>
</body>
如上例所示,动态参数 abc 的值决定了绑定的事件具体是什么,增加代码的灵活性。
(5)缩写
由于绑定属性和事件的使用率很高,所以在 Vue 中提供了对应的缩写方式。
v-bind 的缩写:
<body>
<div id="app">
<!-- v-bind:属性名 的缩写方式为 :属性名 -->
<div v-bind:title="one" :class="two">动态绑定属性</div>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
one: 'this is a title',
two: 'topContent abc'
}
})
</script>
</body>
v-on 的缩写:
<body>
<div id="app">
<p v-on:click="one" @mouseenter="two">this is a test</p>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
const app = new Vue({
el: '#app',
methods: {
one: function () {
console.log('这是正常的事件绑定。');
},
two() {
console.log('这是缩写形式的事件绑定');
}
}
});
</script>
</body>
2:计算属性和侦听器
(1)计算属性
模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。
<div id="example">
{{ message.split('').reverse().join('') }}
</div>
所以对于任何复杂逻辑,都应该使用计算属性
计算属性对应的数据选项为 computed,类似于 data,只不过 data 对应的是一个值,而计算属性对应的是一个方法。在方法里面就可以书写复杂的计算,然后将结果进行返回。
计算属性的值依赖于数据,如果数据发生变化,计算属性也会发生变化
<body>
<div id="app">
<p>{{ message }}</p>
<!-- Hello Vue! -->
<p>{{ reverseMess }}</p>
<!-- !euV olleH -->
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
const data = {
message: 'Hello Vue!'
}
const vm = new Vue({
el: '#app',
data: data,
computed: {
reverseMess: function () {
return this.message.split('').reverse().join('')
}
}
});
</script>
</body>
(1-1)计算属性缓存 和方法对比
在 Vue 的实例中,还存在一个数据选项 methods,用来书写方法。
如果把上面的例子由计算属性修改为方法:
<body>
<div id="app">
<p>{{ message }}</p>
<!-- Hello Vue! -->
<p>{{ reverseMess() }}</p>
<!-- !euV olleH -->
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
const data = {
message: 'Hello Vue!'
}
const vm = new Vue({
el: '#app',
data: data,
methods: {
reverseMess: function () {
return this.message.split('').reverse().join('')
}
}
});
</script>
</body>
计算属性和方法给人的感觉就像是同一个东西
但是,计算属性只有在它的相关依赖发生改变时才会重新求值,而方法,只要发生重新渲染,methods调用会执行所有函数
<body>
<div id="example">
<button v-on:click="a++">A++</button>
<button v-on:click="b++">B++</button>
<!-- computedA 计算属性依赖于数据 a , 当 a 的值发生变化时 , computedA 会重新进行计算 -->
<p>{{ computedA }}</p>
<!-- computedB 计算属性依赖于数据 b , 当 b 的值发生变化时 , computedB 会重新进行计算 -->
<p>{{ computedB }}</p>
<!-- 只要发生重新渲染 , 所有函数就会被执行 -->
<p>{{ methodA() }}</p>
<p>{{ methodB() }}</p>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
const vm = new Vue({
el: '#example',
data: {
a: 1,
b: 1
},
computed: {
computedA: function () {
console.log('computedA has done');
return this.a;
},
computedB: function () {
console.log('computedB has done');
return this.b;
}
},
methods: {
methodA: function () {
console.log('methodA has done');
return this.a;
},
methodB: function () {
console.log('methodB has done');
return this.b;
}
}
});
</script>
</body>
所以两者的区别就在于如果有一个遍历极大的数组和大量的计算时用计算属性computed来返回结果,就算其他地方发生了局部渲染,也不会影响computed计算属性的值,不用再进行计算,如果性能消耗不大,不希望存在缓存,就用methods方法来返回结果
(1-2)计算属性的setter
计算属性提供一个 getter 即可,也就是模板中直接获取计算属性的值。但是如果涉及到要设置计算属性的值的话,也可以给计算属性设置一个 setter,在 setter 中来对计算属性设置时进行一定的限制。
<body>
<!-- 一般来讲 , 我们只会获取计算属性的值 , 如果要设置计算属性的值 , 可以为计算属性设置一个 setter -->
<div id="app">
<!-- fullname 为一个计算属性 -->
<p>你的全名为:{{fullName}}</p>
<!-- xing 和 ming 为数据 -->
<p>你的姓氏为:{{xing}}</p>
<p>你的名字为:{{ming}}</p>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
const vm = new Vue({
el: '#app',
data: {
xing: 'mu',
ming: ' lian'
},
computed: {
// 注意使用 getter 和 setter 的时候,fullName 对应一个对象,而不再是一个函数
// get 或者 set 属性对应的才是一个函数
fullName: {
// getter 用于读取的时候
get: function () {
return this.xing + this.ming;
},
// setter 写入时触发
// 例如在浏览器控制台执行 vm.fullName = 'song ya jing' , 这里就是对计算属性进行了值的设定
set: function (value) {
// 根据新设置的姓名来给 firstName 和 lastName 进行赋值
const newName = value.split(' ');
this.xing = newName[0]; // song
this.ming = ' '; // 首先重置this.ming,注意有一个空格
// 通过for循环将newName剩余的元素拼接到名字里面
for (let i = 1; i < newName.length; i++) {
this.ming += newName[i] + ' ';
}
}
}
}
});
</script>
</body>
数据观察
Vue 提供了一个 watch 数据选项来观察和响应 data 数据的变动。watch 对象的键是需要观察的 data 数据,值对应一个回调函数,回调函数得到的参数为新值和旧值。
<body>
<div id="app">
<button @click="a++">a加1</button>
<p>当前 a 的值为:{{ a }}</p>
<p>{{ message }}</p>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
const vm = new Vue({
el: '#app',
data: {
a: 1,
message: ''
},
watch: {
// 对 data 数据中的 a 进行监控
// 发生改变时 , 新值和旧值会传入回调函数
a: function (val, oldVal) {
this.message = 'a的旧值为' + oldVal + ',新值为' + val;
}
}
})
</script>
</body>
除了 watch 数据选项以外,实例对象的 $watch 方法也可以监听 data 数据的改变。
<body>
<div id="app">
<button @click="a++">a加1</button>
<p>当前a的值:{{a}}</p>
<p>{{ message }}</p>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
const vm = new Vue({
el: '#app',
data: {
a: 1,
message: ''
}
});
// 实例对象的 $watch 方法也可以监听 data 数据的改变
// 将新值和旧值传入到回调函数里面
vm.$watch('a', function (val, oldVal) {
this.message = 'a的旧值为' + oldVal + ',新值为' + val;
})
</script>
</body>
watch 数据选项和 $watch 都可以实现对 data 数据的监听,但是还是有一定的区别。
$watch 方法会返回一个取消观察函数,用来停止触发回调。
<body>
<div id="app">
<button @click="a++">a加1</button>
<p>当前a的值:{{a}}</p>
<p>{{ message }}</p>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
const vm = new Vue({
el: '#app',
data: {
a: 1,
message: ''
}
});
// 实例对象的 $watch 方法也可以监听 data 数据的改变
// 将新值和旧值传入到回调函数里面
// $watch 会返回一个函数 , 调用该函数可以取消观察
const unwatch = vm.$watch('a', function (val, oldVal) {
if (val === 10) {
unwatch(); // 执行函数取消观察
}
this.message = 'a的旧值为' + oldVal + ',新值为' + val;
})
</script>
</body>