如何使用 Polaris 构建 Vue.js Shopify 前端应用程序

已发表: 2019-06-17

注意:本文是关于在本文创建的 Laravel 应用程序之上构建一个 Vue.js 单页应用程序。 在阅读本文之前,请确保您已阅读上一篇关于使用 Laravel 构建应用程序的文章,因为我们将使用该现有代码。

什么是 Vue.js?

Vue.js 是一个 JavaScript 前端框架,可与 React 等类似框架相媲美,最初源自 AngularJS。 与其他框架相比,它的设计要轻一些,因此您可以仅在需要时将其用作表示层 - 但您也可以通过完整的状态管理来大规模扩展它或使用 Vue 之上的框架,例如作为 Nuxt.js。 您可以在此处找到有关 Vue.js 的更多信息。

什么是北极星?

Polaris 是 Shopify 的 UI 设计框架,可与 Bootstrap 或 SemanticUI 等其他 UI 框架相媲美。 在 Eastside Co,我们有一个库的 Vue.js 端口,用于在我们的应用程序中提供一致的 UI。

设置 Vue.js 进行编译

Vue 随 Laravel 开箱即用,但有一些定制可以使开发更容易。 Laravel 带有 Laravel Mix,它是 Webpack 的简洁包装器。 Webpack 将你所有的前端资产编译成你想要提供给客户端浏览器的东西——Laravel 提供了一个包含许多默认值的实现。 让我们稍微优化一下 Webpack 的输出。 在项目的根目录中打开 webpack.mix.js。 将其更改为:

 mix.js('resources/js/app.js', 'public/js') .sass('resources/sass/app.scss', 'public/css'); mix.webpackConfig({ resolve: { extensions: [ '.js', '.vue', ], alias: { '@': path.resolve(__dirname, 'resources/assets/js'), }, }, devtool: “inline-source-map” });

在这里,我们告诉 webpack 为 resources/assets/js 文件夹中的文件设置别名,以便在导入语句中使用,并识别 .vue 和 .js 扩展名,这样我们就不需要在 JavaScript 中使用完整的文件名。 devtool 选项还使 wepack 为我们编译的 JS 生成源映射,以帮助更快地在浏览器中进行调试。

我们现在可以运行 npm 来安装我们的前端依赖项,并运行一个服务器来监视我们的 JavaScript 文件的更改。 前往终端并输入:

 Npm install Npm run dev

现在,我们需要将我们的基本 Laravel 路由挂接到我们的 Vue 应用程序中。

在 Laravel 中设置 Vue.js

为了从 Laravel 到 Vue,我们需要做一些调整才能得到一个像样的脚手架。 我们需要做的第一件事是将 Vue 导入基本 Twig 模板,然后为我们的应用程序创建一个入口点。

为了避免混淆,让我们创建一个新的路由、控制器方法和树枝模板。

 routes/web.php Route::get('/vueapp', 'ShopifyController@vueapp'); app/Http/Controllers/ShopifyController.php public function vueapp() { return view('vueapp'); }

由于 Vue 将使用我们在 Laravel 中创建的端点,我们已经放弃了 ShopifyAPI——但这将在以后使用。 现在我们需要将 Vue 连接到我们命名为 vueapp 的新 Twig 模板中。 创建以下文件:

 resources/views/vueapp.twig <!DOCTYPE html> <html> <head> <title>My VueJs app</title> <meta name="csrf-token" content="{{ csrf_token() }}"> </head> <body> <div> <app-entry></app-entry> </div> <script src="{{ asset('js/app.js') }}"></script> </body> </html>

CSRF 令牌很重要 - Laravel 将令牌传递给 Vue 以防止跨站点请求伪造。 这里还发生了一些其他事情——首先, <div id=”app”>是我们绑定 Vue 的 div 标签,而<app-entry>是我们尚未构建的自定义 Vue 组件,所以我们很快就会建立起来。

搭建 Vue 脚手架

接下来,我们需要为我们的应用程序构建我们的应用程序入口点。 我们将它视为一个组件,但将它放在烘焙组件文件夹之外,因为它是 Vue 其余部分的前端入口点。 创建一个新文件:

 resources/js/AppEntry.vue <template> <p>App Entry Point</p> </template> <script> export default { mounted() { console.log('Rendered app entry point') } } </script>

所以,最后一部分是在 Vue bootloader 中注册<app-entry>组件。 前往

资源/js/app.js

这里有很多来自 Laravel 样板代码的注释 - 删除所有代码并将其替换为以下代码:

 require('./bootstrap'); window.Vue = require('vue'); Vue.component('app-entry', require('./AppEntry.vue').default); const app = new Vue({ el: '#app', });

所以,我们的入口组件已经加载完毕,Vue 已经启动,绑定到 div id 应用程序。 在浏览器中加载路线:

http://localhost:8000/vueapp

我们可以在浏览器 devtools 打开的情况下看到 vue 已初始化。 我们已经启动并运行了!

创建 API 端点

现在我们有了一个入口点,我们将创建一个新组件来呈现产品列表。 在我们可以创建前端组件之前,我们需要创建一个 API 端点,它将有效地成为 Shopify API 的代理。

Laravel 为 API 调用提供了一个自动配置的 /api/ 基本根目录,并带有与 HTTP 路由分离的逻辑。 添加以下行:

 routes/api.php Route::get('/products', 'ShopifyController@products'); We've not created the 'products' method in the ShopifyController, so let's create it: app/Http/Controllers/ShopifyController.php public function products() { $shopifyApi = app('ShopifyAPI'); $products = $shopifyApi->call('GET', '/admin/products.json'); return (array) $products; }

