Vue 动画效果过渡模式
- 相同标签名的元素切换
<div id="demo">
<transition>
<button v-bind:key="isEditing" v-on:click="isEditing = !isEditing">
{{isEditing ? 'save' : 'edit'}}
</button>
</transition>
</div>
<script>
new Vue({
el:'#demo',
data:{
isEditing:true
}
})
</script>
效果如下:
- 多个元素的过渡,可重写为绑定了动态属性的单个元素过渡
<div id="demo2">
<transition name="fade" mode="out-in">
<button v-bind:key="docState" v-on:click="rever">
{{ buttonMessage }}
</button>
</transition>
</div>
<script>
new Vue({
el:'#demo2',
data:{
docState:0
},
methods: {
rever:function(){
this.docState += 1;
if(this.docState > 2){
this.docState = 0
}
}
},
computed: {
buttonMessage:function(){
switch(this.docState) {
case 0: return '按钮一';
case 1: return '按钮二';
case 2: return '按钮三';
}
}
}
})
</script>
<style>
.fade-enter-active,.fade-leave-active{
transition:all 0.3s ease;
}
.fade-leave-active{
opacity:0;
transform: translateX(10px);
}
</style>
效果如下:
- 多个组件的过渡,也可以使用动态组件,不需要使用 key 特性。
<div id = "demo">
<input type="radio" value="A" id="a" name="boy" v-model="view">
<label for="a">A</label>
<input type="radio" value="B" id="b" name="boy" v-model="view">
<label for="a">B</label>
<p>选择结果:{{view}}</p>
<transition name="fade" mode="out-in">
<component v-bind:is="view"></component>
</transition>
</div>
<script>
new Vue({
el:'#demo',
data:{
view:'A'
},
components:{
'A':{
template:'<div>模块 A</div>'
},
'B':{
template:'<div>模块 B</div>'
}
}
})
</script>
<style>
.fade-enter-active,.fade-leave-active{
transition: opacity 0.3s ease
}
.fade-enter,.fade-leave-to{
opacity:0
}
</style>
效果如下:
created:在模板渲染成html前调用,即通常初始化某些属性值,然后再渲染成视图。
mounted:在模板渲染成html后调用,通常是初始化页面完成后,再对html的dom节点进行一些需要的操作。
渲染函数 & JSX
1.渲染多个元素/组件
<div id="demo">
<anchored-heading>
</anchored-heading>
</div>
<script>
Vue.component('anchored-heading',{
render:function(createElement){
return createElement('div',
Array.apply(null,{length:5}).map(function(){
return createElement('p','hi')
})
)
}
})
new Vue({
el:'#demo'
})
</script>
效果如下:
template 中使用的 v-if 和 v-for
<div id="demo2">
<ul v-if="items.length">
<li v-for="item in items">{{ item.name }}</li>
</ul>
<p v-else>No items found.</p>
</div>
<script>
Vue.component('menulist',{
props:['items'],
render:function(createElement){
if(this.items.length){
return createElement('ul', this.items.map(function(item){
return createElement('li',item.name)
}))
}else{
return createElement('p', 'No items found.')
}
}
})
new Vue({
el:'#demo2',
"items.length":false,
data:{
items : [
{ name: 'Foo' },
{ name: 'Bar' }
]
}
})
</script>
效果如下:
过滤器
可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持)。过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符号指示:
<!-- 在双花括号中 -->
{{ message | capitalize }}
<!-- 在 `v-bind` 中 -->
<div v-bind:id="rawId | formatId"></div>
例子:输入value值,首个字母大写
<div id="demo4">
<input v-model="message">
<p>{{ message | capitalize }}</p>
</div>
<script>
new Vue({
el:"#demo4",
data:{
message:'haha'
},
filters:{
capitalize:function(value){
if(!value) return ''
value = value.toString();
return value.charAt(0).toUpperCase() + value.slice(1)
}
}
})
</script>
效果如下:
表单验证
<template>
<div>
<form
id="app"
@submit="checkForm"
action="/something"
method="post"
novalidate="true"
><h3>基础表单验证</h3>
<p v-if="errors.length" id="tip">
<b>提交错误:</b>
<ul>
<li v-for="error in errors">{{ error }}</li>
</ul>
</p>
<p>
<label for="name">Name</label>
<input id="name" v-model="name" type="text" name="name">
</p>
<p>
<label for="age">age</label>
<input id="age" v-model="age" type="number" name="age">
</p>
<p>
<label for="email">email</label>
<input id="email" v-model="email" type="text" name="email">
</p>
<p>
<label for="movie">movie</label>
<select id="movie" v-model="movie" name="movie">
<option>Star Wars</option>
<option>Vanilla Sky</option>
<option>Atomic Blonde</option>
</select>
</p>
<p>
<input type="submit" value="Submit">
</p>
</form>
</div>
</template>
<script>
export default {
data(){
return {
errors: [],
name: null,
age: null,
email: null,
movie: null
}
},
methods:{
checkForm:function(e){
this.errors = [];
if(!this.name){
this.errors.push('请输入姓名');
}
if(!this.age){
this.errors.push('请输入年龄');
}
if(!this.email){
this.errors.push('请输入邮箱');
}else if(!this.validEmail(this.email)){
this.errors.push('请输入正确邮箱')
}
if(!this.errors.length){
return true
}
e.preventDefault();
},
validEmail:function(email){
var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(email); //test() 方法用于检测一个字符串是否匹配某个模式.
}
}
}
</script>
<style>
#tip{overflow: hidden; width: 200px;}
#tip ul li{ list-style: none;}
#tip b{float: left;}
#tip ul{float: right; width:50;}
#app {margin-top:60px; text-align: left; margin-left: 30px; }
#app p{text-align: left; line-height: 30px;}
</style>
效果如下:
自定义滚动事件
比如想为网站的滚动事件添加一些行为,尤其是动画。已有的做法很多,但是代码和依赖最少的方式可能就是使用一个自定义指令创建一个钩子,在特定的滚动事件之后作处理。
<template>
<div id="scroll">
<h1>滚我</h1>
<div class="box" v-scroll="handleScroll">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. A atque amet harum aut ab veritatis earum porro praesentium ut corporis. Quasi provident dolorem officia iure fugiat, eius mollitia sequi quisquam.</p>
</div>
</div>
</template>
<script>
export default {
directives: {
scroll: {
//指令定义
inserted: function(el, binding) {
let f = function(evt) {
if (binding.value(evt, el)) { //此时绑定事件的binding.value是一个表达式,此处为方法handleScroll
window.removeEventListener('scroll', f);
}
};
window.addEventListener('scroll', f);
}
}
},
methods: {
handleScroll: function (evt, el) {
if (window.scrollY > 50) {
el.setAttribute(
'style',
'opacity: 1; transform: translate3d(0, -20px, 0)'
)
}
return window.scrollY > 180
}
}
}
</script>
<style>
body{background: #333;}
#scroll{color: #fff;height: 2000px; margin-top:180px;}
.box{ width: 300px; height: 300px; padding: 10px; border:1px solid #ccc; margin:50px auto 0; background:rgba(0, 0, 0, 0.3); opacity: 0;transition: 1s all cubic-bezier(0.39, 0.575, 0.565, 1)}
.box p{line-height: 28px;}
</style>
效果如下:
注:关于banding.value()
官方文档详解:
el: 指令所绑定的元素,可以用来直接操作 DOM 。
binding: 一个对象,包含以下属性:
name: 指令名,不包括 v- 前缀。
value: 指令的绑定值, 例如: v-my-directive=“1 + 1”, value 的值是 2。
oldValue: 指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
expression: 绑定值的字符串形式。 例如 v-my-directive=“1 + 1” , expression 的值是 “1 + 1”。
arg: 传给指令的参数。例如 v-my-directive:foo, arg 的值是 “foo”。
modifiers: 一个包含修饰符的对象。 例如: v-my-directive.foo.bar, 修饰符对象 modifiers 的值是 { foo: true, bar: true }。
vnode: Vue 编译生成的虚拟节点,查阅 VNode API 了解更多详情。
oldVnode: 上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
使用axios访问API
相关笔记:
1、finally()finally方法用于指定不管 Promise 对象最后状态如何
2、methods:不调用不会执行。mounted:在模板渲染成html后调用,通常是初始化页面完成后,再对html的dom节点进行一些需要的操作。(调用第三方插件可以放在mounted里边)。
3、请求会发送到 https://api.coindesk.com/v1/bpi/currentprice.json,
创建一个 data 里的属性以最终放置信息,然后将会在 mounted 生命周期钩子中获取数据并赋值过去
API 获取数据时的加载状态
获取价格信息
<template>
<div id="demo">
<h1>价格表</h1>
<div v-if="errored">
<p>很抱歉,我们目前无法检索此信息,请稍后再试</p>
</div>
<div v-else>
<div v-if="loading">loading...</div>
<div
v-else
v-for="currency in info"
class="currency"
>
{{ currency.description }}:
<span class="amount">
<span v-html="currency.symbol"></span>
{{ currency.rate_float | currencydecimal}}
</span>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
data () {
return {
info: null,
loading: true,
errored: false
}
},
filters: {
currencydecimal (value) {
return value.toFixed(2)
}
},
mounted () {
axios
.get('https://api.coindesk.com/v1/bpi/currentprice.json')
.then(response => {
this.info = response.data.bpi
})
.catch(error => {
console.log(error)
this.errored = true
})
.finally(() => this.loading = false)
}
}
</script>
效果如下: