商品的参数用于显示商品的固定的特征。
整体布局如下:
面包屑导航就不说了,主要是下面的级联选择器和添加参数的按钮,当选择商品的三级分类时,下面的卡片视图区域会对应出现动态参数和静态参数的面板
1、我们需要设置级联框的属性,主要步骤是先获取API数据,再配置到级联框中,显示的值为cat_id,绑定到label。其中,prop为配置选项,其中包括:expandTrigger——指定次级菜单的展开方式; value——指定选项的值为选项对象的某个属性值cat_id; label——指定选项标签为选项对象的某个属性值,这里指定为cat_name。
<el-row class="cat_opt">
<el-col>
<span>选择商品分类:</span>
<!-- 选择商品分类的级联选择框 -->
<el-cascader v-model="selectedCateKeys" :options="cateList"
:props="{
expandTrigger: 'hover',
value:'cat_id',
label:'cat_name',
children:'children'}"
@change="handleChange"></el-cascader>
</el-col>
</el-row>
options为可选项数据源,键名可通过 Props 属性配置,我们这里需要获取所有的参数列表,通过文档给定的API请求数据,并通过options进行配置。将级联选择框选中的项双向绑定到数组身上。
2、级联框选中发生变化,会触发该函数,获取对应参数,参数更新使用的getParamsData函数,考虑到很多操作会引起参数更新,比如:级联框的选中状态、tab页签中动态和静态参数的点击,所以将参数更新的函数写成了getParamsData函数。
定义级联框选中发生变化,会触发的函数handleChange。
//级联框选中发生变化,会触发该函数
handleChange(){
this.getParamsData()
}
async getCateList(){
const{data:res}=await this.$http.get('categories')
if(res.meta.status !== 200){
return this.$http.error('获取商品分类失败')
}
//console.log(res.data);
this.cateList=res.data;
console.log(this.cateList);
}
这里的selectedCateKeys即级联选择框选定的数组,选中范围设置为第三及分类设置相关参数,通过判断选中的数组长度判断,如果不是,则直接清空数组,无法选中。
async getParamsData(){
//console.log(this.selectedCateKeys);
//以数组长度判断,选中第三级分类,不选中则清空选中状态
if(this.selectedCateKeys.length!==3){
this.selectedCateKeys=[]
this.manyTableData=[]
this.onlyTableData=[]
return
}
3、展示数据使用了element ui中的el-tag,用于分隔内容上有关联但属于不同类别的数据集合。Tabs 组件提供了选项卡功能,默认选中第一个标签页。activeName:‘many’
该项目中v-model 绑定值与选中选项卡的 name对应,当选中哪个
name 与选项卡绑定值 value 对应的标识符,表示选项卡别名
tab页签点击触发事件的处理函数handleTabClick
```css
handleTabClick(){
//console.log(this.activeName)
this.getParamsData()
}
点击页签的同时要获取到对应面板应获取的值
const{data:res}=await this.$http.get(`categories/${this.cateId}/attributes`,
{params:{sel:this.activeName}}
)
if(res.meta.status!==200){
return this.$message.error('获取参数列表失败')
}
看下动态参数面板el-tab-pane的代码:
<el-tab-pane label="动态参数" name="many" >
<!-- 添加参数的按钮 -->
<el-button type="primary" size="mini" @click="adddialogVisible=true" :disabled="isBtnDisabled">添加参数</el-button>
<!-- 动态参数表格 -->
<el-table :data="manyTableData" border stripe>
<!-- 展开行 -->
<el-table-column type="expand">
<template slot-scope="scope">
<el-tag v-for="(item,i) in scope.row.attr_vals" :key="i" closable @close="handleClose(i,scope.row)">{{item}}</el-tag>
<!-- 输入的文本框 -->
<el-input class="input-new-tag" v-if="scope.row.inputVisible" v-model="scope.row.inputValue" ref="saveTagInput" size="small" @keyup.enter.native="handleInputConfirm(scope.row)"
@blur="handleInputConfirm(scope.row)"> </el-input>
<!-- 添加的按钮 -->
<el-button v-else size="small" @click="showInput(scope.row)">+ New Tag</el-button>
</template>
</el-table-column>
<!-- 索引列 -->
<el-table-column type="index"></el-table-column>
<el-table-column label="参数名称" prop="attr_name"></el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button size="mini" type="primary" icon="el-icon-edit"
@click="showEditDialog(scope.row.attr_id)">编辑</el-button>
<el-button size="mini" type="danger" icon="el-icon-delete"
@click="removeParams(scope.row.attr_id)">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
4、获取到的数据分别是动态参数和静态属性,绑定到表格el-table的data上,分别命名为
//动态属性数据
manyTableData:[]
//静态属性
onlyTableData:[]
数据的获取就还是getParamsData,判断activeName给定赋值为哪个数组。
async getParamsData(){
//console.log(this.selectedCateKeys);
//以数组长度判断,选中第三级分类,不选中则清空选中状态
if(this.selectedCateKeys.length!==3){
this.selectedCateKeys=[]
this.manyTableData=[]
this.onlyTableData=[]
return
}
//选中三级分类
//console.log(this.selectedCateKeys);
//根据所选的分类id,和当前所处面板,获取对应的参数
const{data:res}=await this.$http.get(`categories/${this.cateId}/attributes`,
{params:{sel:this.activeName}}
)
if(res.meta.status!==200){
return this.$message.error('获取参数列表失败')
}
//console.log(res.data);
//获取到参数,需要处理,将字符串循环分割为数组(可能为空),这里要对字符串进行三元表达式判断
res.data.forEach(item=>{
item.attr_vals=item.attr_vals?item.attr_vals.split(','):[];
//控制每个单独的文本框的显示和隐藏
item.inputVisible=false
//文本框输入的值
item.inputValue=''
})
//console.log(res.data);
//获取到的数据进行判断
if(this.activeName==='many'){
this.manyTableData=res.data
}else{
this.onlyTableData=res.data
}
}
表格的基本组成则是一列列el-table-column,基本的索引列有参数名称、操作(编辑、删除)。
<el-table-column type="index"></el-table-column>
<el-table-column label="参数名称" prop="attr_name"></el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button size="mini" type="primary" icon="el-icon-edit"
@click="showEditDialog(scope.row.attr_id)">编辑</el-button>
<el-button size="mini" type="danger" icon="el-icon-delete"
@click="removeParams(scope.row.attr_id)">删除</el-button>
</template>
</el-table-column>
5、还有每一行都是展开列(效果如下图),通过模板列实现。
```css
<el-table-column type="expand">
<template slot-scope="scope">
<el-tag v-for="(item,i) in scope.row.attr_vals" :key="i" closable @close="handleClose(i,scope.row)">{{item}}</el-tag>
<!-- 输入的文本框 -->
<el-input class="input-new-tag" v-if="scope.row.inputVisible" v-model="scope.row.inputValue" ref="saveTagInput" size="small" @keyup.enter.native="handleInputConfirm(scope.row)"
@blur="handleInputConfirm(scope.row)"> </el-input>
<!-- 添加的按钮 -->
<el-button v-else size="small" @click="showInput(scope.row)">+ New Tag</el-button>
</template>
</el-table-column>
template指定slot-scope=“scope”,会接受每行的数据,主要是将scope.row.attr_vals循环渲染到一个个tag中, 首先这个参数在前面的getParamsData中已经得到,但是由于后台传入的数据是字符串形式,获取到参数后需要处理,将字符串循环分割为数组(可能为空),这里要对字符串进行三元表达式判断,如果不为空则以逗号分割。
res.data.forEach(item=>{
item.attr_vals=item.attr_vals?item.attr_vals.split(','):[];
//控制每个单独的文本框的显示和隐藏
item.inputVisible=false
//文本框输入的值
item.inputValue=''
})
还有个比较有趣的是实现tag标签与文本框的切换,点击+New Tag,文本框失去焦点或按下enter都会触发handleInputConfirm,由于初始默认文本框状态为ture,函数触发后状态取反,文本框变换成tag标签。v-if/else实现转换。
<el-input class="input-new-tag" v-if="scope.row.inputVisible" v-model="scope.row.inputValue" ref="saveTagInput" size="small" @keyup.enter.native="handleInputConfirm(scope.row)"
@blur="handleInputConfirm(scope.row)"> </el-input>
<!-- 添加的按钮 -->
<el-button v-else size="small" @click="showInput(scope.row)">+ New Tag</el-button>
async handleInputConfirm(row){
// console.log('ok');
if(row.inputValue.trim().length===0){
row.inputValue=''
row.inputVisible=false
return
}
6、完成添加参数或属性的操作,其实出现的对话框是同类型的,就是文字不一样,因此这里只写了一个el-dialog,通过条件判断渲染哪个类型的参数。核心是根据激活的页签activeName判断显示参数名字。
titleText(){
if(this.activeName==='many'){
return '动态参数'
}
return '静态参数'
}
<el-dialog :title="'添加'+titleText" :visible.sync="adddialogVisible" width="50%" @close="addDialogClosed">
<!-- 添加参数的表单 -->
<el-form :model="addForm" ref="addFormRef" :rules="addFormRules" label-width="100px">
<el-form-item :label="titleText" prop="attr_name">
<el-input v-model="addForm.attr_name"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="adddialogVisible = false">取 消</el-button>
<el-button type="primary" @click="addParams">确 定</el-button>
</span>
</el-dialog>
7、后面点击修改和删除按钮会弹出对话框,与前面同,不赘述。