硅谷后台项目中遇到的问题
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
删除品牌:点击确认之后发送请求>>>要进行页面个数判断,小于一跳转到上一页
三级联动(商品管理)
封装一个全局组件: 一般放在component里面,需要在main.js里引入
import CategorySelect from '@/components/CategorySelect';
Vue.component( CategorySelect.name, CategorySelect);
// 这样就封装好了
使用el-card:实现边框阴影效果
三级联动,请求分类的数据时,因为request请求封装了一次(在模板response里不等于两万,出现莫名错误):加上&& res.code!=200 解决
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的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的值获取不到