Zen and the Art of Vue

Jen Looper

Senior Developer Advocate Lead

Microsoft

@jenlooper

agenda

Examine a theory of creating quality products by positioning ourselves in a mental model contrasting the 'logical' and the 'artistic'

Leveraging that positioning to build an engaging web and mobile app experience

Robert Pirsig, 1971

A book about a road trip on a motorcycle

an analysis of a half-forgotten past existence as a writing professor obsessed with 'good' writing

a comparison of the world experience of a logical, analytical author with traveling companions who are more 'artistic'

a series of 'Chautauquas' or analyses of various philosophical points

a quest to reconcile world views in pursuit of Quality

What is a motorcycle?

A Classicist's point of view

"A motorcycle can be divided according to its components and according to its functions"

the "what" of the motorcycle: its components

 

the "how" of the motorcycle: its functions

"that's all the motorcycle is, a system of concepts worked out in steel."

A Romantic's point of view

"If you were to show an engine...to a romantic it is unlikely he would see much of interest in it. It has no appeal because the reality he sees is its surface."

A 'romantic' viewpoint values the experience of motorcycling more than the machine.

What is a JavaScript framework?

🔧 A system of concepts worked out in code.

 

🎨 A system that makes working with JavaScript more elegant, easier, less error-prone.

What is Vue.js?

🔧 It's just CSS, HTML, and JavaScript

 

🎨 It's elegant CSS, HTML and JavaScript! The API is designed for simplicity. And even the CLI has a UI! 

The "Romantic Mode"

"inspirational, imaginative, creative, intuitive. Feelings rather than facts predominate."

The "Classic Mode"

"proceeds by reason and by laws, seeing the world primarily as underlying form itself."

"The classic and romantic split is between two separate worlds."

The quest

a convergence of the classic and the romantic world views

motorcycle maintenance / motorcycle riding

writing software / enjoying the experience

"Quality"

the fulcrum between

'hip' and 'square'

'romantic' and 'classic'

'technological' and 'humanistic'

How can we achieve Quality?

"At the moment of pure Quality, subject and object are identical"

Text

similar to Zen Buddhism's concept of "just sitting"

 

"not being dominated by feelings of separateness from what s/he's working on"

Bridging the divide between developer and designer: Sarah Drasner

The Zen of Vue

Design

Technology

Docs

"I ... try to remember that the docs aren't an objective artifact describing the reality of Vue - its goal isn't even directly to teach people how to use Vue, but rather to guide their emotional and conceptual development in a way that helps them become more content in their work. So the docs aren't about me or anyone else working on them, but about the relationships between developers and their work using Vue."

- Chris Fritz

what if

you could create a project that would find flow between three platforms without struggle

and that project would help you create a contemplative work of art to aid in your focus?

 

build your own personal mandala

Mandalas represent the cosmos and creating one is an act of meditation on the attainment of enlightenment by visualizing pure lands.

creation as meditation

Create your own sacred geometry

Use the new Vue CLI 3 plugin for NativeScript-Vue!

How?

Use the Vue UI 🌷

create a new project

install the vue-cli-plugin-nativescript-vue

configure the plugin

run the scripts to start the project for web, iOS and Android!

Party on!!

Or, for the purists... 🧘‍♀️

Check out the code

package.json

"dependencies": {
    "nativescript-vue": "^2.2.0",
    "tns-core-modules": "^5.2.2",
    "vue": "^2.6.10",
    "vue-router": "^3.0.2",
    "vuex": "^3.1.0"
  },

main.js / main.native.js

import Vue from 'vue';
import App from '~/App.vue';
import router from './router';
import store from './store';

Vue.config.productionTip = false;

new Vue({
  router,
  store,
  render: (h) => h(App)
}).$mount('#app');
import Vue from 'nativescript-vue';
import App from './App.vue';
import store from './store';

Vue.config.silent = false;

new Vue({
  store,
  render: (h) => h('frame', [h(App)])
}).$start();

Forked templates - App.vue

<template web>
  <div class="w-page">
    <nav>
      <ul class="w-navbar">
        <li class="w-title">{{navbarTitle}}</li>
      </ul>
    </nav>
    <div class="w-container">
      <router-link tag="button" class="w-button" id="homeButton" to="/">Home</router-link>
      <button class="w-button" id="aboutButton" v-on:click="goToAboutPage">About</button>
      <router-view/>
    </div>
  </div>
</template>

