Como construir um aplicativo Vue.js Shopify Frontend com Polaris
Publicados: 2019-06-17Nota: este artigo é sobre como construir um aplicativo de página única Vue.js sobre o aplicativo Laravel criado neste artigo. Antes de ler isso, certifique-se de ler o artigo anterior sobre como construir um aplicativo com Laravel, pois usaremos esse código existente.
O que é Vue.js?
Vue.js é uma estrutura de front-end JavaScript, comparável a estruturas semelhantes, como React e originalmente derivada de AngularJS. Comparado com os outros frameworks, ele foi projetado para ser um pouco mais leve, para que você possa usá-lo apenas como uma camada de apresentação apenas se desejar - mas também pode escalá-lo massivamente com gerenciamento de estado completo ou usar um framework em cima do Vue, como como Nuxt.js. Você pode encontrar mais informações sobre o Vue.js aqui.
O que é Polaris?
Polaris é a estrutura de design de interface do usuário da Shopify, comparável a outras estruturas de interface do usuário, como Bootstrap ou SemanticUI. Na Eastside Co, temos uma porta Vue.js da biblioteca para uma interface de usuário consistente em nossos aplicativos.
Configurando o Vue.js para compilação
O Vue vem com o Laravel pronto para uso, mas existem algumas personalizações que facilitarão o desenvolvimento. O Laravel vem com o Laravel Mix, que é um wrapper elegante em torno do Webpack. O Webpack compila todos os seus recursos de front-end para o que você deseja servir para o navegador do cliente - o Laravel vem com uma implementação disso com muitos padrões embutidos. Vamos otimizar um pouco a saída do Webpack. Abra webpack.mix.js na raiz do seu projeto. Altere para:
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” });Aqui nós dissemos ao webpack para alias de arquivos dentro da pasta resources/assets/js para uso em instruções de importação e para reconhecer extensões .vue e .js para que não precisemos usar nomes de arquivos completos em JavaScript. A opção devtool também faz com que o wepack gere mapas de origem para nosso JS compilado para ajudar na depuração no navegador mais rapidamente.
Agora podemos executar o npm para instalar nossas dependências de front-end e executar um servidor para observar as alterações em nossos arquivos JavaScript. Vá até o terminal e digite:
Npm install Npm run devAgora, precisamos conectar nossa rota base do Laravel em nosso aplicativo Vue.
Configurando o Vue.js no Laravel
Precisamos fazer alguns ajustes para obter um andaime decente do Laravel para o Vue. As primeiras coisas que precisamos fazer são importar o Vue para um modelo básico do Twig e, em seguida, criar um ponto de entrada para nosso aplicativo.
Para não confundir as coisas, vamos criar uma nova rota, método do controlador e modelo de galho.
routes/web.php Route::get('/vueapp', 'ShopifyController@vueapp'); app/Http/Controllers/ShopifyController.php public function vueapp() { return view('vueapp'); }Como o Vue vai usar um endpoint que criamos no Laravel, abandonamos a ShopifyAPI - mas isso será usado mais tarde. Agora precisamos conectar o Vue ao nosso novo modelo Twig, que chamamos de vueapp. Crie o seguinte arquivo:
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> O token CSRF é importante - o Laravel passa um token para o Vue para evitar falsificações de solicitações entre sites. Há algumas outras coisas acontecendo aqui - primeiro, <div id=”app”> é a tag div à qual estamos vinculando o Vue, e <app-entry> é um componente Vue personalizado que ainda não construímos, então vamos construir isso em breve.
Construção de andaimes Vue
Em seguida, precisamos criar nosso ponto de entrada de aplicativo para nosso aplicativo. Estamos tratando-o como um componente, mas colocando-o fora da pasta de componentes pré-instalados, pois é o ponto de entrada do front-end para o restante do Vue. Crie um novo arquivo:
resources/js/AppEntry.vue <template> <p>App Entry Point</p> </template> <script> export default { mounted() { console.log('Rendered app entry point') } } </script> Então, a última parte é registrar o componente <app-entry> no bootloader Vue. Dirigir a
recursos/js/app.js
Há muitos comentários aqui do código clichê do Laravel - exclua todo o código e substitua-o pelo seguinte:
require('./bootstrap'); window.Vue = require('vue'); Vue.component('app-entry', require('./AppEntry.vue').default); const app = new Vue({ el: '#app', });Então, nosso componente de entrada foi carregado e o Vue foi inicializado, sendo vinculado ao aplicativo div id. Carregue a rota no seu navegador:
http://localhost:8000/vueapp
E podemos ver com nossos devtools do navegador abertos que o vue foi inicializado. Estamos funcionando!

