首页 » 爱链网 » Vue3-mini 电商项目实战(实战项目组件数据导入),vue项目组件化。

Vue3-mini 电商项目实战(实战项目组件数据导入),vue项目组件化。

少女玫瑰心 2024-07-24 01:40:30 爱链网 0

扫一扫用手机浏览

文章目录 [+]

export default { //vue2

data(){ return {count:0} },

methods:{ addCount(){this.count++} }

Vue3-mini 电商项目实战(实战项目组件数据导入) Vue3-mini 电商项目实战(实战项目组件数据导入) 爱链网
(图片来自网络侵删)

}

<script setup>

Vue3-mini 电商项目实战(实战项目组件数据导入) Vue3-mini 电商项目实战(实战项目组件数据导入) 爱链网
(图片来自网络侵删)

import { ref } from 'vue'//vue3

const count = ref(0)

const addCount = ()=> count.value++

</script>

特点:

代码量变少分散式维护变成集中式维护

2. Vue3更多的优势

2. 使用create-vue创建项目

前置条件 - 已安装16.0或更高版本的Node.js

执行如下命令,这一指令将会安装并执行 create-vue

npm init vue@latest

组合式API - setup选项

1. setup选项的写法和执行时机

<script>

export default {

setup(){},

beforeCreate(){}

}

</script>

2. setup中写代码的特点

在setup函数中写的数据和方法需要在末尾以对象的方式return,才能给模版使用

<script>

export default {

setup(){

const message = 'this is message'

const logMessage = ()=>{console.log(message)}

// 必须return才可以

return { message,logMessage }

}

}

</script>

3. <script setup>语法糖

script标签添加 setup标记,不需要再写导出语句,默认会添加导出语句

<script setup>

const message = 'this is message'

const logMessage = ()=>{

console.log(message)

}

</script>

组合式API - reactive和ref函数

1. reactive

接受对象类型数据的参数传入并返回一个响应式的对象

<script setup>

import { reactive } from 'vue'// 导入

const state = reactive({msg:'this is msg'})// 执行函数 传入参数 变量接收

const setSate = ()=>{ // 修改数据更新视图

state.msg = 'this is new msg'

}

</script>

<template>

{{ state.msg }}

<button @click="setState">change msg</button>

</template>

2. ref

<script setup>

import { ref } from 'vue'// 导入

const count = ref(0)// 执行函数 传入参数 变量接收

const setCount = ()=>{// 修改数据更新视图必须加上.value

count.value++

}

</script>

<template>

<button @click="setCount">{{count}}</button>

</template>

3. reactive 对比 ref

都是用来生成响应式数据不同点reactive不能处理简单类型的数据ref参数类型支持更好,但是必须通过.value做访问修改ref函数内部的实现依赖于reactive函数

在实际工作中的推荐,推荐使用ref函数,减少记忆负担

组合式API - computed

计算属性基本思想和Vue2保持一致,组合式API下的计算属性只是修改了API写法

<script setup>

import {ref, computed } from 'vue'// 导入

const count = ref(0)// 原始数据

const doubleCount = computed(()=>count.value 2)// 计算属性

const list = ref([1,2,3,4,5,6,7,8])// 原始数据

const filterList = computed(item=>item > 2)// 计算属性list

</script>

组合式API - watch

侦听一个或者多个数据的变化,数据变化时执行回调函数,俩个额外参数 immediate控制立刻执行,deep开启深度侦听

1. 侦听单个数据

<script setup>

import { ref, watch } from 'vue'// 1. 导入watch

const count = ref(0)

watch(count, (newValue, oldValue)=>{// 2. 调用watch 侦听变化

console.log(`count发生了变化,老值为${oldValue},新值为${newValue}`)

})

</script>

2. 侦听多个数据

侦听多个数据,第一个参数可以改写成数组的写法

<script setup>

import { ref, watch } from 'vue'// 1. 导入watch

const count = ref(0)

const name = ref('cp')// 2. 调用watch 侦听变化

