计算属性、内容分发、自定义事件
计算属性
计算出来的结果保存在属性中。内存中运行,是一个能将计算结果缓存起来的属性(成为静态属性),可以视作缓存。
<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--view层:模版-->
<div id="app-4">
<!--两种调用等价-->
<p>currentTime1: {{currentTime1}}</p>
<p>currentTime2: {{currentTime2()}}</p>
</div>
<!-- 导入vue.js -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app4 = new Vue({
el: '#app-4',
data: {
msg: "hello, vue!"
},
computed: { //计算属性,computed 和 methods 方法名不能重名,否则优先调用方法名
currentTime1: function () {
this.msg; //当数据发生变动(增、删、改)时,计算属性才会重新生成,并保存到缓存中
return Date.now();
}
},
methods: {
currentTime2: function () {
return Date.now();
}
}
})
</script>
</body>
</html>
内容分发
为了让组件可以组合,需要一种方式来混合父组件的内容与子组件自己的模板。这个过程被称为 内容分发 (或 “transclusion” )
Vue 实现了一套内容分发的 API,这套 API 的设计灵感源自 Web Components 规范草案,将
在 2.6.0 中,为具名插槽和作用域插槽引入了一个新的统一的语法 (即 v-slot 指令)。它取代了 slot 和 slot-scope 这两个目前已被废弃但未被移除且仍在文档中的 attribute。
规则:
父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。
代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--view层:模版-->
<div id="app-4">
<todo>
<!--slot: 插槽-->
<todo-title slot="todo-title" :title="title"></todo-title>
<todo-items slot="todo-items" v-for="item in todoItems" :item="item"></todo-items>
</todo>
</div>
<!-- 导入vue.js -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component("todo",{
template:
'<div>\
<slot name="todo-title"></slot>\
<ul>\
<slot name="todo-items"></slot>\
</ul>\
</div>'
});
Vue.component("todo-title",{
props: ['title'],
template: '<div>{{title}}</div>'
});
Vue.component("todo-items",{
props: ['item'],
template: '<li>{{item}}</li>'
});
var app4 = new Vue({
el: '#app-4',
data: {
title: "书籍列表",
todoItems: ["java", "py", "c"]
}
})
</script>
</body>
</html>
结果
自定义事件
最终效果:点击删除按钮后,可以更改相应数据,并实时传递给视图
例:点击 py 后的 “删除” 按钮,呈现效果如下:
组件内部绑定事件, 需要用到 this.$emit(“事件名”,参数)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--view层:模版-->
<div id="app-4">
<todo>
<todo-title slot="todo-title" :title="title"></todo-title>
<!-- :index="index" 给模版参数赋值,:是v-bind的缩写 @是v-on的缩写 remove222是自定义方法名-->
<todo-items slot="todo-items" v-for="(item,index) in todoItems"
:item="item" :index="index" @remove222="removeItems(index)"></todo-items>
</todo>
</div>
<!-- 导入vue.js -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component("todo",{
template:
'<div>\
<slot name="todo-title"></slot>\
<ul>\
<slot name="todo-items"></slot>\
</ul>\
</div>'
});
Vue.component("todo-title",{
props: ['title'],
template: '<div>{{title}}</div>'
});
Vue.component("todo-items",{
props: ['item'],
//定义方法 remove111() 在同一个对象中
template: '<li>{{item}}<button @click="remove111">删除</button></li>',
methods: {
remove111: function () {
//自定义事件分发
//通过 this.$emit 将自定义方法与组件方法绑定,参数依次为【自定义方法名,入参】
this.$emit('remove222',this.index);
}
}
});
var app4 = new Vue({
el: '#app-4',
data: {
title: "书籍列表",
todoItems: ["java", "py", "c"]
},
//只能绑定当前组件的方法
methods: {
removeItems: function (index) {
//一次删除一个元素,splice()是js操作array的万能方法。参数为【开始索引,删除元素个数,添加元素内容(可省略)】
this.todoItems.splice(index,1);
}
}
})
</script>
</body>
</html>