<template native>
  <Page>
    <ActionBar :title="navbarTitle"/>
    <GridLayout rows="auto, auto">
      <Button text="Home" @tap="goToHomePage" row="0"/>
      <Button text="About" @tap="goToAboutPage" row="1"/>
    </GridLayout>
  </Page>
</template>

Forked components - HelloWorld for native or iOS/Android versioning

Share styles cross-platform or scope them

ActionBar
  color #42b983

.w-navbar
  color #42b983
  position fixed
  z-index 10000
  height 3em
  width 100%
  top 0px
  left 0px
  margin auto
  list-style none
  display flex
  align-items center
  padding 0 10px
  -webkit-box-shadow -8px 8px 6px -7px #999
  -moz-box-shadow -8px 8px 6px -7px #999
  box-shadow -8px 8px 6px -7px #999

concept: draw on mobile, build mandala and display on web

demo

architecture: 

  • Use Firebase x2

  • Use Vuex

  • Use a new drawing plugin (I built it!)

  • Use a side drawer

  • Use Vuetify on web

"dependencies": {
    "nativescript-vue": "^2.2.0",
    "firebase": "^5.9.0",
    "nativescript-plugin-firebase": "^8.0.1",
    "nativescript-vue-multi-drawer": "0.0.2",
    "nativescript-paint": "^1.0.0",
    "tns-core-modules": "^5.2.2",
    "nativescript-color-picker": "^1.5.0",
    "vuetify": "^1.5.7",
    "vue": "^2.6.10",
    "vue-router": "^3.0.2",
    "vuex": "^3.1.0"
  },

vuex for data manipulation

Create modules to manage different Firebase versions

main.js / main.native.js

import Vue from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';

import Vuetify from 'vuetify';
import 'vuetify/src/stylus/app.styl';

import firebase from 'firebase/app';
// Setup Firebase
...
firebase.initializeApp(config);
...
Vue.use(Vuetify, {
// Setup theme
});

new Vue({
	router,
	store,
	render: h => h(App),
}).$mount('#app');
import Vue from 'nativescript-vue';
import App from './App.vue';
import firebase from 'nativescript-plugin-firebase';
import MultiDrawer from 'nativescript-vue-multi-drawer';
import store from './store';

firebase
 .init({
   //initialization routines here
);
...
Vue.use(MultiDrawer);
Vue.registerElement('PaintPad', () => 
    require('nativescript-paint').PaintPad);

new Vue({
  store,
  render: h => h('frame', [h(App)]),
}).$start();

App.vue

<template web>
  <v-app dark class="primary">
    ...
    <v-content class="bg">
      <router-view/>
    </v-content>
  </v-app>
</template>

<template native>
  <Page actionBarHidden="true">
    <Home/>
  </Page>
</template>
...

<style web lang="stylus">
@import '~styles/style-one';
</style>
<style native lang="stylus">
@import '~styles/style-two';
</style>

Welcome.vue

<template>
  <v-card>
    <v-card-text>
      <h1 align="center">
        Build your personal mandala
      </h1>
    </v-card-text>
    <img src="~/assets/logo_lg.png" class="my-3" contain>
    <v-card-text title>
      <v-btn href="#/build" color="primary" dark large>
        Get Started
      </v-btn>
    </v-card-text>
  </v-card>
</template>

Welcome.native.vue

<template>
<MultiDrawer>
  <StackLayout slot="left">
    <Image
      :src="paintingImage"
      width="50%"
      :visibility="paintingImage ? 'visible' : 'collapsed'"
      stretch="aspectFit"
    />
    ...
  <StackLayout>
    ...
  </StackLayout>
</MultiDrawer>
</template>

<script>
import { PaintPad } from "nativescript-paint";
import { ColorPicker } from "nativescript-color-picker";
import * as platformModule from "tns-core-modules/platform";
import * as fs from "file-system";
import * as imageSource from "image-source";
...

Code sharing as convergence

Find your flow as a developer by building simultaneously for web, iOS, and Android

Focus on user experience by providing native apps appropriate to each platform

Enjoy ease of design and development by using a flexible plugin

"The Buddha, the Godhead, resides quite as comfortably in the circuits of a digital computer or the gears of a cycle transmission as he does at the top of a mountain or in the petals of a flower."

@jenlooper

Gary Gambill, Manuel Saelices, Igor Randjelovic

Zen and the Art of Vue

By Telerik DevRel

Zen and the Art of Vue

Vue.us, NS Dev Day

  • 3,444