Interesting problems encountered in Vue & Vue cli 3.0 project

Keywords: Javascript Front-end Vue-cli Vue.js scss

1. The problem that custom fonts do not work on ios system

Background: the blogger recently introduced the third-party font provided by the design into the project during development. It is normal on computers and Android phones, but it does not work on Apple phones. Finally, it is found that ios does not support this font, and the font formats supported by different systems are also different:
After searching, I found a fontmin plug-in for font conversion to generate format fonts. The fontmin plug-in uses the following:
Compression tool is "fontmin"
Finally, in the global font file of the project, assign and paste the newly generated css content. Pay attention to the path change:

@font-face {
    font-family: "PingFangSC";
    src: url("PingFang-Medium.eot"); /* IE9 */
    src: url("PingFang-Medium.eot?#iefix") format("embedded-opentype"), /* IE6-IE8 */
    url("PingFang-Medium.woff") format("woff"), /* chrome, firefox */
    url("PingFang-Medium.ttf") format("truetype"), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
    url("PingFang-Medium.svg#PingFangSC") format("svg"); /* iOS 4.1- */
    font-style: normal;
    font-weight: normal;
}

2. Blocking automatic access to web pages

Recently, bloggers found that the content displayed on Google browsers of different users was different. Finally, they found that it was caused by the automatic translation of the browser, but different users may have different translation settings, which can only be disabled together, that is, the automatic translation cannot be performed when the page is opened. After searching, I found the following solutions:
Change the lang in the project template html to "zh CN"
Namely: < HTML lang = "zh CN" >
Add the following content to the head: < meta name = "Google" content = "notranslate" >, that is, Google prohibits translation
All codes:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="google" content="notranslate">
  <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <title><%= htmlWebpackPlugin.options.title %></title>
  </head>
  <body>
    <noscript>
      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

3. Summary of common methods

Record summary of common functions in daily projects (I)

4. template solves the problem of V-for and V-IF sharing

Template is used as a template placeholder to help us wrap elements, but during the loop, the template will not be rendered to the page.
We usually encounter a situation in the development process. The traversal experience has if judgment conditions for display. At this time, we may think of using v-if in v-for, such as:

<div class="my-list" v-for="(item,index) in list" :key="index" v-if="index%2===0">{{item}}</div>

However, because the priority of v-for is higher than that of v-if, it will cause unnecessary waste of resources.
Then what shall I do?
1. Solution 1 - set another div on the periphery

<div class="my-list-content" v-for="(item,index) in list" :key="index">
	<div class="my-list" v-if="index%2===0">{{item}}</div>
</div>

But this will add a layer of div demo that doesn't work.
2. Solution 2 - template

<template v-for="(item,index) in list">
	<div :key="index" class="my-list" v-if="index%2===0">{{item}}</div>
</template>

Template can well solve the problem of v-for and v-if sharing, as well as the problem of more useless elements. However, it should be noted that the template function cannot be set: the key attribute can only be set on its children. Therefore, if there are multiple children, each child needs to be assigned a key.

<template v-for="(item,index) in list">
	<div :key="index+'list'" class="my-list">{{item}}</div>
	<div :key="index+'list1'" class="my-list1">{{item}}</div>
	<div :key="index+'list2'" class="my-list2">{{item}}</div>
</template>

5. mixin mixed file

Mixin provides a very flexible way to distribute reusable functionality in Vue Components. A mixed object can contain any component option. When a component uses mixed objects, the options of all mixed objects will be "mixed" into the options of the component itself. The mixed object can contain any component options, and can define Data, methods, Components, LifeCycle Hooks (life cycle functions), Directives (instructions), routing hook functions, etc.

Scenario application:
There are two very similar components. Their basic functions are the same, but there are enough differences between them. They may share some business logic, but their page structure is different. At this time, you can use mixin to reuse the code. (similar to the JS library, the exposed methods achieve the effect of function reuse. Different from the JS library, it inherits all objects in vue script, including life cycle, data and methods)

Write a mixed file:
Mixin.js

