vue3-vite2-blog-h5

A simple version of the mobile terminal blog. The front-end project is mainly built with Vue3’s latest syntax sugar

  1. PC side blog online preview address: www.rasblog.com
  2. PC side blog warehouse address: github.com/Sujb-sus/vu…
  3. H5 terminal blog warehouse address: github.com/Sujb-sus/vu…

The project structure

technology

First, REM adaptation

  1. Installing a plug-inyarn add amfe-flexible postcss-pxtorem -S
  • amfe-flexibleIs to configure a scalable layout scheme, mainly by setting 1 rem to viewWidth / 10
  • postcss-pxtoremPostcss is a plugin for generating REM units from pixel (PX) units
  1. In the main. Ts importamfe-flexible
import "amfe-flexible";
Copy the code
  1. inpostcss.config.jsconfigurationpostcss-pxtorem
module.exports = {
  plugins: {
    "postcss-pxtorem": {
      rootValue: 37.5.propList: ["*"],}}};Copy the code
  • RootValue is set by dividing the width of the design draft by 10. Assume that the design draft is 375, that is, rootValue is set to 37.5
  • PropList is to set the attributes to be converted. This * means to convert for all units (px)

2. Add a CSS prefix

  1. Installing a plug-inyarn add autoprefixer -D
  2. inpostcss.config.jsconfigurationautoprefixer
module.exports = {
  plugins: {
    autoprefixer: {
      overrideBrowserslist: ["Android 4.1"."iOS 7.1"].grid: true,}}};Copy the code
  • OverrideBrowserslist: compatible configuration for browsers
  • Grid: true for IE enable grid layout prefix

Common components are written in TSX syntax

// svgIcon.tsx
import { defineComponent, computed } from "vue";

export default defineComponent({
  name: "svgIcon".props: {
    name: {
      type: String.required: true,}},setup(props) {
    const iconName = computed(() = > ` #${props.name}`);
    return () = > (
      <>
        <svg class="icon" aria-hidden="true">
          <use xlinkHref={iconName.value}></use>
        </svg>
      </>); }});Copy the code
  • DefineComponent encapsulates the setup function and returns the options object, giving the component the correct argument type inference under TS
  • <use xlink:href={iconName.value}>Need to change to hump form<use xlinkHref={iconName.value}>Otherwise there will be grammar problems

Four,<script setup>Syntactic sugar

1. The parent component passes the value to the child component

<! -- Parent component's HTML -->
<List :showTitle="false" :params="params"></List>
Copy the code
// 
interfaceProps { showTitle? :boolean; params? :object;
}
const props = withDefaults(defineProps<Props>(), {
  showTitle: true.params: undefined});Copy the code
  • definePropsDefining the props type
  • withDefaultsProvides the props default value
  • The two<script setup>Inside can be used without additional import

2. Child components pass values to parent components

<! -- Parent component's HTML -->
<LabelSelect @changeLabel="changeLabel" ref="label"></LabelSelect>
Copy the code
// The parent component 
const changeLabel = (labelName: string) = > {
  params.type = labelName;
};
Copy the code
// 
const emit = defineEmits(["changeLabel"]);
emit("changeLabel", labelName);
Copy the code
  • defineEmitsDefines the method name of the response parent component that needs to be defined before it can respond via emit()
  • emit('changeLabel', data)ChangeLabel is the method name of the response, and labelName is the value to be passed to the parent component

3. Logic reuse

  • With the use… Start with a hump. Define a useClickLike function and export it.
// useClickLikes.ts
import { ref, computed } from "vue";

function useClickLike(requestApi: Function) {
  let currentId = ref(""); / / the current ids
  let isLike = ref(false); // Whether to like
  let likeList = ref<string[] > ([]);// Thumbs-up list

  const handleLikes = (id: string) = > {
    if (likeList.value.includes(id)) {
      isLike.value = true;
      likeList.value.splice(likeList.value.indexOf(id), 1);
    } else {
      isLike.value = false;
      likeList.value.push(id);
    }
    currentId.value = id;
    return requestApi({ _id: id, isLike: isLike.value }).catch((err: any) = > {
      console.log(err);
    });
  };

  return {
    handleLikes,
  };
}

export default useClickLike;
Copy the code
  • Reference it in a VUE file, go in first, and then deconstruct the function logic you need
import useClickLike from "@/useMixin/useClickLike";
// Like logic
const { handleLikes } = useClickLike(apiUpdateLikes);
Copy the code
  • HandleLikes can be used directly in HTML templates
<div class="footer-item" @click.stop="handleLikes(item._id)"></div>
Copy the code

4. Use of computed and watch

import { computed, watch } from 'vue'

const getLikesNumber = computed(
    () = > (id: string, likes: number) = >
      likeList.value.includes(id) ? likes + 1 : likes
  );

