2021/12/22
5-15:入庫(kù)與出庫(kù)前端交互實(shí)現(xiàn)…
目標(biāo)一: 需要知道 modal ( 方法 ,參數(shù) , 源于 ’ ant - design - vue’ ) ,createVnode
(配置項(xiàng)(第一個(gè)參數(shù)是標(biāo)簽,第二個(gè)參數(shù)是props屬性),源于 ’ vue’ )
'ant - design - vue ’ 除了 message 外, 還有 Modal
彈窗 , Modal . confirm 之類的方法 。
Modal 和 message 雖然是 組件,但是可以當(dāng)成方法 ,直接在父組件使用 ,
因?yàn)橛玫奶摂M節(jié)點(diǎn)也就是Vnode,所以節(jié)點(diǎn)就寫(xiě)在了父組件.js文件里,值也就在父組件,這樣就不會(huì)像
自定義的組件一樣,還需要父子組件傳值,相比父子組件來(lái)講更加方便。
(一般而言,通過(guò)綁定事件去使用Modal 方法)
Modal.confirm 有兩個(gè)參數(shù),參數(shù)一:title 顯示標(biāo)題 參數(shù)二: content : 可以取
string , vnode , function
Modal.confirm 有 個(gè)方法,方法一 : onOk(){}
舉例:
Modal.confirm ({
title : " 要增加多少庫(kù)存 "
content : createVnode ( ’ div ’ , {
id : ’ ',
innerHTML : ’ < a > < /a> ’
}
})
目標(biāo)二 : 用 jsx 代替 js , 可以去掉 createVnode , 給 content 換上簡(jiǎn)易方法, content 加上圓括號(hào)
具體例子:
Modal.confirm({
title :" 要增加多少庫(kù)存",
content : (
< div >
< Input class = " .__book_input_count" />
< / div > //這里 ,Input 是從 ‘ ant - design - vue ’ 中引入來(lái)的。
),
onOk : async () = > {
const el = document . querySelector ( ’ .__book_input_count’)
const res = await book.updateCount ( { id : record.id , num: el.value , type })
…
}
關(guān)于 ctx
:/id —ctx.params ( 沒(méi)有第二個(gè)參數(shù))
{第二個(gè)參數(shù)對(duì)象 }—ctx.request.body
{params: data }— ctx.query
書(shū)籍修改操作:
依舊是先把后端部分的邏輯寫(xiě)清楚:
后端部分:
用到了擴(kuò)展運(yùn)算符(也叫剩余參數(shù)),關(guān)于擴(kuò)展運(yùn)算符,是用來(lái)生成可遍歷的對(duì)象屬性,特殊情況下
也可以遍歷數(shù)組,但是數(shù)組會(huì)以鍵值對(duì)的形式展現(xiàn)出來(lái)。
鏈接:https://www.cnblogs.com/wangyingblock/p/15309047.html#:~:text=%E6%89%A9%E5%B1%95%E8%BF%90%E7%AE%97%E7%AC%A6%20%28…%29%E6%98%AFES6%E7%9A%84%E8%AF%AD%E6%B3%95%EF%BC%8C%E7%94%A8%E4%BA%8E%E5%8F%96%E5%87%BA%E5%8F%82%E6%95%B0%E5%AF%B9%E8%B1%A1%E7%9A%84%E6%89%80%E6%9C%89%E5%8F%AF%E9%81%8D%E5%8E%86%E5%B1%9E%E6%80%A7%EF%BC%8C%E7%84%B6%E5%90%8E%E6%8B%B7%E8%B4%9D%E5%88%B0%E5%BD%93%E5%89%8D%E5%AF%B9%E8%B1%A1%E4%B9%8B%E4%B8%AD%E3%80%82,%E7%94%B1%E4%BA%8E%E6%95%B0%E7%BB%84%E6%98%AF%E7%89%B9%E6%AE%8A%E7%9A%84%E5%AF%B9%E8%B1%A1%EF%BC%8C%E6%89%80%E4%BB%A5%E5%AF%B9%E8%B1%A1%E7%9A%84%E6%89%A9%E5%B1%95%E8%BF%90%E7%AE%97%E7%AC%A6%E4%B9%9F%E5%8F%AF%E4%BB%A5%E7%94%A8%E4%BA%8E%E6%95%B0%E7%BB%84%E3%80%82%20%E5%A6%82%E6%9E%9C%E6%89%A9%E5%B1%95%E8%BF%90%E7%AE%97%E7%AC%A6%E5%90%8E%E9%9D%A2%E6%98%AF%E4%B8%80%E4%B8%AA%E7%A9%BA%E5%AF%B9%E8%B1%A1%EF%BC%8C%E5%88%99%E6%B2%A1%E6%9C%89%E4%BB%BB%E4%BD%95%E6%95%88%E6%9E%9C%E3%80%82
(這里是為了給書(shū)籍做修改操作,但是一個(gè)個(gè)判斷有沒(méi)有值再賦值太麻煩了,于是…)
這里只截取部分代碼:
const { id , …others } = ctx.request.body; // others長(zhǎng)這樣: { name:"",age:xx, }
const one = await Book.findOne({ _id:id}).exec();
Object.entries(others)// 關(guān)于 Object.entries ,如果是對(duì)象,那么結(jié)果就是 [ [ name, “”],[age,xx] ] 大概長(zhǎng)這樣,一個(gè)可遍歷的二維數(shù)組,所以它的value 長(zhǎng)這樣 [ key ,value ] 。 所以,forEach接收的function 的第一個(gè)參數(shù)是value ,對(duì)于二維數(shù)組是[key,value]
const newQuery = { };
Object.entries(others).forEach([key,value]) = > { if(value) { newQuery[key]=value;} });
Object.assign(one,newQuery);
const res = await one.save();
增加了一個(gè)update組件。
前端部分:
要增加一個(gè)< update > 組件。
關(guān)于 < add-one > 和 < update > 當(dāng) v-model:show = " true " 顯示的位置問(wèn)題:
因?yàn)榻M件本身是彈窗,所以顯示當(dāng)然也是按照彈窗的樣式來(lái)顯示的,所以顯示在最頂層沒(méi)有問(wèn)題滴。
在子組件內(nèi)部:
watch 監(jiān)聽(tīng)響應(yīng)式數(shù)據(jù)是否發(fā)生變化,如果變化,則去觸發(fā)傳遞給它的回調(diào)。
具體:
watch ( () = > props.book , ( current ) = > {
Object.assign ( editForm,curent)
這句話的意思是說(shuō),當(dāng)子組件發(fā)現(xiàn)父組件傳來(lái)的record不是當(dāng)前的record,那么就需要觸發(fā)這個(gè)回調(diào)函數(shù)。
通過(guò)當(dāng)下的Object.assign 來(lái)改變 editForm的值。
因?yàn)閜rops是對(duì)象所以才這樣寫(xiě)的,如果監(jiān)聽(tīng)的是普通類型就不是這個(gè)格式了,具體看鏈接:
https://www.cnblogs.com/baifangzi/p/14234981.html
關(guān)于為什么要用watch監(jiān)聽(tīng)響應(yīng)式對(duì)象:因?yàn)樗拍懿煊X(jué)到響應(yīng)式對(duì)象的變化,如果沒(méi)有watch
關(guān)于父組件是如何傳遞record給子組件的:通過(guò)中間變量curEditBook:
為了使得 props.book = record ,在父組件里的子組件 < update :book=“curEditBook” >
在js中,curEditBook.value = record ;
關(guān)于watch函數(shù)為什么要監(jiān)聽(tīng)props.book的解釋: 因?yàn)閟etup函數(shù)只執(zhí)行一次,而setup(props),
book又是props.book,如果再發(fā)生二次改變,setup也不會(huì)執(zhí)行,故需要引入watch()函數(shù)。
可以看一下案例:https://blog.csdn.net/weixin_42555053/article/details/115493192?spm=1001.2101.3001.6650.2&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-2.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-2.no_search_link
在Update/index.js中:
npm i moment:
import moment from ‘moment’(這個(gè)moment是javascript 日期處理類庫(kù),明天學(xué))
然后 在 watch() 函數(shù)中的 Object.assign 后面添加:
editForm.publishDate = moment ( Number( editForm.publishDate))
const submit = async () =>{
const res = await book.update({
id: props.book._id;
…editForm
拿到時(shí)間戳的方法: publishDate:editForm.publishDate.valueOf( )
書(shū)籍詳情頁(yè)前端頁(yè)面結(jié)構(gòu):
若是想給class = “items” 下級(jí)的最后一層item( class = “item”) 修改樣式,可以這樣寫(xiě):
(.items的直接下級(jí)是item)
.items{
&:last-child{
margin-bottom:0;
}
這個(gè)&:last-child 應(yīng)該是scss語(yǔ)法,&:nth-child 可以選擇任意直接子元素。
像css是 .items:last-child 用偽元素直接寫(xiě)。scss的話&表示items
前端聯(lián)調(diào)書(shū)籍詳情接口:
第一步:當(dāng)點(diǎn)擊詳情的時(shí)候會(huì)進(jìn)入另一個(gè)頁(yè)面,所以需要引入useRouter,也就是說(shuō):(在Books/index.js)
import { useRouter } from ‘vue-router’
const toDetail = ( { record } ) =>{
router.push(/books/${record._id});
之前在bookDetail/index.js中有:
import { useRoute } from ‘vue-router’
兩者的區(qū)別是:
useRoute:表示當(dāng)前頁(yè)面相關(guān)信息,比如url里的參數(shù)有哪些,對(duì)應(yīng)的params有哪些,query有哪些
useRouter:里面存的是操作路由的一些方法。比如前進(jìn)頁(yè),后退頁(yè),跳到某一頁(yè)。
第二步,onMounted
第三步:當(dāng)跳轉(zhuǎn)頁(yè)面后,在bookDetail/index.js 將對(duì)不同的id做不同的處理,如下:
import { useRoute } from ‘vue-router’
setup(){
const route = useRoute();
const id = route.params.id;
es6的新方法:自動(dòng)填充,默認(rèn)填充的是空格。
padStart ,padEnd
第一個(gè)參數(shù)是總長(zhǎng)度,若取值為n,padStart默認(rèn)向前填充n-目前長(zhǎng)度。
第二個(gè)參數(shù)可以指定填充什么。
具體做法看鏈接:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String/padStart
這個(gè)padStart可以用在格式化日期上,hin好用就素了。
舉例子:‘1’.padStart(4,’&’) 是字符串方法所以不能用數(shù)字。
結(jié)果:’&&&1’
數(shù)字轉(zhuǎn)換為字符串的方法: .toString 或者 String( )
所以格式化日期自動(dòng)填充零的方法:
const tsPadStart = (str) = >{
str = String ( str ); //把數(shù)字轉(zhuǎn)換為字符串
return str.padStart(2,‘0’);
}
業(yè)務(wù)方面有些看不懂可以先學(xué)會(huì)知識(shí)點(diǎn)然后再琢磨琢磨。
目前學(xué)到的獲取id有兩種,一種是通過(guò)useRoute()也就是 route.params.id 去url路徑獲取,
一種就是通過(guò)< a-table > 的< template # xx > 去獲取 data.record.id
關(guān)于useRouter ,也就是項(xiàng)目的router,有一個(gè)方法是replace,也就是用某頁(yè)代替當(dāng)前頁(yè),并且到了
某頁(yè)以后就無(wú)法回到當(dāng)前頁(yè)了,這個(gè)很適合刪除的業(yè)務(wù)邏輯。
舉例:
router.replace(’/books’) : 從當(dāng)前頁(yè)進(jìn)入/books頁(yè)面。
!!!!!!!!!!!!!!!!!!!!
以前總在想根據(jù)url 有# ,這個(gè)router.replace 或者 router.push 需不需要加#呢,現(xiàn)在才明白人家
是直接在路由表里面找的~路由表怎么寫(xiě)它就怎么進(jìn),跟url沒(méi)有直接關(guān)系!
是按照router/index.js 里的配置進(jìn)行的路徑查找!
庫(kù)存日志服務(wù)端相關(guān)內(nèi)容實(shí)現(xiàn):
這個(gè)涉及日志了啊!要好好學(xué)!!
好像沒(méi)啥難度… 用文檔保存一次次記錄。
還有寫(xiě)一個(gè)獲取所有列表的接口。
log.save()可以異步,所以不用加await。
庫(kù)存日志接口聯(lián)調(diào)和列表實(shí)現(xiàn):
操作時(shí)間 : record.meta.createdAt
書(shū)籍相關(guān)內(nèi)容優(yōu)化:
其實(shí)就是對(duì)createdAt的優(yōu)化,meta: getMeta()
時(shí)間的創(chuàng)建開(kāi)始于Schema的創(chuàng)建,那么時(shí)間就是固定的,這樣是不合理的,因此要進(jìn)行優(yōu)化。
對(duì)于createdAt時(shí)間,如果每次都是手動(dòng)去寫(xiě)就會(huì)很麻煩,因此我們可以通過(guò)利用Mongoose提供的
鉤子,它會(huì)在每次文檔保存之前,去插入一些代碼做一些事情。
寫(xiě)在db/helpers.js const getMeta之后。
const preSave= function ( next ) {
if(this.isNew){
const ts = Date.now();
this[‘meta’].createdAt = ts
…
}
當(dāng)函數(shù)被調(diào)用的時(shí)候,next會(huì)由mongoose傳遞過(guò)來(lái),next()告訴mongoose可以繼續(xù)執(zhí)行。
寫(xiě)在db/schemas/InventoryLog.js中:
InventoryLogSchema.pre(‘save’,preSave);
(通過(guò)這句話完成了函數(shù)的鉤子注冊(cè))
一些字符串方法:slice 截取 比如只截取最后思維 str.slice(-4)
當(dāng)學(xué)會(huì)了str.padStart以及str.slice之后,就可以實(shí)現(xiàn)截取手機(jī)號(hào)后四位并對(duì)手機(jī)號(hào)前面位數(shù)進(jìn)行加密
的應(yīng)用了:
代碼如下:
fullNumber.slice(-4)
‘5581’
const phonenumber = ‘13698512348’
const lastnumber = phonenumber.slice(-4)
const nownumber = lastnumber.padStart(phonenumber.length,’*’);
nownumber
‘*******2348’
nownumber就是加密后的手機(jī)號(hào)碼~
一個(gè)js的小知識(shí): 只有NaN不等于自身。
一個(gè)業(yè)務(wù)小知識(shí):如果某個(gè)東西只是單純的顯示隱藏,不涉及數(shù)據(jù)方面,那么可以用上v-if or v-show.
總結(jié)
以上是生活随笔為你收集整理的2021/12/22的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 邮箱注册申请,怎么快速了解并注册邮箱?
- 下一篇: 菜园租种农场认养土地认领带你感受不一样的