导航到您的端点,您应该会取回数据:

API 端点就是这样 - 我们没有使用任何授权,因为这是一个基本指南,但您可以查看 https://laravel.com/docs/5.7/authentication 以获取有关自定义身份验证实现的更多信息,包括基本、承载令牌和 oAuth。

创建组件并获取 API 数据

让我们创建我们将在其中渲染产品的组件 - 在 components 目录中创建一个新文件:

 resources/js/components/ProductComponent.vue <template> <div id=”root element”>Vue components always need one root element</div> </template> <script> export default { mounted() { console.log('Component loaded') }, data() { return { apidata: "" } }, } </script>

现在在 Vue 中注册组件:

 resources/js/app.js Vue.component('shopify-products', require('./components/ProductsComponent.vue').default);

并将组件放入我们的应用程序模板中:

 <template> <div> <shopify-products></shopify-products> </div> </template>

在我们从 api 端点获取产品并循环它们之前,有一些事情需要用 Vue 模板解释。 首先, <script>标签背后的逻辑——每个 Vue 组件都有一个生命周期,可以在各个阶段利用它,使您能够发出事件、设置观察者; 你需要的任何东西都可以在这里编码。

您可以在此处找到有关编码组件的更多信息。 我们首先添加了 data() 方法,该方法返回您将使用或绑定到组件的数据。 我们在这里命名了一个键 apidata 并将其创建为一个空白字符串 - 这样做的原因是它将是组件存储产品的位置 - 一旦我们在模块在生命周期中加载后在 fetch 中进行编码。

为了填充这些数据,我们将使用 axios 添加一个方法,该方法将在生命周期中执行 created() 方法时调用。

 resources/js/components/ProductComponent.vue <script> export default { mounted() { console.log('Component loaded') }, created() { this.fetchProducts() }, data() { return { apidata: "" } }, methods: { fetchProducts() { axios.get('/api/products').then(response => { this.apidata = response.data.products }) } } } </script>

产品现在将可用于 apidata 下的模板 - 使用 Vue 的 v-for 循环,我们可以遍历模板中的数组:

在 Polaris 中渲染

<template> <div> <div class="card" v-for="product in apidata"> <h5>{{ product.title }}</h5> <p>{{ product.body_html }}</p> </div> </div> </template>

加载页面和宾果游戏! 以下是我们渲染出来的产品:

在 Vue 中开发时,Vue devtools 扩展对于调试非常有用。 您可以在此处查看这些工具。

如果我们使用 devtools,我们可以看到我们的 apidata 数据对象所取的值(即 API 的响应已被强制转换为数组):

在北极星上钩

所以我们的最后一部分是使用 EastsideCo 的 Vue Polaris 端口来渲染我们的产品。 我们通过 npm 安装 Polaris 库:

 Npm install @eastsideco/polaris-vue

然后我们将它绑定到我们的 Vue 应用程序中:

 resources/js/app.js require('./bootstrap'); import PolarisVue from '@eastsideco/polaris-vue/lib/polaris-vue'; import PolarisVueCss from '@eastsideco/polaris-vue/lib/polaris-vue.css'; window.Vue = require('vue'); Vue.component('app-entry', require('./AppEntry.vue').default); Vue.component('shopify-products', require('./components/ProductsComponent.vue').default); Vue.use(PolarisVue); const app = new Vue({ el: '#app', });

我们现在可以访问以 Polaris 命名的自定义 HTML 标签 - 您可以在 http://demo.polaris-vue.eastsideco.io/ 的文档页面上查看移植标签的完整列表

我们的模板现在被重构为如下所示:

 resources/js/components/ProductsComponent.vue <template> <div> <polaris-page> <polaris-card sectioned title="My Shopify Vue App"> Uses EastsideCo port of Polaris to Vue </polaris-card> <polaris-card sectioned> <polaris-layout-section> <polaris-resource-list :items="apidata"> <template slot="item" slot-scope="props"> <polaris-resource-list-item :attribute-one="props.item.title" :attribute-two="props.item.created_at" :media="props.item.image"> </polaris-resource-list-item> </template> </polaris-resource-list> </polaris-layout-section> </polaris-card> </polaris-page> </div> </template>

这里发生了很多事情,所以让我们分解一下 -

开头的<div>只是一个容器——这是因为 Vue.js 组件总是需要一个根元素。 然后我们使用<polaris-page>为页面定义一个 CSS 容器。

布局系统在前面提到的文档中定义得很好。

然而, <polaris-resource-list>是一个更复杂的组件——它需要传入一个 prop,在这种情况下,我们将响应传递给我们创建的 API 端点。 然后资源列表有一个作用域槽,我们在其中创建一个<polaris-resource-list-item> 。 在插槽中,您定义了另一个插槽 - “item”(将其视为对 foreach 循环的迭代,作为一个简单的解释),然后插槽的整个范围(即 apidata)被命名为插槽的 props。 因此,为了在这一点上访问当前迭代的属性,我们使用 props.item。 这些属性如attribute-one 和media 被组件解析并渲染到Polaris 库中。 结果是一个基本的产品列表:

这就是我们 - 插入 Vue Polaris 的产品列表。

您可以在我们的仓库 https://github.com/EastsideCo/polaris-vue 上找到此演示代码的工作副本。

在 Eastside Co,我们有一个应用程序开发团队,所以如果您有任何问题,请随时与我们联系!