Vue学习-项目化


插件全局注册

通用性组件通过插件方式全局注册

index.js:

//component中所有组件全局注册
//通过插件方式
import imgView from './imageView/index.vue'
import Sku from './XtxSku/index.vue'


export const componentPlugins = {
  install(app) {
    //app.component('组件名字',组件的配置对象)
    app.component('imgView', imgView)
    app.component('Sku', Sku)
  }
}

main.js:

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'

// 引入样式
import '@/styles/common.scss'

//引入懒加载指令插件
import { lazyPlugin } from './directives'
import { componentPlugins } from './components/index'

const app = createApp(App)

app.use(createPinia())
app.use(router)
app.use(lazyPlugin)
app.use(componentPlugins)
app.mount('#app')

注册持久化插件:xxx.use()

懒加载插件

import { useIntersectionObserver } from '@vueuse/core'


export const lazyPlugin = {
  install(app) {

    app.directive('img-lazy', {
      mounted(el, binding) {
        // el:绑定的元素
        // binding:binding.value  指令等号后面的表达式的值
        console.log(el, binding);


        const { stop } = useIntersectionObserver(
          el,
          ([{ isIntersecting }]) => {
            console.log(isIntersecting)
            if (isIntersecting) {
              // 进入视口区域
              el.src = binding.value
              stop()
            }
          },
        )

      }
    })
  }
}


asios基础配置

http.js:

import axios from "axios";

const httpInstance = axios.create({
  baseURL: 'http://xxxx',
  timeout: 5000,
})

// 添加请求拦截器
httpInstance.interceptors.request.use(function (config) {
  // 在发送请求之前做些什么
  return config;
}, function (error) {
  // 对请求错误做些什么
  return Promise.reject(error);
});

// 添加响应拦截器
httpInstance.interceptors.response.use(function (response) {
  // 2xx 范围内的状态码都会触发该函数。
  // 对响应数据做点什么
  return response;
}, function (error) {
  // 超出 2xx 范围的状态码都会触发该函数。
  // 对响应错误做点什么
  return Promise.reject(error);
});


export default httpInstance

api.js

import httpInstance from "@/utils/http";



export function getBannerAPI(params = {}) {
  const { distributionSite = '1' } = params
  return httpInstance({

    url: '/home/banner',
    params: {
      distributionSite
    }
  })
}

banner.vue:

const bannerList = ref([])
const getBanner = async ()=>{
  const res = await getBannerAPI()
  // console.log(res);
  bannerList.value = res.data.result
}

onMounted(()=>{
  getBanner()
})

请求拦截器携带token

// 添加请求拦截器
httpInstance.interceptors.request.use(function (config) {
  const userStore = useUserStore()

  const token = userStore.userInfo.token
  if (token) {
    config.headers.Authorization = `Bearer ${token}`
  }

  // 在发送请求之前做些什么
  return config;
}, function (error) {
  // 对请求错误做些什么
  return Promise.reject(error);
});
  1. 从pinia中取出token数据
  2. 按照后端要求拼接token数据

响应拦截器处理失效token


// 添加响应拦截器
httpInstance.interceptors.response.use(function (response) {
  // 2xx 范围内的状态码都会触发该函数。
  // 对响应数据做点什么
  return response;
}, function (error) {
  //统一错误提示
  console.log(error)
  ElMessage({
    type: 'warning',
    message: error.response.data.message
  })

  //401 token失效处理
  if (error.response.status === 401) {
    const userStore = useUserStore()
    userStore.clearUserInfo()
    const router = useRouter()
    router.push('/login')
  }
  return Promise.reject(error);
});

Pinia配置

import { ref } from 'vue'
import { getCategoryAPI } from '@/apis/layoutApi.js'
import { defineStore } from 'pinia'

export const useCategoryStore = defineStore('category', () => {
  //导航列表的逻辑
  const categoryList = ref([])
  const getCategory = async () => {

    const res = await getCategoryAPI()
    // console.log(res);
    categoryList.value = res.data.result
  }

  return { categoryList, getCategory }
})

使用:

import { useCategoryStore } from '@/stores/category';
const categoryStore = useCategoryStore()

  1. defineStore导入并使用:defineStore(‘模块名’, ()=> {})
  2. Pinia 包括两个部分:数据state和 获取数据接口action
  3. 最后以对象格式将state和action return出去

pinia数据持久化

pinia-plugin-persistedstate
运行机制:在设置state的时候自动把数据同步给localstorage,在获取state 数据的同时会优先从localstorage中取出

