返回博客首页
← 所有文章

使用 NativeScript-Vue 进行路由:第二集

2019 年 7 月 30 日 — 作者:Raymond Camden

在我关于 NativeScript-Vue 路由的上一篇文章中,我讨论了如何在 NativeScript-Vue 应用程序中进行基本的路由。我描述了通过手动路由功能提供的简单内置路由,以及它如何让你在应用程序的不同页面之间移动。

在本文中,我将介绍一种不同的技术。我将介绍一个类似选项卡的界面,其中某个导航 UI(想想屏幕底部的选项卡)将在其上方加载不同的组件,而不是更改整个页面(例如,从“列表”页面更改为“详情”页面)。

和以前一样,我要感谢Jen Looper 的帮助!

“Is Component” 方法

Vue 可以做的事情之一是使用动态组件。这是通过 :is 声明实现的。例如

<component :is="someComponent" />

在这个例子中,基本的 component 标签将被渲染为 someComponent 的值。你甚至可以动态切换它。如果 someComponent 指向 Cat 组件,但后来指向 Dog,Vue 将自动处理更新新组件的显示。我写了一个例子,几个月前使用动态表单字段完成的。

这项技术也给了我们一种有趣的方式进行导航。如果我们把 <component> 标签看作我们的“视图”,那么我们就可以通过简单地交换 is 属性的当前值来“导航”。

让我们看一个实际应用的例子。

首先,我们的主“首页”组件

<template>
    <Page class="page">
        <ActionBar :title="currentComponent" class="action-bar" />
        <GridLayout rows="2*, auto" columns="*, *, *">
            <component v-for="component in viewsArray" v-show="component === currentComponent" :is="component" 
            row="0" col="0" colSpan="3"/>
            <Button text='Info' @tap="currentComponent = 'CatInfo'" row="1" col="0" />
            <Button text='Pic' @tap="currentComponent = 'CatPic'" row="1" col="1" />
            <Button text='Log' @tap="currentComponent = 'CatLog'" row="1" col="2" />
        </GridLayout>
    </Page>
</template>

<script>
import CatInfo from './CatInfo';
import CatPic from './CatPic';
import CatLog from './CatLog';

export default {
    data () {
        return {
            viewsArray: [ 'CatInfo', 'CatPic', 'CatLog' ],
            currentComponent: 'CatInfo'
        };
    },
    components: {
        CatInfo, CatPic, CatLog
    }
}
</script>

让我们从标记开始。首先,请注意 GridLayout 的使用。这里的想法是为我们的“视图”设置应用程序的顶部部分,为导航设置应用程序的底部部分。GridLayout 中的第一个元素是 component 标签。从技术上讲,多个标签,因为你可以看到那里使用了 v-for。我们不想同时看到三个视图,所以这是如何工作的?首先要注意使用 v-show 来确保我们一次只看到一个。然后注意相同的位置信息(rowcol),这样组件基本上就会彼此堆叠。最后,底部三个按钮处理导航。

现在让我们看看代码。一组可能的视图在名为 viewsArray 的数组中定义。这就是绑定到上面 component 标签的内容。然后有一个简单的字符串值叫做 currentComponent。如果你回到按钮那里,你会看到那里的逻辑只是改变了字符串的值。

最终的结果是,你可以点击每个按钮来交换当前可见的视图。虽然这些视图没什么特别,但这是 CatInfo

<template>
    <Label text="cat info!" />
</template>

<script>
export default {
    data() {
        return {
        };
    }
}
</script>

这里还有一个例子,CatPic

<template>
    <Image src="https://placekitten.com/400/500" />
</template>

<script>
export default {
    data() {
        return {
        };
    }
}
</script>

最后,应用程序运行时的屏幕截图

Screen shot of the application with the pic tab

你可以在这个 NativeScript Playground 项目中看到整个应用程序,并在你的设备上测试它。有关这项技术的另一个例子,请查看 Jen Looper 的例子这里

使用 Frames

对于下一个例子,我们将做一些比以前更底层的事情。每个 NativeScript 应用程序都使用一个名为 Frame 的核心 UI 元素。Frame 是渲染你的 Page 组件的地方。你可能以前甚至没有注意到这一点。在默认的 NativeScript Vue 应用程序中,你的 app.js 文件将如下所示

import Vue from 'nativescript-vue';

import HelloWorld from './components/HelloWorld';

