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>
效果如下: