Code Sharing with Vue.js

Jen Looper

Senior Developer Advocate, Progress

@jenlooper

Sharing code between your web and mobile apps

A brief history!

Two brave knights

Tiago Alves

Igor Randjelovic

A damsel in distress

Lol I need a code sharing talk STAT

Sallying forth to create a good way to share code

Lol ok, have fun!

Chapter 1: PR Vue

https://github.com/vuejs/vue/pull/7264

Chapter 2: fork the Vue-Loader and make it work for us

https://github.com/nativescript-vue/nativescript-vue-webpack-template

Code Structure

<template web>
    <div class="SealGallery">
        <ul style="padding: 0;">
            <li v-for="seal in seals" :key="seal.id" 
                style="list-style: none; border-bottom: 1px solid #e0e0e0;">
                <div style="display: flex; align-items: center; padding: 10px">
                    {{ seal.name }}
                </div>
            </li>
        </ul>
    </div>
</template>

<template native>
    <StackLayout>
        <ListView :items="seals">
            <v-template>
                <StackLayout orientation="horizontal">
                    <Label :text="item.name" style="vertical-align: center;padding: 10px;"/>
                </StackLayout>
            </v-template>
        </ListView>
    </StackLayout>
</template>

NativeScript-Vue-Loader picks out the pieces to compile

Result

Chapter 3: make webpack do the work

https://github.com/tralves/ns-vue-codeshare-demo

Code Structure

SFCs go here, with naming convention set

Entry points

Shared service

Global styles

SFC structure

<template>
  <Page class="Page">
      <ActionBar title="🐕🐩🐕🐩🐕🐩🐕🐩🐕🐩🐕🐩🐕🐩" class="action-bar" />
      <ScrollView>
      <WrapLayout orientation="horizontal">
          <StackLayout v-for="dog in dogsList" :key="dog" class="card">
              <Image height="100%" width="48%" stretch="aspectFill" :src="dog" />
          </StackLayout>
      </WrapLayout>
      </ScrollView>
    </Page>
</template>
<template>
  <v-container grid-list-md fluid>
    <v-layout wrap>
      <v-flex xs6 sm4 md2 v-for="(dog, index) in dogsList" :key="dog">
        <v-card>
         <v-card-media
          height="200px"
          :src="dog"></v-card-media>
           ...
        </v-card>
      </v-flex>
    </v-layout>
  </v-container>
</template>

Home.vue

Home.web.vue

Entry Points:web

main.web.js

import Vue from 'vue';
import router from 'vue-router';
import Home from './components/Home';
import Vuetify from 'vuetify';

import './styles';

Vue.use(Vuetify, {
  theme: {
    primary: '#3f51b5',
    secondary: '#b0bec5',
    accent: '#8c9eff',
    error: '#b71c1c'
  },
});

new Vue({
  el: '#app',
  router,
  render: h => h(Home),
});

Entry Point:mobile

main.native.js

import Vue from 'nativescript-vue';
import Home from './components/Home';

import './styles';

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

new Vue({

  render: h => h(Home),

}).$start();

SFC Script: identical

<script>
import service from "../shared/service.vue";

  export default {
    mixins: [service],
    created() {
      this.loadDogs();
    }
  };
</script>

Shared Service

/shared/service.vue

<script>
import axios from "axios";

export default {
   data () {
      return {
        dogsList: []
      }
    },
    methods: {
        loadDogs() {
            axios
              .get("https://dog.ceo/api/breeds/image/random/50")
              .then(response => {
                this.dogsList = response.data.message;
              })
              .catch(error => {
                console.log(error);
              });
          },
    }
}
</script>

CSS

page-specific scoped, or global

<style scoped>
  Page {
      background-color: #ffffff;
  }
  .action-bar {
    background-color: #303F9F;
    color: #C5CAE9;
  }
  .card{
    margin: 5;
    color: white;
    border-radius: 5;
    height:250;
  }

</style>
// NativeScript core theme
@import '~nativescript-theme-core/scss/skins/light/index';
@import '~nativescript-theme-core/scss/index';

The result! 🐶

going forward

"vue add

nativescript-vue"

Get ready for Vue 3 and the accompanying Vue CLI 3.x 

  • Vue 3 will make it easier for third party folks like us to develop a custom renderer
  • The Vue CLI will allow easy creation of extensions via plugins so we can extend the CLI if you need to 'bolt on' a mobile app to your existing Vue web app
  • Creation of the Vue CLI 3 plugin is in process - most parts done, only webpack part to be completed: https://github.com/nativescript-vue/vue-cli-plugin-nativescript-vue

Thank you, kind sir, for the NativeScript-Vue implementation.

Hon, you look like you need a drink

Code Sharing with Vue.js

By Telerik DevRel

Code Sharing with Vue.js

for webinar

  • 2,865