编者按:本文由夏风在众成翻译平台上翻译。
Vue的声明式特性实践
滑动选项卡
目前针对移动设备的Cordova应用程序和渐进式的Web应用程序非常流行。提升用户体验和交互的关键是传递出原生的视觉效果和感觉,这并不总是一件容易的事情。当然,新建有样式装饰的多选复选框(checkboxes)和单选按钮(radio buttons)是很容易的,但是提供我们所追求的质量飞跃的真正特性是基于用户交互的。
滑动选项卡将内容分割成不同的页面,并且它允许用户使用手指将自己想要的页面滑到当前视图。那如果,在用户拖拽页面的同时,这个应用程序随着拖拽逐渐改变自己的外观呢?是不是听起来很酷炫但是有点难呢?让我们来看看用Vue.js实现有多么简单。
开始吧
首先,我们需要一个真正的滑动选项卡组件。有很多可供选择的提供了不同的特性的这样的组件,这里我们将会使用
Onsen UI
提供的选项卡,它允许在滑动的时候执行自定义操作。以防你不知道这个,Onsen UI针对Vue应用程序有一系列的iOS和安卓组件。针对已存在的项目,可以使用NPM或者Yarn安装。
$> npm install onsenui vue-onsenui --save-dev
$> yarn add onsenui vue-onsenui -D
应用程序里必须有的一些文件:
import 'onsenui/css/onsenui.css';
import 'onsenui/css/onsen-css-components.css';
import VueOnsen from 'vue-onsenui';
Vue.use(VueOnsen);
另外,新的项目通过Vue CLI马上就可以开始。它可以可选的添加Vuex和一些其它的特性。
$> vue init OnsenUI/vue-cordova-webpack # For Cordova apps
$> vue init OnsenUI/vue-pwa-webpack # For PWA
这样之后,就可以在这个应用程序中使用这个组件了。
Vue里的滑动选项卡
在Vue模板里用Onsen UI添加一个最小的滑动选项卡非常简单。可以像下面这样定义:
<v-ons-tabbar swipeable :tabs="tabs" />
swipeable
属性可以在应用程序的不同时刻切换允许滑动和不允许滑动,如果有必要的话。
tabs
是一个简单的数组对象,描述了每个选项卡的外观和每个页面、标签和图标属性的内容。这个组件完整的参考页面点击
这里
。
在顶部,可以使用更多的设置来修改默认的表现形式,添加一些额外的自定义的属性设置,可以获得独一无二的应用程序样式。让我们一起来看看吧,例如,为了区分一个应用程序中不同的部分,怎样使用
on-swipe
属性,让它可以在滑动的时候逐渐的改变界面的颜色呢?(在文章的最后有链接到真实的应用程序)。
颜色插值
代码片段:
<template>
<v-ons-page>
<v-ons-toolbar :style="swipeTheme">
<div class="center">Swiping Tab Bar</div>
</v-ons-toolbar>
<v-ons-tabbar
swipeable
position="top"
:tabs="tabs"
:on-swipe="onSwipe"
:tabbar-style="swipeTheme"
/
>
</v-ons-page>
</template>
<script>
import Home from './pages/Home.vue';
import Forms from './pages/Forms.vue';
import Animations from './pages/Animations.vue';
const lerp = (x0, x1, t) => parseInt((1 - t) * x0 + t * x1, 10);
const red = [244, 67, 54];
const blue = [30, 136, 229];
const purple = [103, 58, 183];
export default {
data () {
return {
colors: red,
animationOptions: {},
tabs: [
{
page: Home,
label: 'Home',
theme: red
},
{
page: Forms,
label: 'Forms',
theme: blue
},
{
page: Animations,
label: 'Anim',
theme: purple
}
]
};
},
computed: {
swipeTheme() {
return {
backgroundColor: `rgb(${this.colors.join(',')})`,
transition: `all ${this.animationOptions.duration || 0}s ${this.animationOptions.timing || ''}`
}
}
},
methods: {
onSwipe(index, animationOptions) {
this.animationOptions = animationOptions;
const a = Math.floor(index), b = Math.ceil(index), ratio = index % 1;
this.colors = this.colors.map((c, i) => lerp(this.tabs[a].theme[i], this.tabs[b].theme[i], ratio));
}
}
};
</script>
这个代码使用
v-ons-page
、
v-ons-toolbar
和
v-ons-tabbar
组件新建了一个带有简单的工具栏和选项卡的页面。
tabs
属性包括了一个选项卡数组。
page
和
label
这两个属性都可以被选项卡组件自己使用来描述这个选项卡的内容和外观,但是这并不能阻止我们用自定义的属性如
theme
或者其它的属性。这些主题都是RGB颜色的简单数组。我们马上就可以知道为什么这个形式可以很好的描述主题。
注意,
swipeTheme
计算属性是怎么传递给工具栏的(通过
style
属性)和选项卡的(通过
tabbar-style
属性)。无论什么时候改变这个属性,这两个组件的样式都会更新。在
on-swipe
属性中,也提供了
onSwipe
方法,当用户的手指在屏幕上滑动的时候总是会调用这个方法。但是我们现在怎么合适地改变界面的颜色呢?
线性插值
简单地射线,
线性插值
(在计算机图形学中的“lerp”)是基于一些输入,然后可以生成出两个数值(比如颜色)中间的点的一个公式。比如,我们想在屏幕上把一个点从初始位置X0逐渐移动到终点x1。我们只需要把这两个点一起给这个公式还有这个“完成率”以确定这个点在特定时刻该放置在哪个位置。换句话说,这个比率(或者叫alpha值)描述了我们距离终点有多远。
const lerp = (x0, x1, r) => (1 — r) * x0 + r * x1;
比如,如果我们想生成从x0到x1之间的三个点(不包括x0和x1),第一步需要
r = 0.25
(完成25%);第二步
r = 0.5