軟體工程實踐專案學習與執行日誌
Vue3專案實踐
https://pan.baidu.com/s/1ZqjMxwZklZVYpB1ZbzEKKA&pwd=9987
首先我一直不明白別人老說要學會git倉庫,這個是幹嘛的怎麼用有何益處?github我知道你可以儲存自己的專案與他人共享,其中含有許多雙贏的道理。
06.git reset回退版本_嗶哩嗶哩_bilibili(這個up的專題講得特別好)
對於這個只是簡單瞭解一下如果要深入的掌握還是需要不斷的實踐操作才可以的。
專案宣告:本專案是在瞭解一定的vue3知識進行的新手入門專案
1.1第一步:建立專案框架+git倉庫儲存
1.2實戰學習
- 學習了利用pinia進行資料與方法的管理,使得傳送請求的時候只進行一次減少了資源的浪費。但是在我第一次嘗試中我並沒有成功。我發現沒有成功的原因就是沒有下載pinia這個包而且這個也是要在main.js中去註冊一下才能夠展示出來。
在這個裡我就有一個疑惑了,什麼樣的需要在main.js中註冊才能使用其功能?
答:好吧內容挺多的我感覺我記下來也沒有什麼比較明確的好處。總結來說,任何需要在整個 Vue 應用中全域性可用的外掛、庫或元件,都需要在 main.js 中進行註冊。這樣做可以確保這些功能在應用啟動時就被初始化,並在各個元件中都能使用。
我還有一個疑惑就是store這個資料夾是作什麼的?
答:(好吧其實我是很懂)
定義 Store 的檔案: 每個 store 檔案定義了一個獨立的狀態模組,包括狀態(state)、動作(actions)、getters(計算屬性)等。這些檔案通常命名為與它們管理的狀態相關的名稱,例如 counter.js 或 user.js。
分模組管理: 對於大型應用,將狀態管理分為多個模組有助於更好地組織程式碼。例如,可以有一個 auth.js 檔案管理使用者認證相關的狀態,一個 products.js 檔案管理產品相關的狀態等。
(Home-整體結構拆分和分類)
- 看我做成了這樣的頁面佈局其實我頁不知道這些是怎麼做出來的?
答:請看程式碼註釋
- 其實我一直很疑惑就是前端開發師怎麼記住哪些顏色數值的,還有那些頁面的大小怎麼就直接寫出來了。而且我就想不能夠有這樣的軟體設計師直接在相關的畫板中設計相關的UI介面,設計後軟體直接給出相關的設計的佈局程式碼。
答:
大多數前端開發專案都會有設計稿,通常由設計師使用設計工具(如 Adobe XD、Sketch、Figma 等)製作。
設計稿上會明確標註各個元素的尺寸、間距和位置,前端開發人員可以根據這些標註來設定相應的 CSS 屬性。
設計師通常會使用設計工具(如 Adobe XD、Sketch、Figma 等)建立設計稿。
這些工具中,設計師會使用特定的顏色並標註顏色值。
前端開發人員可以直接從設計工具中獲取顏色的十六進位制值(如 #333)。
Figma
- 功能:實時協作設計工具,支援團隊成員同時線上編輯。提供豐富的 UI 元素和設計元件。
- 程式碼生成:Figma 可以生成 CSS、iOS 和 Android 的程式碼片段。右鍵點選元素選擇“Inspect”即可檢視和複製相應的程式碼。
- 外掛:Figma 有許多外掛可以生成程式碼或匯出設計,如 Figma to HTML、Figma to React 等。
總結:現在有這樣的UI設計工具並且能夠直接給出程式碼的,我相信不久的將來這些類似的軟體更夠越來越完善完全體態員工,所以我打算的就是你就瞭解知道就好不必深究。
- 今日遇到一個問題就是有些資料怎麼顯示都顯示不來
答:後端的API介面不怎麼穩定!
- 其實我有一個疑惑就是:這些佈局到底是怎麼進行管理起來的
答:這些佈局頁面我學習的是透過路由進行管理的
首先在router/index.js下構建路由結構:設定好一級路由、二級路由
在APP.vue中書寫一級路由的出口,在一級路由的分類夾中的index.js中書寫二級路由的出口
由此所有的佈局頁面就有條有理地展現出來了。
- (Home-banner輪番圖功能實現)
<template>
<div class="home-banner">
<el-carousel height="500px" >
<el-carousel-item v-for="item in bannerList" :key="item.id">
<img :src="item.imgUrl" alt="">
</el-carousel-item>
</el-carousel>
</div>
</template>
這個挺有趣的但是那個佈局我還是不是很懂,可是我覺得它完全可以被替代呀
<el-carousel>:這是輪播圖的容器元件。height="500px" 設定了輪播圖的高度為 500 畫素。
<el-carousel-item>:這是輪播圖中的每一個專案。使用 v-for 指令來遍歷 bannerList 陣列,為每個元素建立一個輪播圖項。每個輪播圖項的 key 屬性使用元素的 id 進行標識,這是 Vue 在列表渲染中推薦的做法,以便在更新列表時能夠高效地進行 DOM 操作。
<img>:在每個輪播圖項中顯示一張圖片。src 屬性繫結到 item.imgUrl,顯示來自 bannerList 陣列中的圖片。
Element Plus:Element Plus 是一個為 Vue 3 設計的基於 Element UI 的元件庫,它提供了豐富的 UI 元件,幫助開發者快速構建美觀的介面。你需要安裝和引入 Element Plus 元件庫。
- Home-皮膚件封裝
這裡主要涉及到的知識就是prop和插槽感覺好方面啊,但是我對這些知識還不是很會捏
- Giao git學得不精啊這個寫錯了不知道怎麼退回我的專案
Git是什麼:
日常生活中我們都會經歷多個人修改某檔案的情況,以修改競賽文字為例,第一種當多人同時修改競賽文字時之後還需要手工合成多人修改的部分。如果修改的版本過多可能會出現合成的版本不一致的問題,其他版本丟失等情況。第二種方式就是為了避免合成就一個個接替修改就會導致浪費時間等情況,那麼我們急需版本控制系統對檔案版本進行有效地管理。這裡將要介紹的就是git。
Git採用的是分散式管理,每個人都有版本庫,可在本地進行修改。修改後只需將倉庫同步一下就好。使用它時可以知道誰在什麼時間做了什麼修改,也可以將檔案恢復到某一版本,可為非常好用!(其實我覺得我講得還不到位,我覺得我自己都沒有理解透)
- 同時我還遇到了個問題就是git當中的分支到底是什麼呀?
分支非常適合團隊合作,每位成員都能夠在自己相關的分支完成一定的開發測試任務,之後再彙總到主分支上。
- 還有一個我提交到倉庫的提交資訊搞錯了,我該如何修改
修改最近一次提交的資訊
- 執行 git commit --amend 命令:
bash
複製程式碼
git commit --amend
- 這將開啟你預設的文字編輯器,顯示最近一次提交的資訊。在這裡,你可以編輯提交資訊。
- 編輯提交資訊後,儲存並關閉編輯器。
- Home-新鮮好物和人氣推薦實現
如果多個模組使用的模板相同,那我們就應該提取出需要修改的部分並進行封裝。如果是類似於修改字串這些簡單的修改就可以使用props,如下所示:
<script setup>
defineProps({
title:{
type:String
},
subTitle:{
type:String
}
})
</script>
實際用法如下:
<div class="head">
<!-- 主標題和副標題 -->
<h3>
{{ title }}<small>{{ subTitle }}</small><!--這裡用prop-->
</h3>
此外為複雜的修改可以使用插槽。具體使用情況如下:
div class="home-panel">
<div class="container">
<div class="head">
<!-- 主標題和副標題 -->
<h3>
{{ title }}<small>{{ subTitle }}</small><!--這裡用prop-->
</h3>
</div>
<!-- 主體內容區域 --><!--這裡用插槽-->
<div>
<slot></slot>
</div>
</div>
</div>
詳細說明:
<div> 元素內有一個 <slot> 元素。這個 <slot> 元素表示一個預設插槽,當你在父元件中使用這個元件時,可以將一些內容傳遞給這個插槽。
<slot> 元素用於在元件中定義插槽(slot)。插槽是佔位符,可以在使用元件時向元件內部傳遞內容。換句話說,插槽允許你在父元件中指定一部分內容,然後將其傳遞到子元件的特定位置。
Vue.js 插槽有幾種型別:
- 預設插槽:如上例所示的基本插槽。
- 具名插槽:可以為插槽指定一個名稱,在父元件中按名稱傳遞內容。
- 作用域插槽:允許子元件向父元件傳遞資料,以便父元件能夠自定義渲染內容。
具名插槽示例
定義具名插槽:
<template>
<div>
<slot name="header"></slot>
<slot></slot> <!-- 預設插槽 -->
</div>
</template>
在父元件中使用具名插槽:
<template>
<div>
<MyComponent>
<template v-slot:header>
<h1>This is the header content</h1>
</template>
<p>This is the default slot content</p>
</MyComponent>
</div>
</template>
具名插槽的渲染結果:
<div>
<div>
<h1>This is the header content</h1>
<p>This is the default slot content</p>
</div>
</div>
- Hom-圖片懶載入指令實現
為什麼要進行懶載入:
可能會遇到這種情況—網站資源過多,使用者就不會瀏覽到下面,那麼下面的資源資料就不必展現出來了。我覺得這個是減少浪費吧,具體是減少什麼我就不知道了(減少請求),我只知道這是一個最佳化操作。其作用就是:圖片透過懶載入最佳化手段可以做到只有進入視口區域才傳送圖片請求。
懶載入的基本想法:
使用vueUse判斷圖片是否進入視口——>如果圖片進入視口,傳送圖片資源(img.src=url)請求。
- 空指令實現:
app.directive('img-lazy', {
mounted(el, binding) {
定義一個指令,其中傳入的有指令名還有物件即該指令的具體操作
- 在原始碼中將src=“”改寫成自己定義的指令
<img v-img-lazy="item.picture" alt="" />
- 指令的邏輯實現
app.directive('img-lazy', {
mounted(el, binding) {
// el: 指令所繫結的元素 img,DOM操作
// binding:binding.value 指令等於括號後面繫結的表示式的值,圖片地址url
console.log(el,binding.value);
useIntersectionObserver(
el,//你要監聽誰是否進入視口區域就把誰傳過來
([{ isIntersecting }]) => {//isIntersecting 判斷是否進入視口區域是一個布林值
console.log(isIntersecting);
if (isIntersecting) {
// 進入視口區域,把圖片地址賦值給img的src屬性
el.src = binding.value; // 進入視口區域,把圖片地址賦值給img的src屬性
}
},
)
}
})
- (透過外掛的方法把懶載入指令封裝為外掛,main.js入口檔案只需負責註冊外掛即可) 最佳化
main.js檔案本來主要是進行初始化的工作的,我們可在
src\directives定義全域性指令將方法封裝為外掛:
export const lazyPlugin={
install(app){//接下來是寫該外掛的邏輯
之後寫好外掛邏輯:
export const lazyPlugin={
install(app){
//懶載入指令邏輯
//定義全域性指令
// 使 v-focus 在所有元件中都可用
app.directive('img-lazy', {
mounted(el, binding) {
// el: 指令所繫結的元素 img,DOM操作
// binding:binding.value 指令等於括號後面繫結的表示式的值,圖片地址url
console.log(el,binding.value);
useIntersectionObserver(
el,//你要監聽誰是否進入視口區域就把誰傳過來
([{ isIntersecting }]) => {//isIntersecting 判斷是否進入視口區域是一個布林值
console.log(isIntersecting);
if (isIntersecting) {
// 進入視口區域,把圖片地址賦值給img的src屬性
el.src = binding.value; // 進入視口區域,把圖片地址賦值給img的src屬性
}
},
)
}
})
之後在mian.js註冊+使用就好
//引入懶載入指令外掛並註冊
import { lazyPlugin } from './directives'
app.use(lazyPlugin)
- useIntersectionObserver對於元素的監聽是一直存在的,除非手動停止監聽,存在記憶體浪費。最佳化
解決:在監聽的圖片第一次完成載入之後就停止監聽(可使用如下程式碼)
const { stop } = useIntersectionObserver(
target,
([{ isIntersecting }], observerElement) => {
targetIsVisible.value = isIntersecting
},
)
整體改為:
export const lazyPlugin={
install(app){
//懶載入指令邏輯
//定義全域性指令
// 使 v-focus 在所有元件中都可用
app.directive('img-lazy', {
mounted(el, binding) {
// el: 指令所繫結的元素 img,DOM操作
// binding:binding.value 指令等於括號後面繫結的表示式的值,圖片地址url
console.log(el,binding.value);
const { stop } = useIntersectionObserver(
el,//你要監聽誰是否進入視口區域就把誰傳過來
([{ isIntersecting }]) => {//isIntersecting 判斷是否進入視口區域是一個布林值
console.log(isIntersecting);
if (isIntersecting) {
// 進入視口區域,把圖片地址賦值給img的src屬性
el.src = binding.value; // 進入視口區域,把圖片地址賦值給img的src屬性
stop(); // 停止監聽
}
},
)
}
})
}
}
- Home-Product產品列表實現
方法:
產品列表展示即每個模組的產品展示一部分,這樣的話那靜態模板是一樣的呀(之前學習過了)——>封裝介面——>獲取資料渲染模板——>圖片懶載入
- Home-Goodsltem元件封裝
在這裡的核心思想是把要顯示的資料物件設計為props引數,傳入什麼資料物件就顯示什麼資料物件。
我們今天主要學會的就是:抽象props引數,傳入什麼就顯示什麼
- 一級分類-整體認識和路由配置
<RouterLink :to="`/category/${item.id}`">{{ item.name }}</RouterLink> <!--導航目錄-->
在這條語句中是設定跳轉路由的語句,to則是跳轉到的路徑,在這裡用單號符一直不可以 只有在英文輸入法下用這個符號才可以:`。
- 一級分類-麵包屑導航渲染
基本思想:
準備元件模版 封裝介面函式 呼叫介面獲取資料 渲染模板
(使用路由引數)
不得不說vue真方便!麵包屑導航都是自己幫寫好的!
<div class="bread-container">
<el-breadcrumb separato=">">
<el-breadcrumb-item :to="{path:'/'}">首頁</el-breadcrumb-item>
<el-breadcrumb-item>居家</el-breadcrumb-item>
</el-breadcrumb>
</div>
- 不知道弄了什麼狗逼東西導致執行錯誤想著我使用git,那應該是可以回退到某一個版本的呀
a.git log檢視所有的提交資訊
b. git checkout <commit-id>回退到某一個版本
可惡呀到這裡再執行是發生錯誤的,問chat說是我的
- 今天再試了回退到某個版本居然成功了,果然git好好用。我上次沒成功不知道是什麼原因,但是我都應該驗證一下回退是否成功!
M 和 A 表示以下含義:
- M (Modified): 這些檔案相對於你當前檢視的提交來說已經被修改了,但修改內容還沒有提交。
- A (Added): 這些檔案已經被新增到暫存區(staging area),但還沒有被提交。
如果你想永久回退到這個版本,可以使用 git reset --hard 命令
git reset --hard 385fadc0f846b2208d07ec0970af58636fc3ff5c
- 現在又來完成麵包屑導航啦(由於8月2日的沒完成,請往上看8月2日的相關內容)
- 獲取id那個可惡啊!怎麼就成功了呢,和之前寫的是一樣的呀
來感受一下帶參的介面函式吧
export function getCategoryId (id) {
return request({
url:'/category' , //介面發起 這個介面怎麼就設定成這樣了?md在那個麵包屑導航直接用這個介面就好
params: {
id // 透過 params 傳遞查詢引數 id
}
})
}
獲取資料情況
//獲取資料
const categoryData = ref({})
const route = useRoute()
const categoryId = async () =>{
const res =await getCategoryId(route.params.id)
categoryData.value = res.result
}
onMounted(()=>categoryId())
以下例項物件專門來獲取id引數
const route = useRoute()
- 一級分類-輪播圖功能實現
思想:
改造先前的介面 遷移首頁輪播圖邏輯
(適配引數)
①改造為傳參介面
export function getBannerAPI(params={}){
const {distributionSite='1'} = params;
return httpInstance({
url:'/home/banner',
params:{
distributionSite
}
})
}
②將改造的介面在分類中進行應用
const bannerList = ref([])
const getBanner = async () => {
const res = await getBannerAPI({
distributionSite:'2'
})
console.log(res)
bannerList.value = res.result
}
onMounted(() => getBanner())
說實話我是有點不理解為啥獲取的資料都一樣還要為介面設定不同的引數呀:
理解 distributionSite 引數的作用
- 相同介面,不同資料:在很多 API 設計中,一個介面可以根據傳遞的不同引數返回不同的資料。distributionSite 引數可能被用於在伺服器端區分不同頁面所需的內容。例如,distributionSite='1' 可能返回首頁的輪播圖,而 distributionSite='2' 可能返回“居家”頁面的輪播圖。
- 靈活性:這種設計方式的好處是,前端開發者只需要記住一個介面,而不是多個介面,引數的不同會自動決定返回的資料內容。這種方法也使得 API 設計更具擴充套件性,可以透過增加引數值來支援更多頁面或場景。
舉個例子
假設伺服器端根據 distributionSite 的值返回不同的輪播圖資料:
- 當 distributionSite='1' 時,返回首頁的輪播圖資料,例如廣告、促銷資訊等。
- 當 distributionSite='2' 時,返回居家頁面的輪播圖資料,可能是家居用品的推薦。
為什麼設定不同引數
透過設定不同的 distributionSite 引數,你能夠複用同一個介面獲取不同頁面的定製化資料,而不是硬編碼或為每個頁面設計不同的介面。這種方式不僅提高了程式碼的可複用性,還保持了 API 的一致性。
- 那個一級分類列表有點垃圾那每次點選要重新整理一下才可以
原因:
可能是因為資料獲取和渲染的時間不同步,導致 UI 沒有及時更新
//獲取資料
const categoryData = ref({})
const route = useRoute()
const categoryId = async () =>{
const res =await getCategoryId(route.params.id)
categoryData.value = res.result
}
onMounted(()=>categoryId())
// 監聽路由引數 id 的變化
watch(() => route.params.id, (newId) => {
if (newId) {
categoryId() // 直接呼叫獲取資料的函式
}
})
watch 函式:監聽 route.params.id 的變化,當分類 ID 變化時,重新呼叫 categoryId 函式,以獲取新的分類資料並更新 categoryData。
- 正式開始一級分類-啟用狀態顯示
在點選的部分能顯示啟用
以便使用者知道前所處位置
方法:
原本 <RouterLink自帶啟用功能
但是不夠長久,乾脆寫個屬性在樣式中定義
- 一級分類-分類列表的渲染
其實在這一部分就沒有什麼困難的,在這裡我覺得最重要的就是重用之前封裝的元件
之前封裝的元件:
在 '@/views/Home/components/Goodsitem.vue'中Goodsitem檔案有這樣的元件:
<template>
<RouterLink to="/" class="goods-item">
<img v-img-lazy="good.picture" alt="" />
<p class="name ellipsis">{{ good.name }}</p>
<p class="desc ellipsis">{{ good.desc }}</p>
<p class="price">¥{{ good.price }}</p>
</RouterLink>
</template>
我們在別的頁面也想要這個元件直接引用就好
import Goodsitem from '@/views/Home/components/Goodsitem.vue'
<div class="sub-list">
<h3>全部分類</h3>
<ul>
<li v-for="i in categoryData.children" :key="i.id">
<RouterLink to="/">
<img :src="i.picture"/>
<p>{{ i.name }}</p>
</RouterLink>
</li>
</ul>
</div>
<div class="ref-goods" v-for="item in categoryData.children" :key="item.id">
<div class="head">
<h3>-{{ item.name}}-</h3>
</div>
<div class="body">
<Goodsitem v-for="good in
item.goods" :good="good" :key="good.id"/><!--之前封裝的主鍵-->
</div>
</div>
- 我又產生了這樣一個迷惑就是這些頁面怎麼不像jsp學習的那樣如果是頁面展示都要自己建立一個網頁來,但這個vue好神奇它怎麼頁面銜接展示的
首先咱先看看路由
import { createRouter, createWebHistory } from 'vue-router'
import Login from '@/views/Login/index.vue'
import Layout from '@/views/Layout/index.vue'
import Category from '@/views/Category/index.vue'
import Home from '@/views/Home/index.vue'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
//path和componet對應關係的位置
routes: [
{
path: '/',
name: 'Layout',
component: Layout,
children:[
{
path: '', //預設二級路由為空?
name:'Home',
component: Home
},
{
path:'Category/:id',
name:'Category',
component: Category
}
]
},
{
path: '/login',
name: 'Login',
component: Login
}
]
})
export default router
Layout是一級路由然後Home和Category(你看那個Category後有個動態id它有許多個路由)是二級路由
這個是Layout的佈局,其中index.vue這個引索是決定誰可以展現在頁面中的:
<template>
<LayoutFixe />
<LayoutNav />
<LayoutHeader />
<RouterView /><!--以及路由入口吧-->
<LayoutFooter />
</template>
你在一級路由中點選並且可以跳轉的到其他頁面的“點選”這個就是二級路由
這裡的APP.vue是掌管了總頁面誰可以展示
<template>
<!--一級路由出口-->
<RouterView />
</template>
直接這樣簡單明瞭
這個是Layout的佈局,其中index.vue這個引索是決定誰可以展現在Layout頁面中的:
<template>
<LayoutFixe />
<LayoutNav />
<LayoutHeader />
<RouterView /><!—二及路由出口吧-->
<LayoutFooter />
</template>
- 一級分類-路由快取問題
瞭解一些小知識:
- 生命週期鉤子:
在 Vue.js 中,生命週期鉤子是指在元件的不同階段自動呼叫的一組函式。這些鉤子允許你在元件的建立、更新和銷燬過程的特定時刻執行程式碼。透過這些鉤子,你可以更好地控制元件的行為。
以下是 Vue.js 中常用的生命週期鉤子及其觸發時機:
- beforeCreate:
- 在例項初始化之後,資料觀測 (data observer) 和事件配置 (event/watcher) 之前被呼叫。
- 此時,元件例項還沒有被完全初始化,資料、計算屬性、方法都還不可用。
- created:
- 在例項建立完成後被呼叫。
- 此時,例項已經完成了資料觀測、屬性和方法的初始化,但還未開始編譯模板。
- 如果需要在元件例項被完全初始化後立即執行一些邏輯,可以在這個鉤子中處理。
- beforeMount:
- 在掛載開始之前被呼叫。
- 此時模板已經編譯好了,但還沒有掛載到 DOM 上。
- 你可以在這裡做一些在 DOM 掛載前的最後準備工作。
- mounted:
- 在掛載完成後呼叫。
- 此時元件的 DOM 元素已經被插入文件中,可以在這裡進行依賴 DOM 操作的邏輯。
- beforeUpdate:
- 當響應式資料更新,且在虛擬 DOM 重新渲染和打補丁之前被呼叫。
- 你可以在這個鉤子中讀取舊的狀態和即將更新的狀態。
- updated:
- 在由於資料變化導致的虛擬 DOM 重新渲染和打補丁之後呼叫。
- 此時元件的 DOM 已經更新,你可以在這裡進行依賴更新後 DOM 狀態的操作。
- beforeDestroy:
- 在例項銷燬之前呼叫。
- 此時例項仍然完全可用,你可以在這裡進行清理工作,例如移除事件監聽器或清除計時器。
什麼是路由快取問題:
使用帶引數的路由時需要注意的是,當使用者從/use/category?id=01導航到
destroyed:
- 在例項銷燬後呼叫。
- 呼叫後,所有的事件監聽器會被移除,子例項也會被銷燬,元件從 DOM 中移除
(感覺上面的看一眼瞭解一個大概就可以了)
onMounted(() => getBanner())
在 Vue 3 中,onMounted 是一種組合式 API(Composition API)中的生命週期鉤子,它的功能與 Vue 2 中的 mounted 鉤子相同。onMounted 用於在元件掛載到 DOM 之後執行某些操作。具體來說,當元件的 DOM 元素已經被插入文件後,onMounted 鉤子會被呼叫。
/use/category?id=02時,相同的元件例項將被重複使用。因為兩個路由都渲染同個元件,比起銷燬再建立,複用則顯得更加高效。不過,這也意味著元件的生命週期鉤子不會被呼叫。簡單來說就是一級分類的切換正好滿足上面的條件,元件例項複用,導致分類資料無法更新。
解決問題:
解決這個問題有兩種方法,1.讓元件例項不復用,強制銷燬重建2.、
2.監聽路由變化,變化之後執行資料更新操作(這個我們做過了就是用
Watch進行監聽)
使用方法一:
給<Router-view新增key
<!--新增key 破壞複用機制 強制銷燬重建-->
<RouterView :key="$route.fullPath" />
在Layout中的index.vue新增,但是這個方法回導致同樣的資源重複申請(它的申請是整個頁面的申請)
- 一級分類-使用邏輯函式拆分業務
小理解:
基於邏輯函式拆分業務是指把同一個元件中獨立的業務程式碼透過函式做封裝處理,提升程式碼的可維護性
實施步驟:
- 按照業務宣告以`use`打頭的邏輯函式
- 把獨立的業務邏輯封裝到各個函式內部
- 函式內部把元件中需要用到的資料或方法return出去
- 在元件中呼叫函式把資料或者方法組合回來使用
- 二級分類-整體認識和路由配置
思路:
建立路由元件 配置路由關係 修改模板實現跳轉
有一個需要注意的點就是在配置路由結束後需要重啟專案才能達到想要的效果。
- 二級分類-麵包屑導航實現(感覺蠻簡單的照之前做的就好了)
思想:
(很easy自己操作一下就可以!可惜今天沒做完,明天一定做完)
封裝介面呼叫介面渲染 測試跳轉
- 二級分類基礎商品列表展示
- 基礎列表渲染
- 實現篩選功能
- 實現無線載入功能
思路: 使用elementPlus提供的 v-infinite-scroll指令監聽是否滿足觸底條件,滿足載入條件時讓頁面引數加一獲取下一頁資料,做新老資料拼接渲染。
配置指令(v-infinite-scroll)——>頁數加-獲取下一頁資料
——>老資料和新資料並接——>載入資料完畢
發現個問題這個後端有問題在實現這個功能的時候是展示出了所有的商品並不按分類來(我覺得是介面有問題你看那個介面哪裡有分類資料的id啊)
- 二級分類-定製路由scrollBehavior
直接使用這個:scrollBehavior
當跳級到上一級路由頁面會回到頂部
- 詳情頁-整體認識和路由配置
建立詳情元件——>繫結路由關係——>繫結模板測試跳轉
- 詳情頁-基礎資料渲染
封裝介面——>呼叫獲取資料——>渲染模板
主要需要注意的就是
渲染模板時遇到物件的多層屬性訪問可能出現什麼問題?
訪問的屬性為空!
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'name')
解決方法:1.可選鏈 2.v-if 控制渲染
- 詳情頁-熱榜區域的實現
封裝Hot熱榜元件 ——> 獲取渲染基礎資料 ——> 適配不同標題Title
——>適配不同列表內容
- 適配不同的標題
- 設計props引數 適配不同的title和資料
const props=defineProps({
hotType:{
type:Number
}
})
- 編寫標題物件
const Typemap={
1:'24小時熱榜',
2:'周榜熱榜',
}
- 編寫可進行判斷的標題物件
const title = computed(()=>Typemap[props.hotType])
- 詳情頁-圖片預覽元件封裝
- 透過小圖切換大圖實現
思路:維護一個陣列圖片列表,滑鼠劃入小圖記錄當前小圖示下值,透過下標在陣列中取對應圖片,顯示到大圖位置
準備元件靜態模版——>為小圖繫結事件——>透過下標切換到大圖顯示
記錄當前啟用下標值
——>透過下標實現啟用狀態顯示
- 為小圖繫結事件記錄當前啟用下標值:
<!-- 小圖列表 -->
<ul class="small">
<li v-for="(img, i) in imageList" :key="i" @mouseenter="enterhandler(i)"> <!--給小圖繫結滑鼠事件-->
<img :src="img" alt="" />
</li>
</ul>
- 對啟用事件進行編寫
//小圖切換大圖顯示
const activeIndex=ref(0)
const enterhandler =(i) =>{
activeIndex.value = i
}
- 透過小圖下標顯示大圖
<!-- 左側大圖-->
<div class="middle" ref="target">
<img :src="imageList[activeIndex]" alt="" />
- 啟用狀態一直顯示
.small {
width: 80px;
li {
width: 68px;
height: 68px;
margin-left: 12px;
margin-bottom: 15px;
cursor: pointer;
&:hover,
&.active {
border: 2px solid $xtxColor;
}
}
}
主要是滑鼠點選哪個小圖就顯示哪個小圖為啟用狀態,這時候需要動態類名:
<li v-for="(img, i) in imageList" :key="i" @mouseenter="enterhandler(i)" :class="{active: i===activeIndex}">
- 圖片放大功能
- 左側滑塊跟隨滑鼠移動
思路:
獲取到當前的滑鼠在盒子內的相對位置(useMouselnElement),控制滑塊跟隨滑鼠移動(left/top)
- 滑鼠的距離盒子相對位置
useMouseInElement | VueUse 中文網 (nodejs.cn)
- 控制滑塊的跟隨移動
- 有效移動範圍內的計算邏輯
橫向:
100<elementX<300,left=elementX-小滑塊寬度的一半
縱向:
100<elementY<300,top=elementY-小滑塊高度的一半
- 邊界值控制距離(這些資訊都是教程裡面根據自己盒子來進行計算的)
橫向:
elementX>300 left=200 elmenttX<100 left=0
縱向:
elementY >300 top=200 elementY<100 top=0
- 大圖效果
<div class="large" :style="[
{
backgroundImage: `url(${imageList[activeIndex]})`,
backgroundPositionX: `${positionX}px`,
backgroundPositionY: `${positionY}px`,
},
]" v-show ="!isOutside" ></div>
background-repeat: no-repeat;
// 背景圖:盒子的大小 = 2:1 將來控制背景圖的移動來實現放大的效果檢視 background-position
background-size: 800px 800px;
這裡*2是因為圖片放大兩倍了 它的相對位置也放大兩倍
//控制大圖顯示
positionX.value=-left.value*2
positionY.value=-top.value*2
- 元件props適配
思路:在<ImageView/>這個元件中圖片的url不能夠寫死,把它設定為一個可以進行傳參的元件:
//props適配圖片列表
defineProps({//利用defineProps進行props適配
imageList:{//props名稱
type:Array,//型別
required:true,//是否必傳
default:()=>[]//預設值,工廠函式將其匯出為陣列。
}
})
利用元件的時候可以這樣寫:
<ImageView :image-list="goods.mainPictures"/>
思路總結:
- 封裝複雜互動元件的通用思路:
功能拆解 ——> 尋找核心實現思路 ——> 尋找關鍵技術 ——>
逐個實現,逐個驗證,最後最佳化
- 圖片預覽元件的封裝邏輯
小圖切換大圖顯示 ——> 獲取滑鼠相對位移 ——> useMouselnElement
(left ,top)
——>驗證最佳化
- 詳情頁-SKU元件(8月21日完善的)
問:在實際工作中,經常會經常遇到別人寫好的元件,熟系一個三方元件,首先重點看什麼?
答: props(入參)和emlit(出參) ,props決定了當前元件接收什麼資料,emit決定了會產出什麼資料
驗證元件是否成功使用:
傳入必要資料是否互動功能正常 ——> 點選選擇規格,是否正常產出資料
- 封裝SKU元件(沒學完有點難,還是下次再學吧)
初始化規格渲染——> 點選規格更新選中狀態——>點選規格更新禁用狀態
——> 產出選擇的SKU資料
- 詳情頁-通用元件統一註冊全域性
背景:components 目錄下有可能還會有很多其他通用型元件,有可能在多個業務模組中共享,所有統一進行全域性元件註冊比較好
思路:
Components外掛
把components目錄下的所有元件進行全域性註冊
Main.js(註冊外掛)
//把component中的所有元件都進行全域性化註冊
//透過外掛的方式
import ImageView from './ImageView.vue'
import SKU from './SKU.vue'
export const componentPlugin = {
install(app)//固定方法,固定引數
{
//app是createApp返回的例項
//app.component('元件名','元件配置引數')
app.component('ImageView', ImageView)
app.component('SKU', SKU)
}
}
//引入全域性元件外掛並註冊
import { componentPlugin } from './components'
app.use(componentPlugin)
- 登入-整體認識和路由配置
這個是其他的路由形式 好像使用<Routerlin也是可以的
<li><a href="javascript:;" @click="$router.push('/login')">請先登入</a></li><!--編寫登入事件-->
- 表單校驗的實現
作用:前端提前校驗可以省省去一些錯誤的請求提交,為後端節省壓力
表單資料——>前端校驗(過濾錯誤請求)——>後端查詢是否匹配
ElementPlus 表單元件內配置了表單校驗功能,只需要按照元件要求配置必要引數即可 :Element - 網站快速成型工具
el-input(雙向繫結表單資料)
el-form-item(繫結使用規則欄位)
el-form (繫結表單物件和規則物件)
當功能很複雜時,透過多個元件各自負責某個小功能,再組合成一個大功能是元件設計中常用的方法
表單校驗步驟:
1.按照介面欄位準備表單物件並繫結 2.按照產品要求準備規則物件並繫結
3.指定表單域的校驗欄位名 4.把表單物件進行雙向繫結
我們以下面的要求為例:
使用者名稱:不能為空 欄位名為account
密碼:不能為空且為6-14個字元,欄位名為 password
同意協議:必選,欄位名為 agree(還沒做完,我出錯了出錯是因為required寫錯啦)
- 自定義校驗規則(是否同意協議的校驗)
ElementPlus表單元件內建了初始的校驗配置,應付簡單的校驗只需要透過配置即可,如果想要定製一些特殊的校驗需求,可以使用自定義校驗規則,格式如下:
validator:(rule,val,callback)=>{
//自定義校驗邏輯
//val:當前輸入的資料
//callback:校驗處理函式 校驗透過呼叫
}
校驗邏輯:
如果勾選了協議框,透過邏輯,如果沒有勾選,不透過校驗
(我覺得這個自定定義校驗有問題,為啥一來就同意勾選)
- 整個表單的內容驗證
點選登入時需要對所有需要校驗的表單進行統一校驗
formEl.validate((valid) => {
if(valid){
console.log('登入成功')
}else{
console.log('登入失敗')
return false
}
})
1.獲取form元件例項 ——> 2.呼叫例項方法
- 登入-基礎登入業務實現
表單校驗——>封裝登入介面——>呼叫登入介面
登入成功後邏輯處理 登入失敗後業務邏輯(註冊頁面)
md介面壞了,為了進度我只可以自己寫介面了(md我來搞後端了)
(但是這個又來學後端感覺非常不好我們應該先學完這個前端再學後端吧)
(最終還是來學後端了,感覺自己是一個全棧技術人了)
gRPC[Nodejs]構建現代API和微服務gRPC[Nodejs] MasterClass: Build Modern API&Microservices_嗶哩嗶哩_bilibili
Mysql安裝以及視覺化配置
注意:不要安裝在c盤
https://class.m.imooc.com/qadetail?qid=296837
MySQL安裝教程(詳細版)_mysql安裝教程8.0.36-CSDN部落格
- 刪除並重灌mysql
教你徹底解除安裝MySQL 並重灌(保姆級教程 )_mysql怎麼解除安裝乾淨重灌-CSDN部落格