后台项目中遇到的问题

265 阅读5分钟

硅谷后台项目中遇到的问题

vue解决seo问题

  • 搜索引擎优化

打包之后出现空白页

Promise.then .catch 与async await

login({commit},userInfo){
    const {username,password} = userInfo
    return new Promise((resolve,reject) => {
    login({username:username.trim(),password:password}).then(response =>{
        const {data} = response
        commit('SET_TOKEN',data.token)
        setToken(data.token)
        resolve()
        }).catch(error => {
            reject(error)
        })
    }
}
                       
// async 方法
async login({commit},userInfo){
         const {username,password} = userInfo
         let result = await login({username:username.trim(),password:password})
         if(result.code == 200){
             commit('SET_TOKEN',result.data.token)
             setToken(result.data.token)
             return 'ok'
         }else{
             return Promise.reject(new Error('faile'))
         }
    }

防抖节流

let inp = document.querySelector('input')
let t = null
inp.oninput  = function(){ //oninput 事件在用户输入时触发。
    if(t!==null){
        clearTimeout(t)
    }
    t = setTimeout(()=>{
        console.log(this.value)
    },500)
}

封装一个使用闭包实现防抖的方法

let inp = document.querySelector('input')
inp.oninput = debounce(function(){
     console.log(this.value)
},500)
//封装一个函数,再使用闭包   下面这个写法,上面this指向window,计时器里面的this指向是input,通过.call改变fn指向
function debounce(fn,delay){
    let t = null
    return function(){
        if(t!==null){
            clearTimeout(t)
        }
        t = setTimeout(()=>{
            fn()
        },delay)
    }
}
​
//更新写法
function debounce(fn,delay){
    let t = null
    return function(){
        if(t!==null){
            clearTimeout(t)
        }
        t = setTimeout(()=>{
            fn.call(this)
        },delay)
    }
}

节流

  • 在手敲节流的时候,滑动滚轮没有触发事件,猜测原因:没有滚动条出来的页面没有滚轮事件,把body高度加大使其具备滚轮
// 控制高频事件执行次数
let flag = true
window.onscroll = function(){
    if(flag){
        setTimeout(()=>{
            console.log("hello")
            flag = true
        },500)
    }
    flag = false
}
​
//封装节流window.onscroll = throttle(function(){
     console.log("hello")
},500)
​
​
function throttle(fn,delay){
    let flag = true
    return function(){
        if(flag){
            setTimeout(()=>{
                console.log("hello")
                fn.call(this)
                flag = true
            },delay)
    }
    flag = false
    }
}

element分页器的应用细节

  • 想实现分页器的左右布局展示顺序:按照书写的顺序展示,用 -> 可以实现右边的代码在最后边展示
<el-pagination
      style="margin-top: 20px; text-align: center"
      :current-page="page"
      :total="total"
      :page-size="limit"
      :pager-count="7"
      :page-sizes="[3, 5, 10]"
      @current-change="getPageList"
      @size-change="handleSizeChange"
      layout="prev, pager, next, jumper,->,sizes,total"
    >
</el-pagination>

启动项目的要注意的地方

在axios二次封装里面,请求拦截器的请求头设置的什么值,这个需要和后端确认一下

调用商品列表API

宽度按要求设置

左边加上序号:type='index'

prop的作用:对应列内容的字段名

列表里展示图片: 用到作用域插槽(后台接口返回的是图片的地址), $index:数组中每个元素相应的索引值,

表单里添加:model form表单 :model属性,这个属性的作用是,把表单的数据收集到那个对象的身上 ,将来表单验证,也需要这个属性

点击取消,表单的数据仍然被更改: //将已有的品牌信息赋值给tmForm进行展示

//将服务器返回品牌的信息,直接赋值给了tmForm进行展示。

//也就是tmForm存储即为服务器返回品牌信息

this.tmForm = { ...row }; // 浅拷贝一下,解决这个问题

自定义弹出状态颜色:

this.$message({type:'success',message:this.xxx.id?'修改品牌成功':'添加品牌成功'})

自定义校验规则:

当删除选项之后应该进行的操作: 进行判断,如果总页数大于一,那么就应该停留在当前页面,如果等于一就跳转到一


添加修改品牌

三目运算符判断是否存在id,鉴别是添加还是修改

修改时点击取消,页面数据仍然修改----浅拷贝之后再赋值{...}

表单验证:所有验证通过了再发送请求 >>>>自定义检验规则是重点 :model :rules :ref

删除品牌:点击确认之后发送请求>>>要进行页面个数判断,小于一跳转到上一页

image-20220723162228560.png

三级联动(商品管理)

