一、计算属性
计算属性是用来声明式的描述一个值依赖了其它的值。当你在模板里把数据绑定到一个计算属性上时,Vue 会在其依赖的任何值导致该计算属性改变时更新 DOM。这个功能非常强大,它可以让你的代码更加声明式、数据驱动并且易于维护。
上述描述可是使用一句话作为概括:计算属性时具有缓存的,当计算的结果没有发生改变时直接调用缓存,当计算的结果发生改变时,将会重新计算。
计算属性的特点就是将不经常改变的计算结果进行缓存,节约系统的开销。
计算属性的逻辑(方法)是写在computed中的。
methods和computed中的方法不要重名,如果重名,methods的优先级高于computed
通常情况下,data01和data02的值都会是从服务器端获取,这样的话,只有当服务器返回的data01和data02的值发生改变的时候才会从新结算example,否则直接电泳缓存即可。
var vm = new Vue({
el:"#app",
data: {
data01:10,
data02:20
},
computed: {
example: function () {
return this.data01+this.data02
}
}
})
computed中的方法进行调用的时候的格式:方法名
<div id="app">
<h3>{{example}}</h3>
</div>
当然我们也是可以使用cache: false手动关闭缓存.
computed: {
cache: false,
example: function () {
return this.data01+this.data02
}
}
methods中的方法进行调用的时候格式:方法名()
<div id="app">
<h3>{{example()}}</h3>
</div>
var vm = new Vue({
el:"#app",
data: {
data01:10,
data02:20
},
methods: {
example: function () {
return this.data01+this.data02
}
}
})
二、插槽与内容分发slot
1.插槽
我们在没有接触插槽之前,当我们使用我们自定的组件的时候,可以发现,当我们在自定义的组件的标签体中写入内容的时候,并不会生效。
Vue.component("my-component",{
template:`
<ul>
<li>寒江のjava世界</li>
<li>寒江のpython世界</li>
</ul>
`
})
var vm = new Vue({
el:"#app"
})
<div id="app">
<my-component>寒江のC++世界</my-component>
</div>
如果我们想要是自定义的组件标签中的内容被识别,那么就要使用到< slot>,使用的方法也是很简单,我们只需在我们的模板中的任意的位置插入< slot>< /slot>,,那么组件标签中的内容就会自动的绑定到< slot>< /slot>,。值得注意的是我们可以使用多个< slot>。
Vue.component("my-component",{
template:`
<ul>
<li>寒江のjava世界</li>
<li>
<!--定义插槽的位置-->
<slot></slot>
</li>
<li>寒江のpython世界</li>
</ul>
`
})
var vm = new Vue({
el:"#app"
})
<div id="app">
<!--“寒江のC++世界”将被绑定到定义的slot中去-->
<my-component>寒江のC++世界</my-component>
</div>
2.内容分发slot
为了让组件可以组合,需要一种方式来混合父组件的内容与子组件自己的模板。这个过程被称为 内容分发 (或 “transclusion” )。
我们可以在一个 < template> 元素上使用 “v-slot:插槽名” 指令,用来指定特定组件插入指定的插槽(slot)。
<div id="app">
<my-component>
<template v-slot:cli>
寒江のC++世界
</template>
</my-component>
</div>
当然< template v-slot>的最常使用的方式还是结合其他组件一起使用。
Vue.component("my-slot",{
template: `
<div>
<slot name="header">标题(默认)</slot>
<ul>
<slot name="list">内容...</slot>
</ul>
</div>
`
})
Vue.component("slot-title",{
props:['title'],
template: `
<h3>{{title}}</h3>
`
})
Vue.component("slot-list",{
props: ['list'],
template:`
<li>{{list}}</li>
`
})
var vm = new Vue({
el:"#app",
data:{
head:"寒江のvue世界",
lists:["什么是vue", "vue的使用", "vue的优点"]
}
})
:title:是v-bind:title的简写形式。
title:是"slot-title"组件中的自定义属性
list:是"slot-list"组件中的自定义属性
<div id="app">
<my-slot>
<!--通过templa进行填充名为header的slot-->
<template v-slot:header>
<slot-title :title="head"></slot-title>
</template>
<!--通过templa进行填充名为list的slot-->
<template v-slot:list>
<!--将lists中遍历到的item绑定到“slot-lits”中的list属性上-->
<slot-list v-for="item in lists" :list="item"></slot-list>
</template>
</my-slot>
</div>
在插槽中还有一种被废弃掉的slot的使用,我觉得也是有必要讲一下的。
在一个组件中使用slot=""可以将将该组件插入到其父组件的指定的插槽(slot)中去。
< slot-title slot=“header”>:将slot-title
组件插入到name为header
的插槽中。
< slot-list slot=“list”>:将slot-list
组件插入到name为list
的插槽中。
<div id="app">
<my-slot>
<!--通过其他组件进行填充slot-->
<slot-title slot="header" :title="head"></slot-title>
<!--将lists中遍历到的item绑定到“slot-lits”中的list属性上-->
<slot-list slot="list" v-for="item in lists" :list="item"></slot-list>
</my-slot>
</div>
注意:
父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。
v-slot 只能添加在 <template> 上 (只有一种例外情况:独占默认插槽的缩写语法),这一点和已经废弃的 slot attribute 不同。
三、自定义事件以及$emit的使用
在介绍自定义事件之前,我们先来介绍一下组件中自定义方法以及方法的绑定
methods:和vue实例中的methods的性质是一样的。
@click=“remove”:等价于v-on:click=“remove”。值得注意的是,组件中只能调用组价中methods中的方法,是无法调用到vue实例中的methods中的方法的。
Vue.component("slot-list",{
props: ['list'],
template:`
<li>{{list}} <button @click="remove">删除</button></li>
`,
methods:{
remove:function () {
alert("good")
}
}
})
现在,我们有这么一个需求(A):当我们点击删除按钮时,对应的前面的文本就被删除掉。
很明显,这个是不好实现的,因为文本是vue实例中data的数据,实例中数据的删除需要通过实例中的方法
,但是删除按钮是在组件(component)中定义的,无法调到vue实例中的方法。
为了解决组件调用不到vue实例中方法的问题,我们引入自定义事件和$emit.。
我们可以通过 @自定义事件名=“动作/方法”来实现自定义事件。在组件中我们可以通过$emit(“自定义事件名”, 参数)来调用自定义事件。
<my-component @my-remove="removeItem(index)"></my-component>
this.$emit("my-remove",index)
至此,我们就实现了component中调用vue实例中的函数进而操作vue实例中的数据。
在实现 需求(A) 之前,我们还要解决一个问题:在js中,怎么能够做到灵活的操作数组中的元素。答案很简单,使用 splice() 方法。
splice() 方法向/从数组中添加/删除项目,然后返回被删除的项目。该方法会改变原始数组。
语法:
arrayObject.splice(index, howmany, item1,…,itemX) |
---|
参数 | 描述 |
---|---|
index | 必需。整数,规定添加/删除项目的位置,使用负数可从数组结尾处规定位置。 |
howmany | 必需。要删除的项目数量。如果设置为 0,则不会删除项目。 |
item1, …, itemX | 可选。向数组添加的新项目。 |
说明
splice() 方法可删除从 index 处开始的零个或多个元素
,并且用参数列表中声明的一个或多个值来替换那些被删除的元素。
如果从 arrayObject 中删除了元素,则返回的是含有被删除的元素的数组。
至此,我们具备了实现 需求(A) 的所有条件,下面我们就来实现一下。
vue实例
function (index):index是需要调用者给传递的
var vm = new Vue({
el:"#app",
data:{
head:"寒江のvue世界",
lists:["什么是vue", "vue的使用", "vue的优点"]
},
methods: {
removeItem:function (index) {
let info = this.lists.splice(index,1)
console.log(info+" 被删除了...")
}
}
})
父组件
Vue.component("my-slot",{
template: `
<div>
<slot name="header">标题(默认)</slot>
<ul>
<slot name="list">内容...</slot>
</ul>
</div>
`
})
子组件
Vue.component("slot-title",{
props:['title'],
template: `
<h3>{{title}}</h3>
`
})
@click=“remove”:调用component中的remove方法
Vue.component("slot-list",{
props: ['list',"index"],
template:`
<li>{{list}} <button @click="remove">删除</button></li>
`,
methods:{
remove:function (index) {
this.$emit("my-remove",index)
}
}
})
视图层
v-for="(item,index) in lists":遍历lists中的元素以及元素对应的索引。
:list=“item”:绑定到slot-list中的list属性。:是v-bind:的缩写
:index=“index”:绑定到slot-list中的index属性。:是v-bind:的缩写。
@my-remove=“removeItem(index)”:自定义事件my-remove,该事件调用vue实例中的removeItem(index) 方法,index 是 (item,index) in lists中的index。@是v-on:的缩写。
<div id="app">
<my-slot>
<!--通过templa进行填充slot-->
<template v-slot:header>
<slot-title :title="head"></slot-title>
</template>
<template v-slot:list>
<slot-list v-for="(item,index) in lists"
:list="item"
:index="index"
@my-remove="removeItem(index)"
></slot-list>
</template>
</my-slot>
</div>
至此,我的介绍就结束了,但vue永远在你进步的路上等你…