1.计算属性
模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护,因此负责逻辑放在计算属性中来写,必须要有return,只能做同步,立即得到结果。
计算属性与函数的区别
计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。也就是只要 myName还没有发生改变,多次访问 reversedMessage计算属性会立即返回之前的计算结果,而不必再次执行函数。而函数则会调用几次就计算几次。
<div id="box">
{{myComputedName}}
</div>
<script>
new Vue({
el: "#box",
data: {
myName: "abc"
},
computed: {
myComputedName() {
//功能是将首字母大写
return myName.substring(0, 1).toUpperCase() + myName.substring(1,);
}
}
})
</script>
计算属性默认只有 getter,不过在需要时你也可以提供一个 setter:
computed: {
myComputedName: {
// getter
get: function () {
return this.myName;
},
// setter
set: function (newValue) {
this.myName = newValue;
}
}
}
当在浏览器控制台上给myComputedName赋值时,setter会被调用,myName也会被更新。
2.侦听器
Vue 通过 watch 选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。如下例:myText是被监听的状态。
// 重视过程,监听一个值得改变,不用返回值,异步同步
watch: {
myText(newval, oldval){ //新value值,老value值
setTimeout(() => {
this.list = this.dataList.filter(item => item.includes(newval))
}, 2000)
}
},
3.组件
注册组件
组件命名规范:
你给予组件的名字可能依赖于你打算拿它来做什么。当直接在 DOM 中使用一个组件 (而不是在字符串模板或单文件组件) 的时候,我们强烈推荐遵循 W3C 规范中的自定义组件名 (字母全小写且必须包含一个连字符)。这会帮助你避免和当前以及未来的 HTML 元素相冲突。
注意:
- 组件起名字若用驼峰写法,在html中调用的时候必须用
-
连接 - template只能有一个根节点
- 组件之间是孤岛,无法直接访问组件的状态或方法
<script>
// 全局定义navbar组件
Vue.component("nav-bar", {
// 定义html模板,只能写行内样式
template: `<div style="background-color:red"></div>`,
//data必须是函数写法
data() {
return {
myText: "1111"
}
},
methods: {},
computed: {},
watch: {},
// 给navbar定义子组件,只能在navbar中模板内调用
components: {
"child": {
template: `<div style="background-color:yellow">child</div>`
}
}
})
</script>
动态组件
动态选择组件,每次切换都会销毁切换钱的组件,没有复用 ,若有input框切换后不会保留输入的内容 <component :is="which"></component>
这样写会保证不会销毁切换前的组件,输入的内容在切换后得以保存。
<div id="box">
<button @click="which='list'">list</button>
<button @click="which='home'">home</button>
<button @click="which='bar'">bar</button>
<keep-alive>
<component :is="which"></component>
</keep-alive>
</div>
<script>
Vue.component("home", {
template: `
<div>
home
<input type="text">
</div>`
})
Vue.component("list", {
template: `
<div>
list
</div>`
})
Vue.component("bar", {
template: `
<div>
bar
</div>`
})
// 根组件
new Vue({
el: "#box",
data: {
which: "home"
}
})
</script>
组件间通信
每个组件都是一座孤岛,组件之间不能直接传递信息,但是可通过间接通信传递信息。
父组件传信息给子组件,是通过使用子组件时定义一个属性,再由子组件props接收。所有的 props都使得其父子 props 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。
类型检查中 type 可以是下列原生构造函数中的一个:
String
Number
Boolean
Array
Object
Date
Function
Symbol
<div id="box">
<navbar myname="aaa" :istrue="true"></navbar>
<navbar myname="bbb" :istrue="false"></navbar>
</div>
<script>
// 全局定义navbar组件
Vue.component("navbar", {
// navbar子组件接收父组件(根组件)传来的属性myName
// props:["myname"],
// 类型验证方法
// props: {
// myname:Boolean
// },
//属性验证,默认属性
props: {
myname: String,
default: true
},
// 定义html模板,只能写行内样式
template: `<div style="background-color:red">
<button @click="left" v-show="istrue">left</button>
{{myname}}
{{myText}}
123
</div>`,
//data必须是函数写法
data() {
return {
myText: "1111",
istrue: ""
}
},
methods: {
left() {
console.log("left");
}
},
})
// 根组件
new Vue({
el: "#box"
})
</script>
子组件给父亲传递信息,是通过在使用子组件时绑定一个事件。使用$emit(“父组件中事件名”, 返回参数)
<div id="box">
<navbar @show="handleshow"></navbar>
</div>
<script>
// 父传子用属性
// 子传父使用事件绑定,this.$emit("事件名",参数)触发事件
// 注册navbar子组件
Vue.component("navbar", {
template: `<div>
<button @click="handleClick">点击</button>
</div>`,
methods: {
handleClick() {
this.$emit("show", 10000);
}
}
})
// 根组件(父组件)
new Vue({
el: "#box",
data: {
isTrue: true
},
methods: {
handleshow(value) {
this.isTrue = !this.isTrue;
console.log(value);
}
}
})
</script>
插槽
当组件渲染的时候, 将会被替换为组件标签间的内容。插槽内可以包含任何模板代码,包括 HTML:
<div id="box">
<child>
<!-- 具名插槽,指定位置 -->
<!-- <button slot="a">a</button> -->
<!-- 无名插槽,将button全部塞进插槽-->
<!-- <button>a</button>
<button>b</button> -->
<!-- 新版slot用法 -->
<template>
<button>a</button>
</template>
</child>
</div>
<script>
Vue.component("child", {
template: `
<div>
<slot name="a"></slot>
<slot></slot>
</div>`,
})
// 根组件
new Vue({
el: "#box",
})
</script>
4.过渡
在进入/离开的过渡中,会有 6 个 class 切换。
v-enter
:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。v-enter-active
:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。v-enter-to
:2.1.8 版及以上定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时v-enter
被移除),在过渡/动画完成之后移除。v-leave
:定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。v-leave-active
:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。v-leave-to
:2.1.8 版及以上定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 v-leave被删除),在过渡/动画完成之后移除。
动画样式
<style>
.w-enter-active {
animation: test 1.5s;
}
.w-leave-active {
animation: test 1.5s reverse;
}
//定义关键帧
@keyframes test {
0% {
opacity: 0;
transform: translateX(100px);
}
100% {
opacity: 1;
transform: translateX(0);
}
}
</style>
过渡普通写法
<transition enter-active-class="w-enter-active" leave-active-class="w-leave-active">
<div v-show="isTrue">111111</div>
</transition>
简写,添加name后会在显示过渡时自动寻找w-enter-active类,离开时同样自动寻找w-leave-active
<transition name="w">
<div v-show="isTrue">22222</div>
</transition>
增加默认效果,在页面加载完成的时候就显示过渡效果
<transition name="w" appear>
<div v-show="isTrue">22222</div>
</transition>
多个过渡,只针对在同一时间只能显示一个, 必须加key或不同的标签才有过渡效果
<transition name="w">
<div v-if="isTrue" key="1">333333</div>
<div v-else key="2">444444</div>
</transition>
让过渡先进后出或先出后进mode=“in-out”/mode=“out-in”
<transition name="w" mode="in-out">
<div v-if="isTrue" key="1">333333</div>
<div v-else key="2">444444</div>
</transition>
多个组件之间切换添加过渡效果component
当有相同标签名的元素切换时,需要通过 key attribute 设置唯一的值来标记以让 Vue 区分它们,否则 Vue
为了效率只会替换相同标签内部的内容。
当多个组件切换时会销毁切换前的组件,若组件中有输入框并且输入了内容,那么切换别的组件再切换回去,输入的内容会丢失,而keep-alive标签是让切换前的标签继续存活,这样输入的内容就不会丢失了,提高了用户体验。
<!-- 给组件切换添加动画 -->
<keep-alive>
<transition name="w" mode="out-in">
<!--此组件可通过动态绑定is属性改变使用的组件-->
<component :is="which"></component>
</transition>
</keep-alive>
列表过渡
<!-- 方法一 -->
<!-- <ul v-show="dataList.length">
<transition-group name="w">
<li v-for="(data, index) in dataList" :key="data">
{{data}}
<button @click="handleDel(index)">del</button>
</li>
</transition-group>
</ul> -->
<!-- 方法二 -->
<!-- 将transition-group改为ul标签 -->
<transition-group name="w" tag="ul" v-show="dataList.length">
<li v-for="(data, index) in dataList" :key="data">
{{data}}
<button @click="handleDel(index)">del</button>
</li>
</transition-group>
状态过渡
<div id="box">
<input v-model.number="number" type="number" step="20">
<p>{{ animatedNumber }}</p>
</div>
<script>
new Vue({
el: '#box',
data: {
number: 0,
tweenedNumber: 0
},
computed: {
animatedNumber: function () {
return this.tweenedNumber.toFixed(0);
}
},
watch: {
number: function (newValue) {
gsap.to(this.$data, { duration: 0.5, tweenedNumber: newValue });
}
}
})
</script>
Tip
加油,兄弟们!