Como criar um endpoint de API
Agora temos um ponto de entrada, criaremos um novo componente que renderizará uma lista de produtos. Antes de podermos criar o componente de front-end, precisaremos criar um endpoint de API que será efetivamente um proxy da API da Shopify.
O Laravel vem com uma raiz base /api/ configurada automaticamente para chamadas de API, com lógica separada das rotas HTTP. Adicione a seguinte linha:
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; }Navegue até o seu endpoint e você deve obter os dados de volta:

É isso para o endpoint da API - não estamos usando nenhuma autorização, pois este é um guia básico, mas você pode conferir https://laravel.com/docs/5.7/authentication para obter mais informações sobre implementações de autenticação personalizadas, incluindo basic, bearer tokens e oAuth.

Como criar um componente e buscar dados de API
Vamos criar o componente no qual vamos renderizar os produtos - crie um novo arquivo no diretório de componentes:
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>Agora registre o componente no Vue:
resources/js/app.js Vue.component('shopify-products', require('./components/ProductsComponent.vue').default);E solte o componente em nosso modelo de aplicativo:
<template> <div> <shopify-products></shopify-products> </div> </template> Há algumas coisas para explicar com o modelo Vue antes de podermos buscar produtos do endpoint da API e fazer um loop sobre eles. Em primeiro lugar, a lógica por trás da tag <script> - cada componente Vue tem um ciclo de vida que pode ser aproveitado em vários estágios e permite emitir eventos, definir observadores; tudo o que você precisa pode ser codificado aqui.
Você pode descobrir mais sobre componentes de codificação aqui. Começamos apenas adicionando o método data(), que retorna dados que você usará ou vinculará ao componente. Nomeamos uma chave aqui apidata e a criamos como uma string em branco - a razão para isso é que será onde os produtos são armazenados para os componentes - uma vez que codificamos em uma busca após o módulo ser carregado no ciclo de vida.
Para preencher esses dados, vamos adicionar um método, usando axios, que será chamado quando o método created() for executado no ciclo de vida.
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>Os produtos agora estarão disponíveis para o modelo em apidata - usando o loop v-for do Vue, podemos iterar sobre o array no modelo:
Renderizando em Polaris
<template> <div> <div class="card" v-for="product in apidata"> <h5>{{ product.title }}</h5> <p>{{ product.body_html }}</p> </div> </div> </template>Carregue a página e bingo! Aqui estão nossos produtos renderizados:

Ao desenvolver em Vue, a extensão Vue devtools é extremamente útil para depuração. Você pode ver essas ferramentas aqui.
Se usarmos as devtools, podemos ver o valor que nosso objeto de dados apidata recebeu (ou seja, a resposta da API que foi convertida em um array):

Enganchando em Polaris
Portanto, nossa parte final é usar a porta Vue Polaris da EastsideCo para renderizar nossos produtos. Instalamos a biblioteca Polaris via npm:
Npm install @eastsideco/polaris-vueEntão nós o vinculamos ao nosso aplicativo 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', });Agora teremos acesso a tags HTML personalizadas com o nome polaris - você pode ver uma lista completa das tags portadas na página de documentos em http://demo.polaris-vue.eastsideco.io/
Nosso modelo agora foi refatorado para ficar assim:
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>Há muita coisa acontecendo aqui, então vamos detalhar -
A abertura <div> é apenas um contêiner - isso ocorre porque os componentes Vue.js sempre precisam de um elemento raiz. Em seguida, definimos um contêiner CSS para a página usando <polaris-page> .
O
O <polaris-resource-list> no entanto é um componente mais complexo - ele recebe um prop passado, que neste caso estamos passando a resposta para o endpoint da API que criamos. A lista de recursos tem então um slot com escopo definido, no qual estamos criando um <polaris-resource-list-item> . Dentro do slot, você define outro slot - "item" (pense nisso como uma iteração sobre um loop foreach como uma explicação simples) e, em seguida, todo o escopo do slot (que é apidata) é nomeado como adereços do slot. Então, para ter acesso neste ponto às propriedades das iterações atuais, usamos props.item. Esses atributos, como attribute-one e media, são analisados pelo componente e renderizados na biblioteca polaris. O resultado é uma lista básica de produtos:

E aí estamos - uma lista de produtos conectados ao Vue Polaris.
Você pode encontrar uma cópia de trabalho deste código de demonstração em nosso repositório em https://github.com/EastsideCo/polaris-vue.
Na Eastside Co temos uma equipe de desenvolvimento de aplicativos, portanto, se você tiver alguma dúvida, não hesite em entrar em contato!
