Vue
二、过渡&动画效果
元素在显示和隐藏时,实现过滤或者动画的效果。常用的过渡和动画都是使用 CSS 来实现的
在 CSS 中操作trasition
(过滤 )或 animation
(动画)达到不同效果
为目标元素添加一个父元素 , 让父元素通过自动应用 class 类名来达到效果
过渡与动画时,会为对应元素动态添加的相关 class 类名:
- xxx-enter :定义显示前的效果。
- xxx-enter-active :定义显示过程的效果。
- xxx-enter-to : 定义显示后的效果。
- xxx-leave : 定义隐藏前的效果。
- xxx-leave-active :定义隐藏过程的效果。
- xxx-leave-to :定义隐藏后的效果。
2.1 过滤效果
- 为目标元素添加父元素
<transition name="xxx">
- 定义 class 过渡样式
指定过渡样式: transition
指定隐藏时的样式: opacity(持续的时间)/其它
<style>
/*显示或隐藏的过渡效果*/
.lx-enter-active,
.lx-leave-active {
transition: opacity 1s;
/*过渡,渐变效果 1秒*/
}
/*显示前或隐藏后的效果*/
.lx-enter,
.lx-leave-to {
opacity: 0
/*都是隐藏效果*/
}
/* 可以设置不同的进入和离开动画 */
/*显示过渡效果*/
.lxl-enter-active {
transition: all 1s;
/*all 所有效果,持续1秒 */
}
/*隐藏过渡效果*/
.lxl-leave-active {
transition: all 5s;
}
/*显示前或隐藏后的效果*/
.lxl-enter,
.lxl-leave-to {
opacity: 0;
/*都是隐藏效果*/
transform: translateX(10px);
/*水平方向 X 坐标移动10px*/
}
</style>
</head>
<body>
<div id="app1">
<button @click="show = !show">渐变过渡</button>
<!--在目标元素上添加此元素,结合name值来指定样式-->
<transition name="lx">
<p v-if="show">hello world</p>
</transition>
</div> <br>
<!--可以设置不同的进入和离开动画 -->
<div id="app2">
<button @click="show = !show">渐变平滑过渡</button>
<!--在目标元素上添加此元素,结合name值来指定样式-->
<transition name="lxl">
<p v-if="show">hello world</p>
</transition>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript">
var vm1 = new Vue({
el: '#app1',
data: { show: true }
})
var vm2 = new Vue({
el: '#app2',
data: { show: true }
})
</script>
</body>
2.2 动画效果
CSS 动画用法同 CSS 过渡,只不过采用 animation 为指定动画效果
点击按钮后, 文本内容有放大缩小效果
在 <p>
元素上增加样式 style="display: inline-block"
<style>
/*显示过程中的动画效果*/
.bounce-enter-active {
animation: bounce-in 1s;
/*bounce-in引用了下面@keyframes中定义的持续3秒*/
}
/*隐藏过程中的动画效果*/
.bounce-leave-active {
animation: bounce-in 3s reverse;
/*reverse 相反的顺序*/
}
/* @keyframes 用于实现动画样式 */
@keyframes bounce-in {
0% {
/*持续时长的百分比,如持续1s,0%表示当0秒,50%表示当0.5秒,100%表示当1秒*/
transform: scale(0);
/*缩小为0*/
}
50% {
transform: scale(1.5);
/*放大1.5倍*/
}
100% {
transform: scale(1);
/*原始大小*/
}
}
</style>
<body>
<div id="example-2">
<button @click="show = !show">放大缩小动画</button> <br>
<transition name="bounce">
<p v-if="show" style="display: inline-block">陪你学习,伴你成长 </p>
</transition>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript">
new Vue({
el: '#example-2',
data: { show: true }
})
</script>
</body>
2.3 Vue 内置指令
- v-html 内容按普通 HTML 插入,可防止 XSS 攻击
- v-show 根据表达式的真假值,切换元素的 display CSS 属性来显示隐藏元素
- v-if 根据表达式的真假值,来渲染元素
- v-else 前面必须有 v-if 或 v-else-if
- v-else-if 前面必须有 v-if 或 v-else-if
- v-for 遍历的数组或对象
- v-on 绑定事件监听器
- v-bind 用于绑定元素属性
- v-model 在表单控件或者组件上创建双向绑定
- v-once 一次性插值,当后面数据更新后视图数据不会更新
- v-pre 可以用来显示原始插入值标签 {{}} 。并跳过这个元素和它的子元素的编译过程。加快编译。
- v-text
等价于 {{}} 用于显示内容,但区别在于: {{}} 会造成闪烁问题, v-text 不会闪烁 - v-cloak
如果想用 {{}} 又不想有闪烁问题,则使用 v-cloak 来处理,步骤如下:
1 在被 Vue 管理的模板入口节点上作用 v-cloak 指令
2 添加一个属性选择器 [v-cloak] 的CSS 隐藏样式: [v-cloak] {display: none;}
原理:默认一开始被 Vue 管理的模板是隐藏着的,当 Vue 解析处理完 DOM 模板之后,会自动把这个样式去除,然后就显示出来。
<style>
/*将带有 v-clock 属性的标签隐藏*/
[v-cloak] {
display: none;
}
</style>
<body>
<!-- 在被 Vue 管理的模板入口节点上作用 v-cloak 指令-->
<div id="app" v-cloak>
<!-- 用QQ浏览器刷新页面时, {{}} 会有明显闪烁现象,
原因: 是浏览器从上往下依次解析, 会先把 {{ message }} 当作标签体直接先渲染,
然后 Vue 再进行解析 {{ message }} 变成了 message 的值: 'hello mengxuegu' -->
<h3>{{ message }}</h3>
<h3>{{ message }}</h3>
<h3 v-text="message"></h3>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript"> new Vue({ el: '#app', data: { message: 'hello mengxuegu' } }) </script>
</body>
2.4 注册与使用自定义指令
1、注册全局指令:
// 指令名不要带 v-
Vue.directive('指令名', {
// el 代表使用了此指令的那个 DOM 元素
// binding 可获取使用了此指令的绑定值 等
inserted: function (el, binding) {
// 逻辑代码
}
})
2、注册局部指令
directives : {
'指令名' : { // 指令名不要带 v-
inserted (el, binding) {
// 逻辑代码
}
}
}
3、使用指令:
- 引用指令时,指令名前面加上 v-
- 直接在元素上在使用即可 : v-指令名=‘表达式’
<body>
<div id="app">
<p v-upper-text="lx"></p>
自动获取焦点:<input type="text" v-focus>
</div>
<script src="./node_modules/vue/dist/vue.js" type="text/javascript"></script>
<script type="text/javascript">
// 1. 注册一个全局 v-upper-text 指令,注意指令名不要带 v-
Vue.directive( 'upper-text', {
// 因为是样式,所以不需要元素插入到DOM中,就好像link引入CSS文件时并不关心元素是否加载
bind: function (el) { el.style.color = 'red' },
// el 代表使用了此指令的那个 DOM 元素
// binding 可获取使用了引指令的绑定值 等
inserted: function (el, binding) {
// 将在 v-upper-text 指令中获取到的值,变成大写输出到标签体中
el.innerHTML = binding.value.toUpperCase()
}
})
new Vue({
el: '#app',
data: {
lx: '好好学习,天天向上'
},
//2. 注册一个局部指令 v-focus
directives: {
'focus': {
//和js行为有关的操作,最好在inserted中执行,和样式相关的操作都可在bind中执行
inserted: function (el) {
// 聚焦元素
el.focus()
}
}
}
})
</script>
</body>
三、TodoMVC实战练习
GitHub:https://github.com/tastejs/todomvc-app-template
拉去项目后使用cmd操作npm install
控制台操作npm install vue@2.6.10
引入<script src="./node_modules/vue/dist/vue.js" type="text/javascript"></script>
四、过滤器和插件
1、过滤器
- 过滤器对将要显示的文本,先进行特定格式化处理,然后再进行显示
- 注意:过滤器并没有改变原本的数据, 只是产生新的对应的数据
全局过滤器:
Vue.filter(过滤器名称, function (value1[,value2,...] ) {
// 数据处理逻辑
})
局部过滤器:在Vue实例中使用 filter 选项 , 当前实例范围内可用
new Vue({
filters: {
过滤器名称: function (value1[, value2, ...]) {
// 数据处理逻辑
}
}
})
过滤器可以用在两个地方:双花括号 {{}} 和 v-bind 表达式:
<!-- 在双花括号中 -->
<div>{{数据属性名称 | 过滤器名称}}</div>
<div>{{数据属性名称 | 过滤器名称(参数值)}}</div>
<!-- 在 `v-bind` 中 -->
<div v-bind:id="数据属性名称 | 过滤器名称"></div>
<div v-bind:id="数据属性名称 | 过滤器名称(参数值)"></div>
<body>
<div id="app">
<h3>过滤器接收多个参数:</h3>
<p>{{content | contentFilter}}</p>
<input type="text" :value="content | contentFilter">
<h3>过滤器接收多个参数:</h3>
<p>{{vueScore | add(javaScore, pythonScore)}}</p>
</div>
<script src="node_modules/vue/dist/vue.js" type="text/javascript"></script>
<script type="text/javascript">
/*定义全局过滤器: 过滤敏感数据*/
/*Vue.filter('contentFilter',function (value) {
if (!value) return ''
return value.toUpperCase().replace('TMD','***').replace('SB','***')
})*/
new Vue({
el: '#app',
data: {
content: '小伙子,TMD就是个SB',
vueScore: 80,
javaScore: 95,
pythonScore: 90
},
//局部过滤器
filters: { //不要少了 s
contentFilter(value) { //value是调用时 | 左边的那个属性值
if (!value)
return ''
return value.toUpperCase().replace('TMD', '***').replace('SB', '***')
},
add(num1, num2, num3) { //num1是调用时 | 左边的那个属性值
return num1 + num2 + num3
}
}
})
</script>
</body>
2、插件
- 插件通常会为 Vue 添加全局功能,一般是添加全局方法/全局指令/过滤器等
- Vue 插件有一个公开方法 install ,通过 install 方法给 Vue 添加全局功能
- 通过全局方法 Vue.use() 使用插件,它需要在你调用 new Vue() 启动应用之前完成.
定义一个js:
(function () {
// 声明 MyPlugin 插件对象
const MyPlugin = {}
MyPlugin.install = function (Vue, options) {
// 1. 添加全局方法
Vue.myGlobalMethod = function () {
alert('MyPlugin插件: 全局方法生效')
}
// 2. 添加全局指令
Vue.directive('my-directive', {
inserted: function (el, binding) {
el.innerHTML = "MyPlugin插件 my-directive:" + binding.value
}
})
// 3. 添加实例方法
Vue.prototype.$myMethod = function (methodOption) {
alert('Vue 实例方法生效:' + methodOption)
}
}// 将插件添加到 window 对象中
window.MyPlugin = MyPlugin
})() // 不要少了括号(),让它立即执行
<body>
<div id="app">
<!-- 引用指令时不要少了 v- -->
<span v-my-directive="content"></span>
</div>
<script src="node_modules/vue/dist/vue.js" type="text/javascript"></script>
<script src="js/plugins.js" type="text/javascript"></script>
<script type="text/javascript">
// 1.引入自定义插件 MyPlugin
// 如果报错:Uncaught ReferenceError: MyPlugin is not defined
// 解决方法: 查看 plugins.js 是否引入,如果引入还是报错,检查 js 语法,特别是最后一行 不要少了括号 ()
Vue.use(MyPlugin)
// 2. 创建 Vue 实例, 模板中使用引用全局指令 v-my-directive="content"
var vm = new Vue({
el: '#app',
data: { content: 'hello' }
})
// 3. 调用自定义的全局方法, 所以是 Vue 调用,不是 vm
Vue.myGlobalMethod()
// 4. 调用 Vue 实例方法,所以是 vm 调用,不是 Vue
vm.$myMethod('helloworld')
</script>
</body>