// Uncommment the following to see NativeScript-Vue output logs
// Vue.config.silent = false;

new Vue({

    template: `
        <Frame>
            <HelloWorld />
        </Frame>`,

    components: {
        HelloWorld
    }
}).$start();

注意 template 属性。它定义了要由 Frame 标签包装的核心布局。HelloWorld 组件本身被包装在一个 Page 中。但是,你被允许修改此布局以创建更高级的布局和导航方案。例如,你可以拥有多个 frame,每个 frame 都有自己的页面,并使用导航来操作它们中的任何一个。每个 frame 将拥有自己的导航历史记录,你可以回到每个 frame 的前面或后面。

对于我们选项卡式应用程序的下一个版本,我们仍然要使用一个 frame,但我们将修改核心布局,以便在应用程序的第一个组件中设置 frame。

首先,这里是 app.js 文件

import Vue from 'nativescript-vue';

import Home from './components/Home';

// Uncommment the following to see NativeScript-Vue output logs
//Vue.config.silent = false;

new Vue({
    render: h => h(Home)
}).$start();

注意,这里没有模板,而是直接渲染我们的主组件 Home。现在让我们看看它。

<template>
    <GridLayout rows="*, auto">
        <ContentView row="0">
            <Frame>
                <CatInfo />
            </Frame>
        </ContentView>

        <Nav row="1" />
    </GridLayout>
</template>

<script>
import CatInfo from './CatInfo';
import Nav from './Nav';

export default {
    data() {
        return {};
    },
    components: {
        CatInfo, Nav
    }
};
</script>

和以前一样,我们希望最终在顶部有一个“视图”,在底部有一个导航栏。(说清楚一点,这是随意的。你的选项卡可以在顶部、右边,任何你想要的地方。)注意 ContentViewFrame 在网格顶部部分的使用。这将是渲染我们内容的地方。由于应用程序的第一个“页面”是硬编码的,它只是直接在那里输入。我们的导航现在被分解到它自己的组件 Nav

<template>

    <GridLayout rows="auto" columns="*, *, *">
        <Button text='Information' @tap="goTo('info')" row="1" col="0" />
        <Button text='Picture' @tap="goTo('pic')" row="1" col="1" />
        <Button text='Log' @tap="goTo('log')" row="1" col="2" />
    </GridLayout>

</template>

<script>
import CatInfo from "./CatInfo";
import CatPic from "./CatPic";
import CatLog from "./CatLog";

export default {
    data() {
        return {
            routes: {
                info: CatInfo,
                pic: CatPic,
                log: CatLog
            }
        };
    },
    methods: {
        goTo(s) {
            this.$navigateTo(this.routes[s]);
        }
    }
};
</script>

和前面的例子一样,选项卡栏被定义为一组按钮。这次我们使用了一个方法 goTo,并将要导航到的路由的名称传递给它。$navigateTo 方法用于处理加载我们的视图,由于我们的应用程序只有一个 Frame 标签,它将自动在其中加载组件。你可以使用 $navigateTo 的参数之一来指定一个 frame,如果你有多个 frame 的话。

和以前一样,每个页面几乎都是一样的,但是要注意,我们现在需要使用 Page 组件。这是 CatInfo 组件

<template>

    <Page class="page">
        <ActionBar title="Cat Information" />
        <Label text="Information about the cat. Lorem ipsum meow." />
    </Page>

</template>

<script>
export default {
    data() {
        return {
        };
    }
}
</script>

这是 CatPic 组件

<template>

    <Page class="page">
        <ActionBar title="Cat Picture" />
        <Image src="https://placekitten.com/400/500" />
    </Page>

</template>

<script>
    export default {
        data() {
            return {};
        }
    };
</script>

和以前一样,你可以在这个 NativeScript Playground 项目中看到整个应用程序。此外,你还可以看到 Jen Looper 的更酷的例子这里。我特别喜欢她的例子的一点是,将“路由”进一步分解,使导航组件更加灵活。

进一步

我希望这些例子(以及上一篇文章中的例子)可以帮助你构建更强大的 NativeScript-Vue 应用程序。

如果你想要一个更高级的例子,你应该查看nativescript-vue-navigator 插件。它提供的体验更接近于“传统”的 Vue 路由,更容易上手。(和以前一样,Jen 有一个很好的例子来演示它的实际应用!)