如何使用 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,我们有一个应用程序开发团队,所以如果您有任何问题,请随时与我们联系!