export default {
  data () {
    return {
      // Commodity display
      productShow: false,
      // Video loading
      isVideoOk: false
    };
  },
  mounted () {},
  computed: {},
  methods: {
    // Video playback
    setPlay () {
      const myVideo = this.$refs.myVideo;
      if (myVideo) {
        myVideo.play();
      }
    },
    // Show product list
    handlePlpOpen () {
      this.productShow = true;
    },
    // Close product list
    handlePlpClose () {
      this.productShow = false;
    },
    // page refresh 
    handleReload () {
      this.$router.go(0);
    },
    // Full screen
    setVideoFull () {
      const myVideo = this.$refs.myVideo;
      if (myVideo) {
        myVideo.webkitRequestFullScreen();
      }
    }
  }
};

Mixed file import:
1 - local mixing

import Mixin from '../Mixin/Mixin.js'	// First introduce the mixed object
export default {
    mixins:[Mixin],		// Then register the mixed object you introduced
}

2 - Global blending
Add the following code in main.js:

import Mixin from '../Mixin/Mixin.js'
Vue.mixin(Mixin);

Blending rules:
1. Data, computed and other data objects will be recursively merged internally, and component data will take precedence in case of conflict;
2. Hook functions with the same name such as created and mounted will be combined into an array and will be called. But the hook of the object will be called before the hook of the component itself.
3. components, methods, directives and other objects will be merged into the same object. If the same key value pair appears, the key in the current component has priority

be careful:
Use global blending with caution. If global blending is used, it will affect each newly created Vue instance

6. Set page title

When we develop web pages, we often find that web pages have corresponding page titles. How is this set.
As follows:
1. Add the following to vue.config.js:

module.exports = {
  chainWebpack: config => {
    config
      .plugin('html')
      .tap(args => {
        args[0].title = 'Page title';
        return args;
      });
  }
};

2. Add routing guard:

router.beforeEach((to, from, next) => {
  if (to.meta.title) {
    document.title = 'Page title' + '-' + to.meta.title;
  }
  next();
});

7. Problems in history mode

1. Access to static resources and multiple paths (parent-child routing) in history mode:
The actual problem is the access path of the project configuration. You only need to add the following code in the vue.config.js file

module.exports = {
  publicPath: '/', // Access path
  outputDir: 'dist', // Packed File 
  assetsDir: 'static', // Static resource package
};

2. The build package file cannot be accessed directly in history mode. Problem:
After consulting, it is impossible to access directly in this mode. If I want to access, I can only access from the service. According to the official method, I need to use the express connect history API fallback plug-in
1. First npm install both
2. Add files around the project:
prod.server.js

// Introducing express
const express = require('express');
// Introducing middleware to solve the history mode
const history = require('connect-history-api-fallback');
// Listening port
const port = 9998;
const app = express();
// Using middleware
app.use(history());
// Set static file path
app.use(express.static('./dist'));
// Listening port
module.exports = app.listen(port, function (err) {
  if (err) {
    console.error(err);
  } else {
    console.log(`Project started successfully,Service running on\nhttp://localhost:${port}\n`);
  }
});

3. Add a run instruction in package.json:

"scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint",
    "review": "node prod.server.js"  // newly added
  },

4. Start the service and access the package file: npm run review

8. css and scss custom global variables

Background: when we are developing a page, we usually use some global attributes, such as page theme color. At this time, we can set a css global variable. When we need to change the color later, we can directly change the global color.
Bloggers usually use css and scss styles. Take these two as examples:
1. css global variable

// css version
body {
    --themeColor: #42b983;
    --fontColor: #231815;
    --themeBackColor: #42b983;
}

Call:

html {
  font-size: 14px;
  color: var(--themeColor);
}

2. scss global variable

// scss version
$themeColor: #42b983;
$fontColor: #231815;
$themeBackColor: #42b983;

Configure scss global support

module.exports = {
  css: {
    loaderOptions: {
      sass: {
        prependData: `
          @import "@/assets/styles/theme.scss";
        `
      }
    }
  }
};

Call:

html {
  font-size: 14px;
  color: $themeColor;
}

9. Custom global directives

Customizing global directives in Vue projects

10. Customize global plug-ins

Customizing global plug-ins in Vue Projects - Global Loading plug-ins

11. Customize global components

Customizing global components in Vue projects

12. Disable alert globally

Add the following js to the project template html

<script type="text/javascript">
 window.alert = (e) => {
  return false;
}
</script>

Posted by robinhood on Wed, 06 Oct 2021 22:03:30 -0700