2021/12/22

时间:2025-03-09 09:44:03

5-15:入库与出库前端交互实现…
目标一: 需要知道 modal ( 方法 ,参数 , 源于 ’ ant - design - vue’ ) ,createVnode
(配置项(第一个参数是标签,第二个参数是props属性),源于 ’ vue’ )

'ant - design - vue ’ 除了 message 外, 还有 Modal

弹窗 , Modal . confirm 之类的方法 。

Modal 和 message 虽然是 组件,但是可以当成方法 ,直接在父组件使用 ,
因为用的虚拟节点也就是Vnode,所以节点就写在了父组件.js文件里,值也就在父组件,这样就不会像
自定义的组件一样,还需要父子组件传值,相比父子组件来讲更加方便。
(一般而言,通过绑定事件去使用Modal 方法)

有两个参数,参数一:title 显示标题 参数二: content : 可以取
string , vnode , function
有 个方法,方法一 : onOk(){}
举例:
({
title : " 要增加多少库存 "
content : createVnode ( ’ div ’ , {
id : ’ ',
innerHTML : ’ < a > < /a> ’
}
})

目标二 : 用 jsx 代替 js , 可以去掉 createVnode , 给 content 换上简易方法, content 加上圆括号

具体例子:
({
title :" 要增加多少库存",
content : (
< div >
< Input class = " .__book_input_count" />
< / div > //这里 ,Input 是从 ‘ ant - design - vue ’ 中引入来的。
),
onOk : async () = > {
const el = document . querySelector ( ’ .__book_input_count’)
const res = await ( { id : , num: , type })

}

关于 ctx

:/id — ( 没有第二个参数)
{第二个参数对象 }—
{params: data }—

书籍修改操作:
依旧是先把后端部分的逻辑写清楚:

后端部分:
用到了扩展运算符(也叫剩余参数),关于扩展运算符,是用来生成可遍历的对象属性,特殊情况下
也可以遍历数组,但是数组会以键值对的形式展现出来。
链接:/wangyingblock/p/#:~: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
(这里是为了给书籍做修改操作,但是一个个判断有没有值再赋值太麻烦了,于是…)
这里只截取部分代码:
const { id , …others } = ; // others长这样: { name:"",age:xx, }
const one = await ({ _id:id}).exec();
(others)// 关于 ,如果是对象,那么结果就是 [ [ name, “”],[age,xx] ] 大概长这样,一个可遍历的二维数组,所以它的value 长这样 [ key ,value ] 。 所以,forEach接收的function 的第一个参数是value ,对于二维数组是[key,value]
const newQuery = { };
(others).forEach([key,value]) = > { if(value) { newQuery[key]=value;} });
(one,newQuery);
const res = await ();
增加了一个update组件。

前端部分:
要增加一个< update > 组件。
关于 < add-one > 和 < update > 当 v-model:show = " true " 显示的位置问题:
因为组件本身是弹窗,所以显示当然也是按照弹窗的样式来显示的,所以显示在最顶层没有问题滴。

在子组件内部:
watch 监听响应式数据是否发生变化,如果变化,则去触发传递给它的回调。
具体:
watch ( () = > , ( current ) = > {
( editForm,curent)
这句话的意思是说,当子组件发现父组件传来的record不是当前的record,那么就需要触发这个回调函数。
通过当下的 来改变 editForm的值。
因为props是对象所以才这样写的,如果监听的是普通类型就不是这个格式了,具体看链接:
/baifangzi/p/
关于为什么要用watch监听响应式对象:因为它才能察觉到响应式对象的变化,如果没有watch
关于父组件是如何传递record给子组件的:通过中间变量curEditBook:
为了使得 = record ,在父组件里的子组件 < update :book=“curEditBook” >
在js中, = record ;

关于watch函数为什么要监听的解释: 因为setup函数只执行一次,而setup(props),
book又是,如果再发生二次改变,setup也不会执行,故需要引入watch()函数。

可以看一下案例:/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/中:
npm i moment:
import moment from ‘moment’(这个moment是javascript 日期处理类库,明天学)

然后 在 watch() 函数中的 后面添加:
= moment ( Number( ))

const submit = async () =>{
const res = await ({
id: ._id;
…editForm

拿到时间戳的方法: publishDate:( )

书籍详情页前端页面结构:
若是想给class = “items” 下级的最后一层item( class = “item”) 修改样式,可以这样写:
(.items的直接下级是item)

.items{
&:last-child{
margin-bottom:0;
}
这个&:last-child 应该是scss语法,&:nth-child 可以选择任意直接子元素。
像css是 .items:last-child 用伪元素直接写。scss的话&表示items

前端联调书籍详情接口:
第一步:当点击详情的时候会进入另一个页面,所以需要引入useRouter,也就是说:(在Books/)

import { useRouter } from ‘vue-router’
const toDetail = ( { record } ) =>{
(/books/${record._id});

之前在bookDetail/中有:

import { useRoute } from ‘vue-router’

两者的区别是:
useRoute:表示当前页面相关信息,比如url里的参数有哪些,对应的params有哪些,query有哪些
useRouter:里面存的是操作路由的一些方法。比如前进页,后退页,跳到某一页。

第二步,onMounted

第三步:当跳转页面后,在bookDetail/ 将对不同的id做不同的处理,如下:

import { useRoute } from ‘vue-router’
setup(){
const route = useRoute();
const id = ;

es6的新方法:自动填充,默认填充的是空格。
padStart ,padEnd
第一个参数是总长度,若取值为n,padStart默认向前填充n-目前长度。
第二个参数可以指定填充什么。
具体做法看链接:/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String/padStart
这个padStart可以用在格式化日期上,hin好用就素了。
举例子:‘1’.padStart(4,’&’) 是字符串方法所以不能用数字。
结果:’&&&1’

数字转换为字符串的方法: .toString 或者 String( )

所以格式化日期自动填充零的方法:

const tsPadStart = (str) = >{
str = String ( str ); //把数字转换为字符串
return (2,‘0’);
}

业务方面有些看不懂可以先学会知识点然后再琢磨琢磨。

目前学到的获取id有两种,一种是通过useRoute()也就是 去url路径获取,
一种就是通过< a-table > 的< template # xx > 去获取

关于useRouter ,也就是项目的router,有一个方法是replace,也就是用某页代替当前页,并且到了
某页以后就无法回到当前页了,这个很适合删除的业务逻辑。
举例:
(’/books’) : 从当前页进入/books页面。

!!!!!!!!!!!!!!!!!!!!
以前总在想根据url 有# ,这个 或者 需不需要加#呢,现在才明白人家
是直接在路由表里面找的~路由表怎么写它就怎么进,跟url没有直接关系!
是按照router/ 里的配置进行的路径查找

库存日志服务端相关内容实现:
这个涉及日志了啊!要好好学!!

好像没啥难度… 用文档保存一次次记录。
还有写一个获取所有列表的接口。
()可以异步,所以不用加await。

库存日志接口联调和列表实现:
操作时间 :

书籍相关内容优化:
其实就是对createdAt的优化,meta: getMeta()
时间的创建开始于Schema的创建,那么时间就是固定的,这样是不合理的,因此要进行优化。
对于createdAt时间,如果每次都是手动去写就会很麻烦,因此我们可以通过利用Mongoose提供的
钩子,它会在每次文档保存之前,去插入一些代码做一些事情。

写在db/ const getMeta之后。

const preSave= function ( next ) {
if(){
const ts = ();
this[‘meta’].createdAt = ts

}

当函数被调用的时候,next会由mongoose传递过来,next()告诉mongoose可以继续执行。

写在db/schemas/中:

(‘save’,preSave);
(通过这句话完成了函数的钩子注册)

一些字符串方法:slice 截取 比如只截取最后思维 (-4)

当学会了以及之后,就可以实现截取手机号后四位并对手机号前面位数进行加密
的应用了:
代码如下:

(-4)
‘5581’
const phonenumber = ‘13698512348’
const lastnumber = (-4)
const nownumber = (,’*’);
nownumber
‘*******2348’
nownumber就是加密后的手机号码~

一个js的小知识: 只有NaN不等于自身。

一个业务小知识:如果某个东西只是单纯的显示隐藏,不涉及数据方面,那么可以用上v-if or v-show.