watch(props.params, (NewVal, oldVal) = > {
    pageindex.value = 1
    hasLoad.value = false
    loading.value = false
    finished.value = false
    list.value = []
    getBlogList()
  })
Copy the code
  • For computed syntax, like vue2, watch syntax is slightly different: props. Params is the object to listen on, newVal is the latest value to listen on, and oldVal is the old value
  • Specific grammar can see the official document: v3.cn.vuejs.org/api/compute…

5. Use of VUex

import { useStore } from "vuex";

const store = useStore();
// Get the getLabelList method under the Label module actions
const getLabelList = () = > store.dispatch("label/getLabelList");
getLabelList(); // Execute the method directly
// Get the labelList attribute under the label module getters
const labelList = store.getters["label/labelList"];
Copy the code
  • Other specific usage please refer to the official document: next.vuex.vuejs.org/zh/guide/mo…

6. Use vue-Router

  • Configure the routing file,createWebHashHistoryMaking hash Patterns
  • /:pathMatch(.*)*Match all routes for redirection
  • This parameter is used to import a routing fileimport.meta.globCan not be used directlyimportImport,importThis is fine at development time, but the packaged file will not recognize the routing file
import { createRouter, createWebHashHistory, RouteRecordRaw } from "vue-router";
import Tabbar from ".. /components/tabbar";
// Identify all views/ folder name/*.vue files
// Only /views/ folder name/*.vue can be identified
const modules = import.meta.glob(".. /views/*/*.vue");
const loadComponent = (component: string) = >
  modules[`.. /views/${component}.vue`];

const routes: Array<RouteRecordRaw> = [
  {
    path: "/home".component: loadComponent("home/index"),
    meta: {
      title: "Home page",}},... {path: "/:pathMatch(.*)*".redirect: "/home",},];const router = createRouter({
  history: createWebHashHistory(),
  routes,
});

export default router;

Copy the code
  • Gets the Query parameter carried by the route
import { useRouter } from "vue-router";
const route = useRouter();
const id = route.currentRoute.value.query["id"];
Copy the code

The back-end service

You must first open the back-end service interface and connect to the MongoDB database, otherwise the front-end project cannot be previewed. The service interface here is actually reusing the interface of the WALL-blog project on the PC side. So if you want to add data in the admin background, you need to move to the repository: github.com/Sujb-sus/vu… .

There are three projects in this warehouse: PC management terminal (admin), PC client, and background server. Server project is actually the server directory of this project, in order to facilitate everyone’s preview, I Copy a Copy over.

  • Client: the PC side of a blog
  • Admin: blog management end, is used to add article data, tag data and so on
  • Server: Provides interface service data to blogs

Enable the back-end interface service

Method 1: Move to the warehouse address mentioned above

The warehouse is described in detail, and the main process is as follows:

  1. View precautions, first install and connect the localMongoDBDatabase, start the service
  2. Start theadminProject, you can manually add data through the management background

Method 2. Connect directly in this projectMongoDBThe database

  1. Before starting the project, install the MongoDB database locally.

  2. Configure the database name, user name, and password in the server/config.js file. The information can be customized, but needs to be synchronized with Step 3.

// server/config.js
export default {
  env: process.env.NODE_ENV,
  port,
  auth,
  log,
  mongodb: {
    username: "wall".// Database user
    pwd: 123456.// Database password
    address: "localhost:27017".db: "wallBlog".// Database name}};Copy the code
  1. Start localmongoService to initialize the database inserver/config.jsSome necessary information for configuration;
> mongo // Start the mongo service
> show dbs // Displays the database list
> use wallBlog // Create a wallBlog database
> db.createUser({user:"wall".pwd:"123456".roles: [{role:"readWrite".db:'wallBlog'}]}) // Create a wall user in wallBlog database with password 123456
> show users // Show which users the library has
> db.auth("wall"."123456"); // The database authenticates the user and password. 1 is successfully authenticated
Copy the code
  1. Enter theserverDirectory, install dependencies, and start services
cd server // Enter the server directory
yarn // Install dependency packages
yarn server // Enable the back-end interface. If the interface succeeds, the database connection is successful
Copy the code

Matters needing attention

  1. env.d.tsFiles: Modules written in TS are still published in JS, so you need a D.ts file to mark the type of a js library surface object
  2. models/index.tsFile: Used to define the type of data returned by the interface. Each data type needs to be defined, otherwise there will be problems when packaging THE HTML rendering data of the VUE file. The export needs to beexport type {... }Format export
  3. components/noData.tsxFile: When referencing a static image, you need to import it in the form of a module import. When using the image path directly in HTML packaging, the image path will not be automatically resolved
  4. styles/common/iphone_x.scssDocumentation: provides bottom spacing for the iPhonex full screen series
  5. tsconfig.jsonFile: strict: true Enables all strict type checks

Reference documentation

  1. Ts Chinese document: www.tslang.cn/docs/handbo…
  2. Vite Chinese document: cn.vitejs.dev/config/