Personal blog: raptazure.github. IO /#/post/17

I happened to see a post on V2EX about the electron vue Boilerplate, someone recommended quasar framework in the comment section, went to the official website for a look, a set of code can simultaneously do SPA, PWA, BEX, SSR, Hybrid Mobile apps and multi-Platform Desktop apps, although the idea of write once and deploy Everywhere has been seen many times, But the heavyweight framework of Vue suddenly made me want to give it a try, so let’s just do it.

What to do

  • Todo already has Todoist for me, so let’s go with the Weather app (this is obviously an excuse). Here’s what it looks like.
  • The main functions to be completed are: location and display the current geographical location weather, search for a location weather, background color and weather icon for different situations.

Setup project

  • You have to go throughyarn global add @quasar/cliInstall the Quasar CLI.
  • throughquasar create <folder_name>Create a new project and install dependencies.
  • usequasar devCompile and run. The single-page application should have been compiled and opened automatically in the browser.

Design & Coding

  • Because the function is relatively simple, so even the Web terminal, the content that needs to be displayed is not too much, according to the proportion of the phone design is good, long and narrow feeling, from top to bottom for the search bar, Logo and positioning and obtain the current location of the weather button/weather details.
  • Since there are some things in the generated template that we don’t need, we’ll focus on the main battlefield firstsrc/layoutssrc/pagesThe contents of the folder will be cleaned upsrc/layouts/MainLayout.vueInitialize to the following code:
<template>
  <q-layout view="lHh Lpr lFf">
    <q-page-container>
      <router-view />
    </q-page-container>
  </q-layout>
</template>

<script>
export default {
  name: "MainLayout",
  data() {
    return{}; }};</script>
Copy the code
  • After that, the main task issrc/pages/index.vueLook at the official documentation should be very easy to understand the following code, where../statics/skyline.pngIt’s a town Sillhouette on Pixabayillustration, while the background of the progressive color can be passeduiGradientsLet’s make a selection.
<template>
  <q-page class="flex column">
    <div class="col q-pt-lg q-px-md">
      <q-input
        bottom-slots
        v-model="search"
        placeholder="Search"
        dark
        borderless
      >
        <template v-slot:before>
          <q-icon name="my_location" />
        </template>
        <template v-slot:append>
          <q-btn round dense flat icon="search" />
        </template>
      </q-input>
    </div>

    <template v-if="weatherData">
      <div class="col text-white text-center">
        <div class="text-h4 text-weight-light">Beijing</div>
        <div class="text-h6 text-weitht-light">Clear</div>
        <div class="text-h1 text-weight-thin q-my-lg relative-position">
          <span>27</span>
          <span class="text-h4 relative-position degree">&deg; C</span>
        </div>
      </div>
      <div class="col text-center">
        <img src/>
      </div>
    </template>

    <template v-else>
      <div class="col column text-center text-white">
        <div class="col text-h2 text-weight-thin">
          Quasar
          <br />Weather
        </div>
        <q-btn class="col" flat>
          <q-icon left size="3em" name="my_location" />
          <div>Find my location</div>
        </q-btn>
      </div>
    </template>

    <div class="col skyline"></div>
  </q-page>
</template>

<script>
export default {
  name: "PageIndex",
  data() {
    return {
      search: "".weatherData: null}; }};</script>

