目录
创建vue项目
npm init vite@latest beimao-h5 -- --template vue-ts

我们使用的是-h5
npm i @nutui/nutui
在src里面的main文件中
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
// 注意:这种方式将会导入所有组件
import NutUI from "@nutui/nutui";
// 采用按需加载时 此全局css样式,需要删除
import "@nutui/nutui/dist/style.css";
createApp(App).use(NutUI).mount("#app");
插件在package.json
- {
- "name": "beimao-h5",
- "private": true,
- "version": "0.0.0",
- "type": "module",
- "scripts": {
- "dev": "vite",
- "build": "vue-tsc --noEmit && vite build",
- "preview": "vite preview"
- },
- "dependencies": {
- "@nutui/nutui": "^3.1.22",
- "axios": "^0.27.2",
- "dayjs": "^1.11.3",
- "path": "^0.12.7",
- "pinia": "^2.0.14",
- "pinia-plugin-persist": "^1.0.0",
- "ts-md5": "^1.2.11",
- "vue": "^3.2.37",
- "vue-router": "^4.0.16"
- },
- "devDependencies": {
- "@vitejs/plugin-vue": "^3.0.0",
- "typescript": "^4.6.4",
- "vite": "^3.0.0",
- "vue-tsc": "^0.38.4"
- }
- }
加入后进行安装
npm install
在src的main.ts里面进行加入东西
-
- import { createApp } from 'vue'
-
- import App from './App.vue'
- //导入我们的路由文件
- import Router from './router/index'
- //导入store
- import store from './store/index'
- // 注意:这种方式将会导入所有组件
- import NutUI from "@nutui/nutui";
- // 采用按需加载时 此全局css样式,需要删除
- import "@nutui/nutui/dist/style.css";
- const app = createApp(App)
- //使用京东 NutUI
- .use(NutUI)
- //实用路由
- app.use(Router)
- //使用store
- app.use(store);
- app.mount('#app')
根据里面的内容,加入相应的文件夹以及ts文件
加入router文件夹,在里面创建index.ts文件,这里面是路由
- import { createRouter, createWebHashHistory } from "vue-router";
-
- const routes = [
- {
- path: '/',
- name: "home",
- component: () => import("@/views/Index.vue"),
-
- },
- {
- path: '/category',
- name: "category",
- component: () => import("@/views/Category.vue"),
-
- },
- ]
-
- const router = createRouter({
- history: createWebHashHistory('/'),
- routes
- })
-
- export default router
建立store文件夹,在里面创建index.ts文件以及appStore.ts文件
index.ts文件
- import { createPinia } from 'pinia'
- import piniaPluginPersist from 'pinia-plugin-persist'
-
- const store = createPinia()
- store.use(piniaPluginPersist)
-
- export default store
appStore.ts文件
- import { defineStore } from 'pinia'
-
- const appStore = defineStore({
- id: 'app',
- state: () => {
- return {
- user: { id: 0, userId: "" },
- token: "",
- }
- },
- getters: {
-
- },
- actions: {
-
- },
- // 开启数据缓存
- persist: {
- enabled: true,
- strategies: [
- {
- key: 'com.beiyou.h5',
- storage: localStorage,
- }
- ]
- }
- })
-
- export default appStore;
建立views文件夹,里面建立Index.vue
Index.vue
- <template>
- <div>你好苍老师div>
- template>
在在外层的vite.config.ts文件中进行配置文件
- import { defineConfig } from 'vite'
- import vue from '@vitejs/plugin-vue'
- import path from "path";
- // https://vitejs.dev/config/
- export default defineConfig({
- plugins: [vue()],
- server: {
-
- port: 4000, // 你需要定义的端口号
-
- proxy: {
- "/api": {
- target: "http://localhost:8080/",
- changeOrigin: true,
- },
-
- },
- },
- resolve: {
- // 配置路径别名
- alias: {
- '@': path.resolve(__dirname, './src'),
- }
- },
- })
当path爆红的时候,安装path
npm install path
删除components里面的文件
在src文件夹下面的App文件里面修改内容
- <template>
- <div>
- home
- div>
- template>
- <script setup lang="ts">
-
- script>
建立http文件夹管理页面拦截
建立index.ts
- import axios, {
- AxiosRequestConfig,
- AxiosRequestHeaders,
- AxiosResponse,
- } from "axios";
-
- import { storeToRefs } from "pinia";
- import appStore from "@/store/appStore";
- let { token } = storeToRefs(appStore());
-
- const state = {
- ok: 0,//请求成功状态码
- 401: "ERR_BAD_REQUEST"
- };
-
- //返回数据规则
- interface IResponseData
{ - status: number;
- message?: string;
- data: T;
- code: string;
- }
-
- //请求默认配置规则
- type TOption = {
- baseURL: string;
- timeout: number;
- };
-
- //默认配置
- const config = {
- baseURL: "",
- timeout: 30 * 1000,
- withCredentials: true,
- };
-
-
- let loading: any = null;
-
- class Http {
- service: any;
- constructor(config: TOption) {
- //实例化请求配置
- this.service = axios.create(config);
-
- //请求拦截
- this.service.interceptors.request.use(
- (config: AxiosRequestConfig) => {
- // loading = ElLoading.service({ fullscreen: true, text: '加载中...' });
-
- if (token.value) {
- (config.headers as AxiosRequestHeaders).Authorization = token.value;
- }
- return config;
- },
- (error: any) => {
- loading.close();
- return Promise.reject(error);
- }
- );
-
- //响应拦截
- this.service.interceptors.response.use(
- (response: AxiosResponse) => {
- // loading.close();
-
-
- const data = response.data;
-
- const { code } = data;
-
- if (code == undefined) {
- //如果没有返回状态码,直接返回数据,针对于返回数据为blob类型
- return response;
- } else if (code !== 0) {
- //ElMessage.error(data.message);
- return Promise.reject(data);
- }
- // code == 0 的时候,提取我们只关注的Api数据data
- // console.log(response);
- return response.data.data;
- },
- (error: any) => {
- loading.close();
- if (error.code === state[401]) {
- // ElMessage.error("请求失败:" + error.message);
- setTimeout(() => {
- localStorage.removeItem('com.beiyou.h5')
- window.location.href = '/#/login'
- }, 1000);
- }
- return Promise.reject(error);
- }
- );
- }
-
- get
(url: string, params?: object, data = {}): Promise> { - return this.service.get(url, { params, ...data });
- }
-
- post
(url: string, params?: object, data = {}): Promise> { - return this.service.post(url, params, data);
- }
-
- put
(url: string, params?: object, data = {}): Promise> { - return this.service.put(url, params, data);
- }
-
- delete
( - url: string,
- params?: object,
- data = {}
- ): Promise
> { - return this.service.delete(url, { params, ...data });
- }
- }
-
- export default new Http(config);