封装一个全局组件: 一般放在component里面,需要在main.js里引入

import CategorySelect from '@/components/CategorySelect';
Vue.component( CategorySelect.name, CategorySelect);
// 这样就封装好了

使用el-card:实现边框阴影效果

三级联动,请求分类的数据时,因为request请求封装了一次(在模板response里不等于两万,出现莫名错误):加上&& res.code!=200 解决

image-20220724124415362.png

el-form表单 在data(){return xxx{ aa bb cc}}里面定义了数据,需要在表单头绑定 :model="xxx",下面el-form-item要使用里面的数据时,v-model="xxx.aaa"

在elementUI 表单标签里面:model 只表示动态绑定表单数据对象


在三级联动,子组件把三级的id传递给父组件,传递多个参数,所以选择对象,那么在获取的时候就可以使用解构,({ }) 在括号里面加上花括号


全局组件里面代码写到了点击一级清除二三级,之后的代码回到view对应的组件里面写: 本身写成全局组件就是为了复用,不通用的业务在各自的组件里完成就好,于是使用了自定义事件子传父

属性添加

使用作用域插槽:

<el-table-column prop="prop" label="属性值列表" width="width">
    <template slot-scope="{ row, $index }">
        <el-tag
            type="success"
            v-for="(attrValue, index) in row.attrValueList"
            :key="attrValue.id"
            style="margin: 0px 20px"
            >{{ attrValue.valueName }}
    </el-tag>
    </template>
</el-table-column>                                                                                                               

对象里面的属性是无序的: 不要在data(){ } 里面在定义属性的时候,获取另外一个同样在data里的数据,

粗心bug: 在elementUI里面使用作用域插槽,<template slot-scope="{row, $index}"> 忘记加{ } 了,导致Input 无法输入值

点击取消,table数据仍然修改: 数据结构不复杂直接使用解构进行拷贝,当有多层嵌套的时候,需要使用别得方法进行深拷贝

  • 但是如果解构的是那种一维数组且里面的数据是简单类型,和那种对象里面是简单类型的是深拷贝。其他情况都是浅拷贝。

引入lodash插件深拷贝的方式: import cloneDeep from "lodash/cloneDeep"; 疑惑:为啥直接from "lodash"

粗心bug: row.flag = false;放在了方法的第一行,导致后续判断都失效

添加在响应式对象里添加响应式数据

  • 向响应式对象中添加一个 property,并确保这个新 property 同样是响应式的,且触发视图更新。

    //第一个参数:对象 第二个参数:添加新的响应式属性 第三参数:新的属性的属性值

表单元素自动聚焦

添加新属性

  • 点击添加属性,光标自动聚焦到新添加的input框里,使用this.attrInfo.attrValueList.length -1获取最新位次

修改属性--单选修改

  • 排他思想,只能选中一个,选中后自动聚焦,使用row的index确定位次,动态绑定到ref身上,使用index确定位次,动态绑定到ref身上,使用refs[index]获取

elementUI版本问题

  • 使用模板的时候,注意elementUI版本,点开官网看到的2.0最新版,不同的版本在代码的书写上,可能会存在差异

保存属性

尝试直接使用async await 出现错误

  • 找到错误:if(result.code == 200){ } 没有加上.code

SPU模块

注意绑定的属性需要在data()里面初始化,

elementUI里面也有对button的提示,但这个项目里选择自己封装一个

  • 我封装了一个Test,发现网上所说的el-title是横屏显示的一个提示

  • 而另一个点击效果是通过this.$message({message:' ',type:' ' })实现

    • 自行封装组件----就是注册使用一个全局组件,在需要提示的地方使用
    • v-bind="$attrs" v-on="$listeners"这两个需要研究一下
<template>
    <a :title="title" style="margin:10px">
        <el-button v-bind="$attrs" v-on="$listeners"></el-button>
    </a>
</template><script>
export default {
    name:'HintButton',
    props:["title"]
}
</script><style scoped></style>

在el-button标签里面不能使用:完整写法v-bind

在做分页器的时候,出现了getSpuList undefined错误,更改分页器点击当前页数函数位置后,bug消失

局部组件的使用,引入,注册,使用

  • 注意:components和methods:{ } 平级
components: {
    SpuForm,
    SkuForm,
  },

在父组件里面可以获取到子组件

  • 可以通过这个特性来调用子组件的方法,同时也可以传值给子组件
  • 用ref='spu'绑定子组件名字 需要使用子组件方法时 $refs.spu.需要使用的方法

bug

  • changeScene(scene){ } 传递过来的数据是普通数据类型的时候,不能采取解构获取

    • 如果写成changeScene({ scene }){ } 那么scene的值获取不到