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
- PC side blog online preview address: www.rasblog.com
- PC side blog warehouse address: github.com/Sujb-sus/vu…
- H5 terminal blog warehouse address: github.com/Sujb-sus/vu…
The project structure
technology
First, REM adaptation
- Installing a plug-in
yarn add amfe-flexible postcss-pxtorem -S
amfe-flexible
Is to configure a scalable layout scheme, mainly by setting 1 rem to viewWidth / 10postcss-pxtorem
Postcss is a plugin for generating REM units from pixel (PX) units
- In the main. Ts import
amfe-flexible
import "amfe-flexible";
Copy the code
- in
postcss.config.js
configurationpostcss-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
- Installing a plug-in
yarn add autoprefixer -D
- in
postcss.config.js
configurationautoprefixer
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
defineProps
Defining the props typewithDefaults
Provides 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
defineEmits
Defines 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,
createWebHashHistory
Making hash Patterns /:pathMatch(.*)*
Match all routes for redirection- This parameter is used to import a routing file
import.meta.glob
Can not be used directlyimport
Import,import
This 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:
- View precautions, first install and connect the local
MongoDB
Database, start the service - Start the
admin
Project, you can manually add data through the management background
Method 2. Connect directly in this projectMongoDB
The database
-
Before starting the project, install the MongoDB database locally.
-
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
- Start local
mongo
Service to initialize the database inserver/config.js
Some 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
- Enter the
server
Directory, 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
env.d.ts
Files: 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 objectmodels/index.ts
File: 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 exportcomponents/noData.tsx
File: 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 resolvedstyles/common/iphone_x.scss
Documentation: provides bottom spacing for the iPhonex full screen seriestsconfig.json
File: strict: true Enables all strict type checks
Reference documentation
- Ts Chinese document: www.tslang.cn/docs/handbo…
- Vite Chinese document: cn.vitejs.dev/config/