有些配置爆红在tsconfig.json里面加入
"baseUrl": ".",
"paths": {
"@/*": [
"src/*"
]
}
加入后的整体样子
- {
- "compilerOptions": {
- "target": "ESNext",
- "useDefineForClassFields": true,
- "module": "ESNext",
- "moduleResolution": "Node",
- "strict": true,
- "jsx": "preserve",
- "sourceMap": true,
- "resolveJsonModule": true,
- "isolatedModules": true,
- "esModuleInterop": true,
- "lib": [
- "ESNext",
- "DOM"
- ],
- "skipLibCheck": true,
- "baseUrl": ".",
- "paths": {
- "@/*": [
- "src/*"
- ]
- }
- },
- "include": [
- "src/**/*.ts",
- "src/**/*.d.ts",
- "src/**/*.tsx",
- "src/**/*.vue"
- ],
- "references": [
- {
- "path": "./tsconfig.node.json"
- }
- ]
- }
上面就是配置好的全部文件以及文件里面的构成
这里为止我们该有的配置已经配置完毕,接下来就是写界面
在src的App.vue里面写入
- <template>
-
- <router-view>router-view>
- <nut-tabbar @tab-switch="tabSwitch" :bottom="true">
- <nut-tabbar-item tab-title="首页" icon="home">nut-tabbar-item>
- <nut-tabbar-item tab-title="分类" icon="category">nut-tabbar-item>
- <nut-tabbar-item tab-title="发现" icon="find">nut-tabbar-item>
- <nut-tabbar-item tab-title="购物车" icon="cart">nut-tabbar-item>
- <nut-tabbar-item tab-title="我的" icon="my">nut-tabbar-item>
- nut-tabbar>
- template>
-
- <script setup lang="ts">
- import { useRoute, useRouter } from "vue-router";
- const route = useRoute();
- const router = useRouter();
- const tabSwitch = (item: any, index: any) => {
- console.log(item, index);
- if (index === 1) {
- router.push({ name: "category" });
- }
- if (index === 0) {
- router.push({ name: "home" });
- }
- };
- script>
:bottom="true">
import { useRoute, useRouter } from "vue-router";
const route = useRoute();
const router = useRouter();
const tabSwitch = (item: any, index: any) => {
console.log(item, index);
if (index === 1) {
router.push({ name: "category" });
}
if (index === 0) {
router.push({ name: "home" });
}
};
解析:
:支持页面跳转 :bottom="true":让下面的首页等在底部
这里就要在路由里面加入一个分支,是category的路由分支
- {
- path: '/category',
- name: "category",
- component: () => import("@/views/Category.vue"),
-
- },
在views里面创建Category.vue文件写入
<template>这是分类页template>
开始正式写vue
在主页面加入一个滚动的公告栏
"华为畅享9新品即将上市" :scrollable="true" :background="`rgba(251, 248, 220, 1)`" :color="`#D9500B`">
在公告栏下面加入一个轮播图
- <nut-swiper :init-page="page" :pagination-visible="true" pagination-color="#426543" auto-play="3000">
- <nut-swiper-item v-for="item in list" :key="item">
- <img :src="item" alt="" />
- nut-swiper-item>
- nut-swiper>
轮播图的script
- import { reactive, toRefs, onMounted } from 'vue';
- export default {
- setup() {
- const state = reactive({
- page: 2,
- list: [
- 'https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg',
- 'https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg',
- 'https://storage.360buyimg.com/jdc-article/welcomenutui.jpg',
- 'https://storage.360buyimg.com/jdc-article/fristfabu.jpg'
- ]
- });
- onMounted(() => {
- setTimeout(() => {
- state.list.splice(1, 1);
- }, 3000);
- });
- return { ...toRefs(state) };
- }
- };
轮播图的样式
- <style lang="scss" scoped>
- .nut-swiper-item {
- line-height: 150px;
- img {
- width: 100%;
- height: 100%;
- }
- }
- style>