计算属性
对于任何复杂逻辑,你都应当使用计算属性
计算属性是定义在computed中的方法,使用计算属性就和使用普通的属性一样
<div id="app">
<p>{{reverseMsg2}}</p>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
msg: "hello"
},
computed: {
reverseMsg2: function () {
// 反转msg
return this.msg.split("").reverse().join("")
}
}
})
</script>
计算属性和方法的区别
我们可以通过在表达式中调用方法来达到同样的效果
<div id="app">
<p>{{reverseMsg2}}</p>
<p>{{reverseMsg1()}}</p>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
msg: "hello"
},
methods: {
reverseMsg1: function () {
return this.msg.split("").reverse().join("")
}
},
computed: {
reverseMsg2: function () {
return this.msg.split("").reverse().join("")
}
}
})
</script>
可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。
然而,不同的是计算属性是基于它们的响应式依赖进行缓存的,只在相关响应式依赖发生改变时它们才会重新求值
这就意味着只要 msg 还没有发生改变,多次访问 reversedMsg2 计算属性会立即返回之前的计算结果,而不必再次执行函数
计算属性相当于是缓存
相比之下,每当触发重新渲染时,调用方法将总会再次执行函数
注意: methods和computed中的方法不能重名
我们为什么需要缓存?
假设我们有一个性能开销比较大的计算属性 A,它需要遍历一个巨大的数组并做大量的计算。然后我们可能有其他的计算属性依赖于 A。如果没有缓存,我们将不可避免的多次执行 A 的 getter!如果你不希望有缓存,请用方法来替代。
插槽
当组件渲染的时候,<slot></slot>
将会被替换为组件。插槽内可以包含任何模板代码,包括 HTML
<div id="app">
<todo>
<!--使用slot属性来对应插槽的名字-->
<todo-title slot="todo-title"></todo-title>
<todo-items slot="todo-items"></todo-items>
</todo>
</div>
<script>
Vue.component("todo", {
// slot就是插槽 name是该插槽的名字
template: "<div> \
<slot name='todo-title'></slot> \
<ul> \
<slot name='todo-items'></slot> \
</ul> \
</div>"
})
Vue.component("todo-title", {
template: "<p>标题</p>"
})
Vue.component("todo-items", {
template: "<li>java</li>"
})
let vm = new Vue({
el: "#app",
data: {},
})
</script>
动态加载数据,还是使用props来接收
<div id="app">
<todo>
<!--使用slot属性来对应插槽的名字-->
<todo-title slot="todo-title" v-bind:title="lan_title"></todo-title>
<todo-items slot="todo-items" v-for="item in lan_items" v-bind:item="item"></todo-items>
</todo>
</div>
<script>
Vue.component("todo", {
// slot就是插槽 name是该插槽的名字
template: "<div> \
<slot name='todo-title'></slot> \
<ul> \
<slot name='todo-items'></slot> \
</ul> \
</div>"
})
Vue.component("todo-title", {
props:["title"],
template: "<p>{{title}}</p>"
})
Vue.component("todo-items", {
props: ["item"],
template: "<li>{{item}}</li>"
})
let vm = new Vue({
el: "#app",
data: {
lan_title: "编程语言列表",
lan_items: ["java", "python", "c++"]
},
})
</script>
自定义事件内容分发
<div id="app">
<todo>
<!--使用slot属性来对应插槽的名字-->
<todo-title slot="todo-title" :title="lan_title"></todo-title>
<todo-items slot="todo-items" v-for="(item, index) in lan_items"
:item="item" :index="index" @remove="removeItems"></todo-items>
</todo>
</div>
<script>
Vue.component("todo", {
// slot就是插槽 name是该插槽的名字
template: "<div> \
<slot name='todo-title'></slot> \
<ul> \
<slot name='todo-items'></slot> \
</ul> \
</div>"
})
Vue.component("todo-title", {
props: ["title"],
template: "<p>{{title}}</p>"
})
Vue.component("todo-items", {
props: ["item", "index"],
template: "<li>{{index}}--{{item}}<button @click='remove'>删除</button></li>",
methods: {
remove: function (index) {
// 自定义事件分发
this.$emit("remove", index)
}
}
})
let vm = new Vue({
el: "#app",
data: {
lan_title: "编程语言列表",
lan_items: ["java", "python", "c++"]
},
methods: {
// 按索引删除列表中的元素
removeItems: function (index) {
this.lan_items.splice(index, 1)
}
}
})
</script>