路由配置

import { createRouter, createWebHistory } from 'vue-router'
import Login from '@/views/Login/index.vue'
import Layout from '@/views/Layout/index.vue'
import Home from '@/views/Home/index.vue'
import Category from '@/views/Category/index.vue'
import SubCategory from '@/views/subCategory/index.vue'
import GoodsDetails from '@/views/Details/index.vue'



const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
  //一级配置
    {
      path: '/',
      component: Layout,
      //二级配置
      children: [
        {
          path: '',
          component: Home,
        },
        {
          path: 'category/:id',
          component: Category
        },

        {
          path: 'category/sub/:id',
          component: SubCategory
        },


        {
          path: 'detail/:id',
          component: GoodsDetails
        }
      ]
    },
    {
      path: '/login',
      component: Login
    }
  ],
//路由滚动行为定制
  scrollBehavior() {
    return { top: 0 }
  }
})

export default router

组件封装



<script setup>


defineProps({
title:{
  type:String

},
subtitle:{
  type:String
}

})
</script>


<template>
  <div class="home-panel">
    <div class="container">
      <div class="head">
         <!-- 主标题和副标题 -->
        <h3>
          {{title}}<small>{{subtitle}}</small>
        </h3>
      </div>
      <!-- 主体内容区域 -->
      <slot> </slot>
    </div>
  </div>
</template>

<style>
</style>

使用:

  <HomePanel title="人气推荐" subtitle="人气爆款 不容错过">
  <ul class="goods-list">
        <li v-for="item in hotList" :key="item.id">
          <RouterLink to="/">
            <img v-img-lazy="item.picture"  alt="">
            <p class="name">{{ item.title }}</p>
            <p class="desc">{{ item.alt }}</p>
          </RouterLink>
        </li>
      </ul>
  </HomePanel>

表单绑定

import { ref } from 'vue'
import { loginApi } from '@/apis/userApi'
import { ElMessage } from 'element-plus'
import 'element-plus/theme-chalk/el-message.css'
import { useRouter } from 'vue-router'
import router from '@/router'

//表单校验:账户名和密码
const form = ref({
  accounr: '',
  password: '',
  agree: true,

})

//准备规则对象
const rules = {
  account: [
    { required: true, message: '用户名不能为空', trigger: 'blur' }
  ],
  password: [
    { required: true, message: '密码不能为空', trigger: 'blur' },
    { min: 6, max: 14, message: '密码为6到14位', trigger: 'blur' }
  ],
  agree: [
    {
      validator: (rule, value, callback) => {
        console.log(value);
        //自定义校验逻辑
        if (value) {
          callback()
        }
        else {
          callback(new Error('请勾选协议'))
        }
      }
    }
  ]
}

//获取form实例
const formRef = ref(null)
const subform = () => {
  const Router = useRouter()
  formRef.value.validate(async (valid) => {
    //表单都通过校验 valid才true
    if (valid) {
      const { account, password } = form.value
      const res = await loginApi({ account, password })
      console.log(res);
      ElMessage({ type: 'success', message: '登录成功' })
      router.replace({ path: '/' })
    }

  })
}


</script>

<template>
 
    <section class="login-section">
      <div class="wrapper">
        <nav>
          <a href="javascript:;">账户登录</a>
        </nav>
        <div class="account-box">
          <div class="form">
            <el-form ref="formRef" :model="form" :rules="rules" label-position="right" label-width="60px" status-icon>
              <el-form-item prop="account" label="账户">
                <el-input v-model="form.account" />
              </el-form-item>
              <el-form-item prop="password" label="密码">
                <el-input v-model="form.password" />
              </el-form-item>
              <el-form-item label-width="22px" prop="agree">
                <el-checkbox size="large" v-model="form.agree">
                  我已同意隐私条款和服务条款
                </el-checkbox>
              </el-form-item>
              <el-button size="large" class="subBtn" @click="subform">点击登录</el-button>
            </el-form>
          </div>
        </div>
      </div>
    </section>
  1. 表单数据绑定 :model=“form”
  2. 准备规则对象 el-form上绑定:rules=“rules” item上绑定 prop=“account”
  3. 自定义校验逻辑 validator: (rule, value, callback) => {}
  4. 获取form实例 提交时进行全部规则检验 formRef.value.validate
  5. 获取当前路由 const Router = useRouter()
    useRouter是方法,useRoute是获取参数

直接跳转 @click=‘$router.push(‘./xxx’)’·

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值