Vue实例的属性及模板渲染
Vue实例的属性及模板渲染1 概述2 el:与DOM元素绑定3 data:定义双向绑定的数据4 computed:计算属性5 methods:定义Vue实例的方法6 Vue中的三种模板6.1 html模板6.2 字符串模板6.3 render函数模板7 watch属性8 模板渲染8.1 条件渲染8.2 列表渲染
Vue实例的属性及模板渲染
1 概述
Vue.js是通过new Vue({...})
来声明一个实例的,在这个实例中包含了当前页面的HTML结构、数据和事件。Vue实例是MVVM模式中的ViewModel,实现了数据和视图的双向绑定。在实例化时可以传入一个选项对象,它包含数据、模板、挂载元素、方法、生命周期钩子函数等选项。
2 el:与DOM元素绑定
el
是element
的简写,用来和DOM元素进行绑定,对应的是DOM元素的id属性值(类似id选择器)。用法如下:
<div id="xxx"></div>
<script>
var vm = new Vue({
el: "#xxx" // xxx为id名
})
</script>
3 data:定义双向绑定的数据
在Vue实例中初始化的data
中的所有数据会自动进行监听绑定,可以使用两个大括号 {{}}
来绑定data
中的数据。用法如下:
<div id="xxx"></div>
<script>
var vm = new Vue({
el: "#xxx",
data: {
健: 值
}
})
</script>
健为属性的名称,值为初始值。示例代码:
<div id="app">
<h2>{{message}}</h2>
<input type="text" v-model="message">
</div>
<script>
var vm = new Vue({
el: "#app",
data: {
message: "橘猫吃不胖"
}
})
</script>
如果在输入框中输入其他内容,h2标签也会显示该内容,vue与h2标签的绑定是单向的,与input标签的绑定是双向的。
注:data中的数据都是浅拷贝。这意味着,如果修改原来的对象也会改变data,从而触发更新事件。
4 computed:计算属性
computed
是计算属性,当我们要用到的属性不存在,需要通过已有属性计算得来,这时使用计算属性。computed
底层借助了Object.defineproperty
方法提供的getter
和setter
来实现。使用方法可以跟data
中的属性一样使用,注意用的时候不要加“()
”。
它是data
属性的补充。在进行数据绑定的时候,对数据要进行一定的处理才能展示到HTML页面上。虽然Vue提供了非常好的表达式绑定方法,但是只能应对低强度的需求。用法如下:
<div id="xxx"></div>
<script>
var vm = new Vue({
el: "#xxx",
computed: {
方法名: function () {}
}
})
</script>
例如,把一个日期按照规定格式进行输出,可能就需要对日期对象做一些格式化。Vue提供的计算属性computed
允许开发者编写一些方法,协助进行绑定数据的操作。
<div id="app">
<table>
<tr>
<td>姓名:</td>
<td>{{name}}</td>
</tr>
<tr>
<td>生日:</td>
<td>{{getBirthday}}</td>
</tr>
</table>
</div>
<script>
var vm = new Vue({
el: "#app",
data: {
name: "橘猫吃不胖",
birthday: 1014228510514 // 传了一个毫秒数
},
computed: { // 计算属性,对data中的数据进行处理
getBirthday: function () { // getBirthday就是表格中的{{getBirthday}},其本质是一个属性
let date = new Date(this.birthday);
return date.getFullYear() + "年" + (date.getMonth() + 1) + "月" + date.getDate() + "日";
}
}
})
</script>
每一个计算属性都包含一个getter
和一个setter
。上面的示例是计算属性的默认用法, 只是利用了getter
来读取。在需要时,也可以提供一个setter
函数, 当手动修改计算属性的值就像修改一个普通数据那样时,就会触发setter
函数,执行一些自定义的操作。
getter
函数执行的时机:
(1)初次读取时会执行一次
(2)当依赖的数据发生改变时会被再次调用
计算属性computed
优势:与methods
实现相比,它的内部有缓存机制,计算属性只有在它相关依赖发生改变时才会重新求值,效率更高,调试方便。
注意:
(1)计算属性最终会出现在Vue实例vm
上,直接读取使用即可
(2)如果计算属性要被修改,那必须写set
函数去响应修改,且set
中要引起计算时依赖的数据发生改变
示例:在输入框中分别输入姓和名,最后将全名显示在页面上,感受getter
方法;在控制台中修改全名,感受setter
方法。
<div id="app">
姓:<input type="text" v-model="xing"><br><br>
名:<input type="text" v-model="ming"><br><br>
你的姓名是:{{fullName}}
</div>
<script>
var vm = new Vue({
el: "#app",
data: {
xing: "", // 初始值为空
ming: ""
},
computed: {
fullName: {
get() {
return this.xing + "-" + this.ming; // 返回值为全名
},
set(value) {
let arr = value.split("-");
this.xing = arr[0];
this.ming = arr[1];
}
}
}
})
</script>
如下所示,在输入框中输入姓和名,会将全名显示在下方。
如果在控制台中修改全名,会修改掉输入框中的值。
5 methods:定义Vue实例的方法
methods
需要搭配v-on
指令来监听DOM事件,我们在methods
对象中定义方法,最终会在Vue实例上,其中的this
会指向Vue的实例vm
,因此其中配置的函数不可以使用箭头函数,否则会改变this
的指向。用法如下:
<div id="xxx"></div>
<script>
var vm = new Vue({
el: '#xxx',
methods: {
方法名: function () { }
}
})
</script>
示例代码:
<div id="app">
<p>原始字符串:"{{ message }}"</p>
<p>反向字符串:"{{ reversedMessage()}}"</p>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
message: '橘猫吃不胖'
},
methods: {
reversedMessage: function () {
return this.message.split('').reverse().join('')
}
}
})
</script>
6 Vue中的三种模板
6.1 html模板
- html模板:基于DOM的模板,内容都是可解析的有效的HTML插值
- 文本:使用
{{}}
语法,作用:替换实例上的属性值,当值改变时,插值内容处会自动更新 - 原生的html:输出的是文本,不会解析html(想要解析html,可以使用指令v-html)
<div id="wrap">
<p>你的名字是{{list.name}}</p>
</div>
<script>
var list = {
name: "donna",
age: 20
}
var vm = new Vue({
el: "#wrap",
data: { list }
});
</script>
6.2 字符串模板
先定义字符串模板,然后在vue的选项对象里面利用template
绑定。字符串模板的优先级会比html模板高,如果html和字符串模板中都有内容,会用字符串模板里的内容替换html模板。需要注意的是定义的字符串模板中根节点只能有一个。还有字符串用 ` 引起来是可以换行的。
示例代码:
<div id="app"></div>
<script>
let obj = {
content: "橘猫吃不胖"
}
let str = `<div>Hello {{content}}</div>`;
new Vue({
el: "#app",
data: obj,
template: str
})
</script>
除了用变量定义模板字符串,还可以用script标签,给script 标签定义id,根节点只能有一个,将html结构写在一对script标签中,设置type=“x-template”,模板将会替换挂载的元素。挂载元素的内容都将被忽略。Vue实例的template属性设置为给定的script标签
示例代码:
<div id="app"></div>
<script type="x-template" id="test">
<div>
<p>姓名:{{obj.name}}</p>
</div>
</script>
<script>
let obj = {
name: "张三"
}
new Vue({
el: "#app",
data: { obj },
template: "#test"
})
</script>
6.3 render函数模板
render(createElement){
createElement(标签名,[数据对象],子元素)//子元素为数组或对象
}
数据对象的属性:
class:{ }, //绑定class
style:{ }, //绑定样式,
attrs:{ }, //添加行间属性
domProps:{ }, //DOM元素属性
on:{ }, //绑定事件
示例代码:
<div id="app"></div>
<style>
.bg {
background-color: pink;
}
</style>
<script>
new Vue({
el: "#app",
render(createElement) {
return createElement(
"ul",
{
class: { bg: true },
style: { listStyle: "none" },
attrs: {
name: "tt"
}
},
[
createElement("li", "苹果"),
createElement("li", "香蕉"),
createElement("li", "橘子")
]
)
}
})
</script>
7 watch属性
watch
属性用来观察和响应Vue实例上的数据变动,watch
属性是一个配置对象,它有两个属性:一个是键,一个是值。键是需要观察的表达式,值可以为以下形式:
- 对应的回调函数,回调函数得到的参数为新值和旧值。
- 方法名称的字符串(通过
methods
声明) - 包含额外选项的对象。当使用对象语法时,回调函数应被声明在
handler
中。额外的选项包含:
选项 | 说明 |
---|---|
immediate | 在初始化时立即调用回调函数handler 。第一次调用时,旧值将为undefined |
deep | 如果源是对象或数组,则强制深度遍历源,以便在深度变更时触发回调 |
flush | 调整回调的刷新时机 |
onTrack / onTrigger | 调试侦听器的依赖关系 |
new Vue({
...
watch: {
// 值为回调函数形式,newVal表示新的值,oldVal表示旧的值
要监视的数据: function (newVal, oldVal) { }
// 值为方法名形式:
要监视的数据: "methods中声明的方法名"
// 值为包含额外选项的对象:
要监视的数据: {
immediate: xxx,
handler(newVal, oldVal) {},
deep: xxx,
}
}
})
示例:点击按钮给属性a
做减法,监听新值与旧值。
<div id="app">
<button @click="a--">减1</button>
<p>{{message}}</p>
</div>
<script>
new Vue({
el: "#app",
data: {
a: 10,
message: " ",
},
watch: {
a: function (val, oldVal) {
this.message = "a的原值是:" + oldVal + ",a的新值是:" + val;
}
}
})
</script>
或者使用Vue实例中的$watch()
,也可以达到监视效果,该方法的返回值是一个取消观察函数,用来停止触发回调,用法如下:
// 完整形式
const vm = new Vue({ })
// unwatch:取消观察函数
let unwatch = vm.$watch("要监视的对象", {
immediate: true, // 配置一些属性
...
handler(newVal, oldVal) { // 回调函数
unwatch(); // 停止监听对象
}
})
// 简写形式
const vm = new Vue({ })
// unwatch:取消观察函数
let unwatch = vm.$watch("要监视的对象", function (newVal, oldVal) {}
})
示例:点击按钮给属性a
做减法,监听新值与旧值。当值为5时,停止监听。
<div id="app">
<button @click="a--">减1</button>
<p>{{message}}</p>
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
a: 10,
message: " ",
}
})
let unwatch = vm.$watch("a", {
handler(val, oldVal) {
if (val === 5) {
unwatch();
}
this.message = "a的原值是:" + oldVal + ",a的新值是:" + val;
}
})
</script>
computed与watch的区别
computed
能完成的功能,watch
都可以完成;watch
能完成的功能,computed
不一定能完成。例如:watch可以进行异步操作(使用setTimeout
函数)。
8 模板渲染
8.1 条件渲染
条件渲染分为两种方式,分别是v-if
和v-show
。
v-if、v-else-if、v-else
v-if
指令用于条件性地渲染一块内容,只有if
后面的值为true
时才会显示DOM元素,为false
时不会显示。v-if
底层采用的是appendChild
来实现的。使用方式如下:
<div v-if="isShow"></div>
其中,isShow
可以是true
或者false
,也可以是表达式,例如:
<div v-if="true">aaaaaaa</div>
<div v-if="1 === 3">bbbbbbbb</div>
结果只显示aaaaaaa
,不显示bbbbbbbb
:
v-else-if
提供的是相应于v-if
的“else if
区块”,它可以被连续多次重复使用,一个使用v-else-if
的元素必须紧跟在一个v-if
或一个v-else-if
元素后面。例如下面的例子,当type
为A
时显示A
,type
为B
时显示B
,type
为C
时显示C
:
<div v-if="type === 'A'">A</div>
<div v-else-if="type === 'B'">B</div>
<div v-else-if="type === 'C'">C</div>
v-else
为v-if
添加了一个“else
区块”,它表示了if...else
中的else
,一个v-else
元素必须跟在一个v-if
或者v-else-if
元素后面,否则它将不会被识别。例如:
<div v-if="1 === 3">aaaaaaa</div>
<div v-else>bbbbbbbb</div>
如果v-if
显示的不止一个元素,我们可以在一个<template>
元素上使用v-if
,这只是一个不可见的包装器元素,最后渲染的结果并不会包含这个<template>
元素。示例代码:
<template v-if="true">
<div>橘猫吃不胖</div>
<div>使用 template 显示</div>
</template>
可以看出并没有显示<template>
元素。
v-show
v-show
用法与v-if
大致相同,它通过样式的display
属性控制标签的显示,具体如下:
<div v-show="isShow"></div>
不同之处在于v-show
会在DOM渲染中保留该元素,并且不支持在<template>
元素上使用,也不能和v-else
搭配使用。
v-if
和v-show
的区别:Vue中v-if和v-show的比较
8.2 列表渲染
我们可以使用v-for
指令基于一个数组来渲染一个列表。v-for
指令的值需要使用item in items
形式的特殊语法,其中items
是源数据的数组,在data
中定义,而item
是迭代项,可以起任意的名字,具体用法如下:
<div v-for="item in items">
{{item}}
</div>
示例代码:
<div id="app">
<div v-for="item in items">
姓名:{{item.name}},年龄:{{item.age}}
</div>
</div>
<script>
var vm = new Vue({
el: "#app",
data: {
items: [
{ id: "001", name: "张三", age: 14 },
{ id: "002", name: "李四", age: 16 },
{ id: "003", name: "王五", age: 19 },
]
}
})
</script>
v-for
也支持使用可选的第二个参数表示当前项的位置索引,具体如下,index
就是数组索引:
<div v-for="(item, index) in items">
{{item}}
</div>
示例代码:
<div id="app">
<div v-for="({ name }, index) in items">
{{index}}-{{name}}
</div>
</div>
<script>
var vm = new Vue({
el: "#app",
data: {
items: [
{ id: "001", name: "张三", age: 14 },
{ id: "002", name: "李四", age: 16 },
{ id: "003", name: "王五", age: 19 },
]
}
})
</script>
我们也可以使用v-for
来遍历一个对象的所有属性。遍历的顺序会基于对该对象调用Object.keys()
的返回值来决定。具体用法如下:
<div v-for="(value, key, index) in obj"></div>
其中,value
表示对象的值,key
表示对象的键,index
表示对象的索引,示例代码如下:
<div id="app">
<div v-for="(value, key, index) in obj">
{{index}}-{{key}}-{{value}}
</div>
</div>
<script>
var vm = new Vue({
el: "#app",
data: {
obj: {
id: "001",
name: "橘猫吃不胖",
age: 3
}
}
})
</script>
通过key管理状态
Vue默认按照“就地更新”的策略来更新通过v-for
渲染的元素列表。当数据项的顺序改变时,Vue不会随之移动DOM元素的顺序,而是就地更新每个元素,确保它们在原本指定的索引位置上渲染。
为了给Vue一个提示,以便它可以跟踪每个节点的标识,从而重用和重新排序现有的元素,我们需要为每个元素对应的块提供一个唯一的key
。具体如下:
<div v-for="item in items" :key="item.id">
<!-- 内容 -->
</div>
当使用<template v-for>
时,key
应该被放在<template>
容器上:
<template v-for="todo in todos" :key="todo.name">
<li>{{ todo.name }}</li>
</template>
更多推荐
所有评论(0)