watch([count, name], ([newCount, newName],[oldCount,oldName])=>{

console.log(`count或者name变化了,[newCount, newName],[oldCount,oldName])

})

</script>

3. immediate

在侦听器创建时立即出发回调,响应式数据变化之后继续执行回调

<script setup>

import { ref, watch } from 'vue'// 1. 导入watch

const count = ref(0)// 2. 调用watch 侦听变化

watch(count, (newValue, oldValue)=>{

console.log(`count发生了变化,老值为${oldValue},新值为${newValue}`)

},{immediate: true})

</script>

4. deep

通过watch监听的ref对象默认是浅层侦听的,直接修改嵌套的对象属性不会触发回调执行,需要开启deep

<script setup>

import { ref, watch } from 'vue'// 1. 导入watch

const state = ref({ count: 0 })

watch(state, ()=>{// 2. 监听对象state

console.log('数据变化了')

})

const changeStateByCount = ()=>{// 直接修改不会引发回调执行

state.value.count++

}

</script>

<script setup>

import { ref, watch } from 'vue'// 1. 导入watch

const state = ref({ count: 0 })

watch(state, ()=>{// 2. 监听对象state 并开启deep

console.log('数据变化了')

},{deep:true})

const changeStateByCount = ()=>{// 此时修改可以触发回调

state.value.count++

}

</script>

声明周期

1. 选项式对比组合式

2. 生命周期函数基本使用

导入生命周期函数执行生命周期函数,传入回调

<scirpt setup>

import { onMounted } from 'vue'

onMounted(()=>{

// 自定义逻辑

})

</script>

3. 执行多次

生命周期函数执行多次的时候,会按照顺序依次执行

<scirpt setup>

import { onMounted } from 'vue'

onMounted(()=>{// 自定义逻辑})

onMounted(()=>{// 自定义逻辑})

</script>

组合式API - 父子通信

1. 父传子

基本思想

父组件中给子组件绑定属性子组件内部通过props选项接收数据

2. 子传父

基本思想

父组件中给子组件标签通过@绑定事件子组件内部通过 emit 方法触发事件

组合式API - 模版引用

概念:通过 ref标识 获取真实的 dom对象或者组件实例对象

1. 基本使用

实现步骤:

调用ref函数生成一个ref对象通过ref标识绑定ref对象到标签

defineExpose

默认情况下在 <script setup>语法糖下组件内部的属性和方法是不开放给父组件访问的,可以通过defineExpose编译宏指定哪些属性和方法容许访问

说明:指定testMessage属性可以被访问到

组合式API - provide和inject

1. 作用和场景

顶层组件向任意的底层组件传递数据和方法,实现跨层组件通信

2. 跨层传递普通数据

实现步骤

顶层组件通过 provide 函数提供数据底层组件通过 inject 函数提供数据

3. 跨层传递响应式数据

在调用provide函数时,第二个参数设置为ref对象

4. 跨层传递方法

顶层组件可以向底层组件传递方法,底层组件调用方法修改顶层组件的数据

什么是pinia

Pinia 是 Vue 的专属状态管理库,可以实现跨组件或页面共享状态,是 vuex 状态管理工具的替代品,和 Vuex相比,具备以下优势

提供更加简单的API (去掉了 mutation )提供符合组合式API风格的API (和 Vue3 新语法统一)去掉了modules的概念,每一个store都是一个独立的模块搭配 TypeScript 一起使用提供可靠的类型推断创建空Vue项目并安装Pinia

1. 创建空Vue项目

npm init vue@latest

2. 安装Pinia并注册

npm i pinia

import { createPinia } from 'pinia'

const app = createApp(App)

// 以插件的形式注册

app.use(createPinia())

app.use(router)

app.mount('#app')

3.实现counter

核心步骤:

定义store组件使用store

1- 定义store

import { defineStore } from 'pinia'

import { ref } from 'vue'

export const useCounterStore = defineStore('counter', ()=>{

const count = ref(0)// 数据 (state)

const increment = ()=>{ count.value++ }// 修改数据的方法 (action)

return { count,increment }// 以对象形式返回

})

2- 组件使用store

<script setup>

import { useCounterStore } from '@/stores/counter'// 1. 导入use方法

const counterStore = useCounterStore()// 2. 执行方法得到store store里有数据和方法

</script>

<template>

<button @click="counterStore.increment">{{ counterStore.count }}</button>

</template>

3-实现getters

const count = ref(0)// 数据(state)

const doubleCount = computed(() => count.value 2)// getter (computed)

4-异步action

思想:action函数既支持同步也支持异步,和在组件中发送网络请求写法保持一致

步骤:

store中定义action组件中触发action

store中定义action

const API_URL = ''

export const useCounterStore = defineStore('counter', ()=>{

const list = ref([])// 数据

const loadList = async ()=>{// 异步action

const res = await axios.get(API_URL)

list.value = res.data.data.channels

}

return {list,loadList}

})

组件中调用action

<script setup>

import { useCounterStore } from '@/stores/counter'

const counterStore = useCounterStore()

counterStore.loadList()// 调用异步action

</script>

<template>

<ul>

<li v-for="item in counterStore.list" :key="item.id">{{ item.name }}</li>

</ul>

</template>

storeToRefs保持响应式解构

直接基于store进行解构赋值,响应式数据(state和getter)会丢失响应式特性,使用storeToRefs辅助保持响应式

<script setup>

import { storeToRefs } from 'pinia'

import { useCounterStore } from '@/stores/counter'

const counterStore = useCounterStore()

// 使用它storeToRefs包裹之后解构保持响应式

const { count } = storeToRefs(counterStore)

const { increment } = counterStore

</script>

<template>

<button @click="increment">{{ count }}</button>

</template>

------------------------------------------------------------------------------------------------------------------------

创建项目并整理目录

npm init vue@latest

jsconfig.json配置别名路径

配置别名路径可以在写代码时联想提示路径

{

"compilerOptions" : {

"baseUrl" : "./",

"paths" : {

"@/":["src/"]

}

}

}

elementPlus引入

1. 安装elementPlus和自动导入插件

npm i elementPlus

npm install -D unplugin-vue-components unplugin-auto-import

2. 配置 vite.config.js 自动按需导入

import AutoImport from 'unplugin-auto-import/vite'

import Components from 'unplugin-vue-components/vite'

import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'

export default defineConfig({

plugins: [// 配置插件

AutoImport({

resolvers: [ElementPlusResolver()],

}),

Components({

resolvers: [ElementPlusResolver()],

}),

]

})

3. 测试组件

<template>

<el-button type="primary">i am button</el-button>

</template>

定制elementPlus主题

1. 安装sass

基于vite的项目默认不支持css预处理器,需要开发者单独安装

npm i sass -D

2. 准备定制化的样式文件 styles/element/index.scss

/ 只需要重写你需要的即可 /

@forward 'element-plus/theme-chalk/src/common/var.scss' with (

$colors: (

'primary': (

// 主色

'base': #27ba9b,

),

'success': (

// 成功色

'base': #1dc779,

),

'warning': (

// 警告色

'base': #ffb302,

),

'danger': (

// 危险色

'base': #e26237,

),

'error': (

// 错误色

'base': #cf4444,

),

)

)

3. 自动导入配置

这里自动导入需要深入到elementPlus的组件中,按照官方的配置文档来

自动导入定制化样式文件进行样式覆盖按需定制主题配置 (需要安装 unplugin-element-plus)

vite.config.js

import { fileURLToPath, URL } from 'node:url'

import { defineConfig } from 'vite'

import vue from '@vitejs/plugin-vue'

import AutoImport from 'unplugin-auto-import/vite'

import Components from 'unplugin-vue-components/vite'

import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'

// 导入对应包

import ElementPlus from 'unplugin-element-plus/vite'

export default defineConfig({

plugins: [

vue(),

AutoImport({

resolvers: [ElementPlusResolver()],

}),

Components({

resolvers: [ElementPlusResolver()],

}),

// 按需定制主题配置

ElementPlus({

useSource: true,

}),

],

resolve: {

alias: {

'@': fileURLToPath(new URL('./src', import.meta.url))

}

},

css: {

preprocessorOptions: {

scss: {

// 自动导入定制化样式文件进行样式覆盖

additionalData: `

@use "@/styles/element/index.scss" as ;

`,

}

}

}

})

axios安装并简单封装

1. 安装axios

npm i axios

2. 基础配置

官方文档地址:https://axios-http.com/zh/docs/intro

基础配置通常包括:

实例化 - baseURL + timeout拦截器 - 携带token 401拦截等

utils/http.js

import axios from 'axios'

// 创建axios实例

const httpinstance = axios.create({

baseURL: 'http://pcapi-xiaotuxian-front-devtest.itheima.net',

timeout: 5000

})

// axios请求拦截器

httpinstance.interceptors.request.use(config => {

return config

}, e => Promise.reject(e))

// axios响应式拦截器

httpinstance.interceptors.response.use(res => res.data, e => {

return Promise.reject(e)

})

export default http

3. 封装请求函数并测试 apis/TestApi.js

import http from '@/utils/http'

export function getCategoryAPI () {

return http({

url: 'home/category/head'

})

}

路由整体设计

路由设计原则:找页面的切换方式,如果是整体切换,则为一级路由,如果是在一级路由的内部进行的内容切换,则为二级路由

views/Login/index.vue

<template>我是登录页</template>

views/Layout/index.vue

<template>我是首页</template>

views/Home/index.vue

<template>我是home</template>

views/Category/index.vue

<template>我是分类</template>

router/index.js

// createRouter:创建router实例对象

// createWebHistory:创建history模式的路由

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'

const router = createRouter({

history: createWebHistory(import.meta.env.BASE_URL),

// path和component对应关系的位置

routes: [

{

path: '/',

component: Layout,

children: [

{

path: '',

component: Home

},

{

path: 'category',

component: Category

}

]

},

{

path: '/login',

component: Login

}

]

})

export default router

静态资源引入和Error Lens安装

1. 静态资源引入

图片资源 - 把 images 文件夹放到 assets 目录下样式资源 - 把 common.scss 文件放到 styles 目录下

2. Error Lens插件安装

scss变量自动导入

var.scss

$xtxColor: #27ba9b;

$helpColor: #e26237;

$sucColor: #1dc779;

$warnColor: #ffb302;

$priceColor: #cf4444;

css: {

preprocessorOptions: {

scss: {

// 自动导入scss文件

additionalData: `

@use "@/styles/element/index.scss" as ;

@use "@/styles/var.scss" as ;

`,

}

}

}

补充eslint配置

/ eslint-env node /

require('@rushstack/eslint-patch/modern-module-resolution')

module.exports = {

root: true,

'extends': [

'plugin:vue/vue3-essential',

'eslint:recommended',

'@vue/eslint-config-typescript'

],

parserOptions: {

ecmaVersion: 'latest'

},

rules: {

'vue/multi-word-component-names': 0, // 不再强制要求组件命名

},

}

-------------------------------------------------------------------------------------------------------------------------

标签:

相关文章