Vue使用了基于HTML的模板语法,允许开发者声明式地将DOM绑定至底层Vue实例的数据。所有Vue的模板都是合法的HTML,所以能被遵循规范的浏览器和HTML解析器解析。
在底层的实现上,Vue将模板编译成虚拟DOM渲染函数。结合响应系统,在应用状态改变时,Vue能够智能地计算出重新渲染组件的最小代价并应用到DOM操作上。
如果你熟悉虚拟DOM并且偏爱JavaScript的原始力量,你也可以不用模板,直接写渲染函数render
,使用可选的JSX语法。
插值
大家在前面的教程中可能看到了我们使用{{}}
的形式来渲染文本。这种形式就是Mustache语法。
<h1>Name: {{ name }}</h1>
Mustache标签将会被替代为对应数据对象上name
属性的值,无论何时,绑定的数据对象上name
属性发生了改变,插值片的内容都会更新。比如:
通过使用v-once
指令(我们后面会学习这个指令),你也能执行一次性地插值,当数据改变时,插值处的内容不会更新。但请留心,这会影响到该节点上所有的数据绑定:
<h1 v-once>Name: {{ name }} (绑定v-once不会改变name)</h1>
使用Mustache语法(也就是双大括号{{}}
)可以很方便的让我们将数据源对象的属性渲染到Vue的DOM元素中。但其也有一定的弊端,比如让你的网速慢,或者数据加载失败的时候会在浏览器中直接渲染插值,比如{{name}}
。或者说,当你的JavaScript报错,或者你的用户禁用页面所有JavaScript时,也会有类似现象:
在这种情况之下,对用户的体验并不好,因为我们的用户并不知道{{xxx}}
表示的是什么?不过,值得庆幸的是,在Vue中,除了使用{{}}
这样的插值语法渲染数据之外,还提供了两个相关的指令,也就是我们今天需要学习的v-text
和v-html
。在学习这两个指令之前,咱位回忆一下JavaScript中相关的几个知识。
JavaScript相关知识点
在JavaScript中有textContent
、innerHTML
、innerText
、outerText
、outerHTML
和nodeValue
。这些属性都可以用来获取某个元素的内容,也可以将内容或标签插入到某个元素中。看上去和渲染内容有点相关。
简单的理解一下这几个属性:
innerHTML
:获取从对象的起始位置到终止位置的全部内容,包括HTML标签。当内容都是文本的时候,可以把这个属性当做textContent
属性来用innerText
:获取从对象的起始位置到终止位置的内容,但它不会包括HTML标签outerHTML
:除了包含innerHTML
的全部内容外,还会包含对象标签本身textContent
:设置或返回指定节点的文本内容,以及它的所有后代。有时候,此属性可用于取代nodeValue
属性,但请记住此属性同时会返回所有子节点的文本。得到的结果跟innerText
的结果是一样的。如果是设置,则原本的子元素会被同时替换掉nodeValue
:和textContent
很像,都是用来获取某个元素中的内容,不过nodeValue
并不能直接操作某个DOM元素,它只能用来获取某段文本节点中的内容outerText
:和outerHTML
有同样的功能,它们都包括自身,不同的是outerText
获取的是元素内容,而outerHTML
获取到的内容包括元素
简单点来看看他们之间对元素操作的结果:
v-text
在JavaScript中可以使用innerText
或者textContent
来操作元素中的纯文本。在Vue中,如前面的示例所展示的一样,使用{{}}
Mustache语法操作元素中的纯文本。不过在Vue中,我们还可以使用v-text
起到同等的作用。
先来看一个例子:
<div id="app">
<h1>用户名:{{ name }}</h1>
<h1 v-text="'用户名:' + name"></h1>
</div>
效果如下:
从效果图上可以看出来,v-text
和{{}}
起到的效果是一样的。同样的,动态修改对象name
的值时,渲染的结果也会有对应的变化:
从上面的示例,我们可以看出v-text=""
指令中的双引号并不是代表字符串,而是Vue自定义的划定界限的符号。如果我们里面输出字符串,就需要在里面再添加一对单引号。比如<h1 v-text="'用户名:' + name"></h1>
。而且,在Vue中要想输出字符串,必须添加单引号,否则会报错。
另外{{}}
代表的就是""
,所以在v-text=""
中,我们在内容里面就不需要再写{{}}
了,直接写数据属性就行了。
在v-for
一节中,我们看到{{}}
方法可以采用对象的形式传递多个数据。其实在v-text
中,也具备同等的功能。比如下面这个示例:
<!-- Template -->
<div id="app">
<h2>{{}}方法:</h2>
<ul>
<li v-for="(value, key) in person">{{ key }}: {{ value }}</li>
</ul>
<hr>
<h2>v-text方法:</h2>
<ul>
<li v-for="(value, key) in person" v-text="key + ':' + value"></li>
</ul>
</div>
// JavaScript
var app = new Vue({
el: '#app',
data: {
person: {
name: '大漠',
set: '男',
age: 30
}
}
})
得到的效果是一致的:
Vue中的
v-text
等同于文本插值{{}}
方法,也类似于JavaScript中的textContent
。
v-html
前面提到过,在JavaScript中使用innerHTML
获取一个元素的HTML标签(包括标签里的内容),也可以用它设置来重置HTML标签(包括标签里的内容),配合JavaScript的一些操作DOM的方法:
let h1Element = document.createElement('h1')
h1Element.classList.add('title')
h1Element.textContent = '把大漠塞进去'
document.getElementById('app').appendChild(h1Element)
创建了一个带有title
类名的h1
元素插入到#app
元素中,相当于把下面的代码插进去了:
<h1 class="title">把大漠塞进去</h1>
结果可以看到的效果如下:
如果你对DOM的操作不太熟悉,建议花点时间阅读下面几篇文章:
- DOM 模型概述
- 操作DOM
- Javascript DOM 控制
- JavaScript与DOM(上)
- JavaScript与DOM(下【汤姆大叔的深入理解JavaScript系列】
- 使用JavaScript修改DOM
- 更快地构建 DOM: 使用预解析, async, defer 以及 preload
在Vue中,我们可以使用v-html
来操作元素中的HTML标签,事情会变得容易得多。比如:
<!-- Template -->
<div v-html="cat"></div>
// JavaScript
var app = new Vue({
el: '#app',
data: {
cat: "<img src='//www.w3cplus.com/sites/default/files/blogs/2017/1709/cat.jpg' />"
}
})
我效果中,我们可以看到:
<img src="//www.w3cplus.com/sites/default/files/blogs/2017/1709/cat.jpg">
插入到了div
元素中,效果如下:
和v-text
一样,如果我们动态修改数据源中cat
的属性值,就会有相应的变化:
注意:你不能使用
v-html
来复合局部模板,因为Vue不是基于字符串的模板引擎。反之,对于用户界面(UI),组件更适合作为可重用和可组合的基本单位。
在Vue中,不能通过{{}}
和v-text
将HTML的元素插入到模板中。如果你感兴趣,不仿自己动手试试。
在Vue中,使用v-html
动态渲染的任意HTML都可能会非常危险,因为它容易导致XSS攻击。这个和JavaScript中的innerHTML
类似。所以在实际使用的时候,请只对可信内容使用HTML插值,绝不要对用户提供的内容使用插值。
总结
在Vue中,我们可以使用{{}}
将数据插入到相应的模板中,这种方法是一种文本插值。使用这种方法,如果网络慢或者JavaScript出错的话,会将{{}}
直接渲染到页面中。值得庆幸的是,Vue还提供了v-text
和v-html
来渲染文本或元素。其中v-text
和{{}}
类似,只是用来渲染文本内容,而v-html
和innerHTML
非常相类,可以将HTML元素渲染。
简单说,这篇文章主要介绍了怎么渲染文本,虽然方法有多种,但个人建议不要使用v-html
,因为会引起XSS攻击,对于动态渲染应该尽量使用v-text
。
由于作者是Vue的初学者,如果文中有不对之处,还请大婶拍正,如果你有更好的经验,欢迎在下面的评论中与我们一起分享。
如需转载,烦请注明出处:https://www.w3cplus.com/vue/v-text-and-v-html.html