# 插值语法—文本
将 data 中数据插入到 HTML 模版内容中
# Mustache 语法 🔥
Mustache 语法,双大括号
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vue</title>
</head>
<body>
<div id="app">
<h2>{{message}}</h2>
<h2>{{message}}李银河</h2>
<!-- 表达式 -->
<h2>{{lastName + firstName}}</h2>
<h2>{{lastName + " "+firstName}}</h2>
<h2>{{lastName}}@{{firstName}}</h2>
<h2>{{count*2}}</h2>
</div>
<script src="./lib/vue.js"></script>
<script>
const vm = new Vue({
el: "#app",
data: {
message: "你好!",
firstName: "三",
lastName: "张",
count: 100,
},
});
</script>
</body>
</html>
Mustache 标签将会被替代为对应 data 数据对象上属性的值。
无论何时,绑定的 data 数据对象上属性发生了改变,插值处的内容都会更新。
Mustache 中存放的是变量对象,也可以放表达式、方法(最后需带括号)(不推荐),若用引号引用则视作字符串不再解析。
# v-once 指令 🔥
只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。通过使用 v-once 指令,你也能执行一次性地插值,当数据改变时,插值处的内容不会更新。但请留心这会影响到该节点上的其它数据绑定
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Title</title>
</head>
<body>
<div id="app">
<!-- 单个元素 -->
<h2>This will change: {{message}}</h2>
<h2 v-once>This will never change: {{message}}</h2>
<!-- 有子元素 -->
<div>
<h2>{{message}}</h2>
</div>
<div v-once>
<h2>{{message}}</h2>
</div>
<!-- 组件 -->
<my-component v-once :comment="message"></my-component>
<my-component :comment="message"></my-component>
<!-- `v-for` 指令-->
<ul>
<li v-for="i in list" :key="i">{{i}}</li>
</ul>
<ul>
<li v-for="i in list" :key="i" v-once>{{i}}</li>
</ul>
</div>
<script src="/lib/vue.js"></script>
<script>
// 这里写的组件必须在 new Vue() 前定义!
Vue.component("my-component", {
data: function () {
return {
count: 0,
};
},
props: {
comment: "",
},
template: "<h1>{{comment}} my-component</h1>",
});
const vm = new Vue({
el: "#app",
data: {
message: "Test 1",
list: [1, 2, 3],
},
methods: {},
});
</script>
</body>
</html>
# v-text 指令
作用和 Mustache 相似,更新元素的 textContent。但是会覆盖该标签的内容!不灵活,一般使用较少!如果要更新部分的 textContent ,需要使用 插值。
# v-html 指令 🔥
双大括号会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTML,你需要使用 v-html 指令:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Title</title>
</head>
<body>
<div id="app">
mustache:
<span>{{url}}</span><br />
v-html:
<span v-html="url"></span><br />
v-text:
<span v-text="url"></span><br />
</div>
<script src="/lib/vue.js"></script>
<script>
const vm = new Vue({
el: "#app",
data: {
message: "Hello",
url: '<a href="https://www.qq.com">QQ</a>',
},
methods: {},
});
</script>
</body>
</html>
属性值会直接作为 HTML——会忽略解析属性值中的数据绑定。注意,你不能使用 v-html 来复合局部模板,因为 Vue 不是基于字符串的模板引擎。反之,对于用户界面 (UI),组件更适合作为可重用和可组合的基本单位。
# v-pre 指令 🔥
如<pre>,跳过这个元素和它的子元素的编译过程。可用来显示原始 Mustache 标签。跳过大量没有指令的节点会加快编译。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Title</title>
</head>
<body>
<div id="app">
<span v-pre>{{ this will not be compiled }}</span>
</div>
<script src="/lib/vue.js"></script>
<script>
const vm = new Vue({
el: "#app",
});
</script>
</body>
</html>
# v-cloak 指令
cloak
披风; 斗篷; 大衣; 氅。这里为挡住之类的意思。
区别 clock 时钟
这个指令保持在元素上直到关联实例结束编译,可以据此来实现判断。
上述含义为,在 Vue 编译完前 HTML 中有 v-cloak 属性,在 Vue 编译完后该属性被删掉。
基本也不会使用,以后这个模版会渲染为函数,和虚拟DOM有关,不会显示 mustache 语法的。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Title</title>
<style>
/* 属性选择器 */
[v-cloak] {
display: none;
}
</style>
</head>
<body>
<div id="app">
<h2 v-cloak>{{message}}</h2>
</div>
<script src="/lib/vue.js"></script>
<script>
setTimeout(() => {
const vm = new Vue({
el: "#app",
data: {
message: "Hello",
},
methods: {},
});
}, 2000);
</script>
</body>
</html>
# 过滤器 🔥
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vue</title>
<style>
table {
/* 合并细线边框 */
border-collapse: collapse;
/* 单元格之间水平、垂直距离,与 border-collapse 冲突,不常用 */
/*border-spacing: 10px 20px;*/
/* 表格居中 */
margin: 100px auto;
}
th,
td {
/* 边框 */
border: 1px solid skyblue;
/* 内边距 */
padding: 20px;
/* 让td居中,th本来就是居中的 */
text-align: center;
/* 默认情况下元素在th,td中是垂直居中的,也可以通过 vertical-align 来修改*/
/* 由此可得,对一个父元素设置 display: table-cell,可以直接使用 vertical-align 来垂直居中*/
}
</style>
</head>
<body>
<div id="app">
<div v-if="books.length >= 1">
<table>
<thead>
<tr>
<th></th>
<th>书籍名称</th>
<th>出版日期</th>
<th>价格</th>
<th>购买数量</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(book,index) in books" :key="book.id">
<td>{{book.id}}</td>
<td>{{book.name}}</td>
<td>{{book.time}}</td>
<!-- <td>{{'¥'+book.price.toFixed(2)}}</td> -->
<!-- 这么多地方使用,可以复用 -->
<!-- 方式1:方法。计算属性也可以 -->
<!-- <td>{{formartPrice(book.price)}}</td> -->
<!-- 方式2:过滤器 -->
<td>{{book.price | formartPrice}}</td>
<td>
<button @click="decrement(book)" :disabled="book.count === 1">
-
</button>
{{book.count}}
<button @click="increment(book)">+</button>
</td>
<td><button @click="remove(index)">移除</button></td>
</tr>
</tbody>
</table>
<!-- 总价:{{'¥'+totalPrice.toFixed(2)}} -->
<!-- 总价:{{formartPrice(totalPrice)}} -->
总价:{{totalPrice | formartPrice}}
</div>
<div v-else>
购物车为空
</div>
</div>
<script src="/lib/vue.js"></script>
<script>
// vue.js文件中定义了 Vue 对象,使用时可以 new 构造出,并且它还有参数(对象类型)
const vm = new Vue({
el: "#app",
// 声明式编程(声明式渲染),不再使用命令式
data: {
books: [
{ id: 1, name: "Java", time: "2006-02", price: 110.0, count: 1 },
{ id: 2, name: "Kotlin", time: "2016-03", price: 120.0, count: 1 },
{ id: 3, name: "Clojure", time: "2008-12", price: 112.0, count: 1 },
{ id: 4, name: "JVM", time: "2002-8", price: 200.0, count: 1 },
],
},
methods: {
increment(book) {
book.count++;
},
decrement(book) {
// if (book.count === 1) {
// return;
// }
book.count--;
},
remove(index) {
this.books.splice(index, 1);
},
formartPrice(price) {
return "¥" + price.toFixed(2);
},
},
computed: {
totalPrice() {
// let totalPrice = 0;
// this.books.forEach((item) => {
// totalPrice += item.price * item.count;
// });
// return totalPrice;
return this.books.reduce((previous, current, index, arr) => {
return previous + current.price * current.count;
}, 0);
},
},
filters: {
formartPrice(price) {
return "¥" + price.toFixed(2);
},
},
});
</script>
</body>
</html>