如何使用 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,我們有一個應用程序開發團隊,所以如果您有任何問題,請隨時與我們聯繫!