<style lang="sass">.q-page background: linear-gradient(to bottom, #136a8a, #267871) .degree top: -44px .skyline flex: 0 0 100px background: url(.. /statics/skyline.png) background-size: contain background-position: center bottom</style>
Copy the code
  • So far, we have implemented the search bar (prototype), the weather (fake at this point) and the corresponding image (not yet added) when there is weather data, the app logo and location button when there is no weather data, and the illustration of the city at the bottom for decoration.

  • Now that you have a rough idea of what the application looks like, it’s time to implement various practical functions, including getting the current geographic location (latitude and longitude) and querying the weather for a specific location (both by city name and by latitude and longitude). If you want to use the OpenWeather API, you need to register your account and save the api-key. If you want to use the api-key, you need to use the. Follow the instructions to install and use app-extension-Dotenv, and remember to recompile in case the environment variables you set are not enabled.

  • Plugins: [“Loading”] can be accessed by this.$q.loading.

  • At the same time, we also calculated the bgClass attribute to switch the gradient background based on the day and night of the target city, so the SPA part is almost complete.

<template>
  <q-page class="flex column" :class="bgClass">
    <div class="col q-pt-lg q-px-md">
      <q-input
        bottom-slots
        @keyup.enter="getWeatherBySearch"
        v-model="search"
        placeholder="Search"
        dark
        borderless
      >
        <template v-slot:before>
          <q-icon @click="getLocation" name="my_location" />
        </template>
        <template v-slot:append>
          <q-btn round dense flat @click="getWeatherBySearch" icon="search" />
        </template>
      </q-input>
    </div>
    <template v-if="weatherData">
      <div class="col text-white text-center">
        <div class="text-h4 text-weight-light">{{ weatherData.name }}</div>
        <div class="text-h6 text-weitht-light">{{ weatherData.weather[0].main }}</div>
        <div class="text-h1 text-weight-thin q-my-lg relative-position">
          <span>{{ Math.round(weatherData.main.temp) }}</span>
          <span class="text-h4 relative-position degree">&deg; C</span>
        </div>
      </div>

      <div class="col text-center">
        <img
          :src=" `https://openweathermap.org/img/wn/${weatherData.weather[0].icon}@2x.png` "
        />
      </div>
    </template>

    <template v-else>
      <div class="col column text-center text-white">
        <div class="col text-h2 text-weight-thin">
          Quasar
          <br />Weather
        </div>
        <q-btn @click="getLocation" class="col" flat>
          <q-icon left size="3em" name="my_location" />
          <div>Find my location</div>
        </q-btn>
      </div>
    </template>

    <div class="col skyline"></div>
  </q-page>
</template>

<script>
export default {
  name: "PageIndex",
  data() {
    return {
      search: "".weatherData: null.lat: null.lon: null.apiUrl: "https://api.openweathermap.org/data/2.5/weather".apiKey: process.env.API_KEY
    };
  },
  computed: {
    bgClass() {
      if (this.weatherData) {
        if (this.weatherData.weather[0].icon.endsWith("n")) {
          return "bg-night";
        } else {
          return "bg-day"; }}}},methods: {
    getLocation() {
      this.$q.loading.show();
      navigator.geolocation.getCurrentPosition(position= > {
        this.lat = position.coords.latitude;
        this.lon = position.coords.longitude;
        this.getWeatherByCoords();
      });
    },
    getWeatherByCoords() {
      this.$q.loading.show();
      this.$axios(
        `The ${this.apiUrl}? lat=The ${this.lat}&lon=The ${this.lon}&appid=The ${this.apiKey}&units=metric`
      ).then(response= > {
        this.weatherData = response.data;
        this.$q.loading.hide();
      });
    },
    getWeatherBySearch() {
      this.$q.loading.show();
      this.$axios(
        `The ${this.apiUrl}? q=The ${this.search}&appid=The ${this.apiKey}&units=metric`
      ).then(response= > {
        this.weatherData = response.data;
        this.$q.loading.hide(); }); }}};</script>

<style lang="sass">.q-page background: linear-gradient(to bottom, #136a8a, #267871) &.bg-night background: linear-gradient(to bottom, #232526, #414345) &.bg-day background: linear-gradient(to bottom, #00b4db, #0083b0) .degree top: -44px .skyline flex: 0 0 100px background: url(.. /statics/skyline.png) background-size: contain background-position: center bottom</style>
Copy the code

More Platforms

Just writing a web app isn’t going to meet our expectations for the framework, so let’s start adapting to other platforms.

Electron – macOS

  • Since I’m currently using macOS, it runsquasar dev -m electronYou can build Weather App for macOS. (Laughter)
  • The initial window size can be passedsrc-electron/main-process/electron-main.jsWidth and height to make the application appear slimmer from the start.
  • But the ability to find a location doesn’t work becausegeolocation apiDoesn’t work in electron, so, we need to pairgetLocation()Make some changes, and you can passhttps://freegeoip.appTo get the location, and then it works:
getLocation() {
    this.$q.loading.show();
    if (this.$q.platform.is.electron) {
      this.$axios.get("https://freegeoip.app/json/").then(response= > {
      this.lat = response.data.latitude;
      this.lon = response.data.longitude;
      this.getWeatherByCoords();
    });
  } else {
    navigator.geolocation.getCurrentPosition(position= > {
      this.lat = position.coords.latitude;
      this.lon = position.coords.longitude;
      this.getWeatherByCoords(); }); }}Copy the code

Electron – Windows

  • inquasar.conf.jsIn theelectron.packageaddplatform: 'win32'.
  • Run againquasar build -m electronBuild the Windows version and open it with a virtual machine!

Cordova – iOS

  • It must be installedXcodeRun,quasar dev -m iosCan be debugged.
  • But it turns out that getting the location still doesn’t work because we didn’t install itcordova-plugin-geolocationIn thesrc-cordovaRunning in thecordova plugin add cordova-plugin-geolocationAnd, insrc-cordova/config.xmlAdd the location of ios in:
<edit-config target="NSLocationWhenInUseUsageDescription" file="*-Info.plist" mode="merge">
    <string>need location access to find things nearby</string>
</edit-config>
Copy the code
  • The recompile run should work fine.

Cordova – Android

  • It must be installedAndroid StudioRun,quasar dev -m androidCan be debugged.
  • However, it still doesn’t work to get the location. Check chrome debug and find that it is HTTPquasar.config.jsIn thedevSever.httpstrueAlso note whether the Emulator’s Android version supports itgeolocation

Conclusion

To be honest, it is very attractive to implement the whole platform in one codebase. Although there will be various problems in the process of adaptation, it has saved a lot of manpower and resources (especially for simple applications). Incidentally, the above code can be found in this repository