功能需求点
- 当点击频道中的汉堡按钮(编辑更多)时弹出层弹出
- 弹出层分两个内容板块,分别是我的频道和全部频道,在这两个模块中实现对频道的 新增,删除,点击跳转的功能需求
- 在对频道进行管理时也需要考虑到两种情况,一种是用户未登陆时频道的状态,还有用户已登陆时频道的状态
弹出层静态页面搭建
- 使用vant组件库中的Popup弹出层显示页面,然后再使用vant中的单元格组件和宫格组件搭建里面的内容,这里我考虑到弹出层在后面需要复用,所以单独封装了起来
- 弹出层代码
<!-- 频道编辑弹出层 -->
<van-popup
v-model="show"
closeable
close-icon-position="top-left"
position="bottom"
:style="{ height: '100%' }"
>
<!-- 编辑内容组件 -->
<channeledit :mychannel="channels" :active="active" @update-active="onUpdateActive" ></channeledit>
</van-popup>
<!-- 频道编辑弹出层 -->
- 弹出层中内容的组件代码
<!-- 我的频道 -->
<van-cell title="我的频道" :border="false">
<van-button size="mini" round type="danger" plain @click="isEdit = !isEdit">{{ isEdit ? '完成' : '编辑' }}
</van-button>
</van-cell>
<van-grid :gutter="10">
<van-grid-item class="channel-item" v-for="(channelItem, index) in mychannel" :key="index"
@click="onMyChannelClick(channelItem, index)"
>
<span class="text" :class="{ active: active === index }" slot="text">{{ channelItem.name }}</span>
<van-icon v-show="isEdit && !fiexdarr.includes(channelItem.id)" slot="icon" name="close" />
</van-grid-item>
</van-grid>
<!-- 我的频道 -->
<!-- 频道推荐 -->
<van-cell title="频道推荐" :border="false"></van-cell>
<van-grid class="recommend-grid" :gutter="10">
<van-grid-item class="channel-item" v-for="channel in recommendChannels" :key="channel.id"
:text="channel.name" icon="plus" @click="addChannel(channel)" />
</van-grid>
<!-- 频道推荐 -->
</div>
点击按钮切换状态
- 需求:需要点击编辑按钮,按钮状态变为保存,并且使我的频道显示叉号并且点击可以删除。
- 解决需求:定义一个变量isshow默认为false,然后给按钮绑定一个点击事件,当点击时对isshow属性取反,在插值语法中使用三元表达式完成对编辑和保存的文字切换
<van-button size="mini" round type="danger" plain
@click="isEdit = !isEdit">{{ isEdit ? '完成' : '编辑' }}</van-button>
我的频道模块页面渲染
- 封装我的频道网络请求
/**
* 获取我的频道列表信息
*/
export const getUserChannels = () => {
return request({
method: 'GET',
url: 'v1_0/user/channels'
})
}
2.定义一个空数组channels接收数据,通过父传子的方式将数据传到封装好的组件中
<!-- 编辑内容组件 -->
<channeledit :mychannel="channels" ></channeledit>
- 在组件中使用props来接受我的频道数据,在模版中遍历完成我的频道模块的初步渲染
频道推荐模块页面渲染
- 需求技术点:这里的频道推荐是基于对所有频道的数据进行筛选和判断来完成的,我的频道中已经有的数据,在推荐频道中就不再显示,点击删除我的频道,那推荐频道中就会多一个频道选项,点击添加频道,那推荐频道中就会少一个,我的频道就会增加一个
- 封装所有频道的网络请求
/**
* 获取所有频道
*/
export const getAllChannels = () => {
return request({
method: 'GET',
url: 'v1_0/channels'
})
}
- 在组件中发起获取所有频道数据的请求并定义空数组allChannels接收数据
// 封装一个函数loadAllChannels()加载所有频道
async loadAllChannels() {
try {
const { data } = await getAllChannels()
this.allChannels = data.data.channels
} catch (err) {
this.$toast('获取频道列表数据失败')
}
},
-
需求技术点分析1::在对所有频道进行筛选时,需要筛选出符合条件的数据(也就是我的频道中没有出现的数据),并且把这个数据放在频道推荐中渲染,这里要使用到数组的filter方法和find方法来嵌套筛选
-
需求技术点分析2:因为数据是在新增和删除中变动,所以使用计算属性来完成,当数据发生变动时,计算属性就会重新计算数据渲染页面,非常的方便。
-
代码实现逻辑:首先使用filter方法循环allChannels(所有频道),这样可以拿到每个频道对象的id号,然后在filter方法中使用find方法对mychannel(我的频道)进行循环,利用find方法特性,筛选出id号相同的数据并返回,最后给计算属性返回一个相反的数据,就可以拿到推荐频道所需要的。
// 推荐频道所需要的数据
recommendChannels() {
// 使用filter遍历所有频道数据
return this.allChannels.filter(channel => {
// 使用find方法查找所有频道数据中符合条件的元素并返回
const mychannels = this.mychannel.find(myChannel => {
return myChannel.id === channel.id
})
// 返回所有不符合find方法查找的元素,也就是我的频道中没有的数据,形成新的数组
return !mychannels
})
},
- 将筛选后的数组渲染到频道推荐组件上
<!-- 频道推荐 -->
<van-cell title="频道推荐" :border="false"></van-cell>
<van-grid class="recommend-grid" :gutter="10">
<van-grid-item class="channel-item" v-for="channel in recommendChannels" :key="channel.id"
:text="channel.name" icon="plus" @click="addChannel(channel)" />
</van-grid>
<!-- 频道推荐 -->
添加频道功能
-
功能逻辑:给推荐频道中每一项添加点击事件,在点击事件中传参数(频道项)在点击事件中将获得的频道项push进入我的频道数组中。
-
功能技术点:在这里需要考虑到数据持久化的问题,所以需要用到vuex,本地存储和axios技术来完成数据持久化
-
数据持久化实现逻辑:这里需要用vuex的mapstate获取token判断用户状态是已登陆还是未登陆,如果用户已经登陆,就调用接口将用户信息存储在线上,如果未登陆存储到本地当中
async addChannel(channel) {
this.mychannel.push(channel)
if (this.user) {
try {
// 已登录,数据存储到线上
await addUserChannel({
id: channel.id, // 频道 id
seq: this.mychannel.length // 频道的 序号
})
this.$toast('添加成功')
} catch (err) {
this.$toast('保存失败')
}
} else {
// 未登陆状态调用封装好的本地存储方法存储到本地
setItem('TOUTIAO_CHANNELS', this.mychannel)
}
}
删除频道功能
- 功能逻辑点:删除频道的功能也需要使用vuex的mapstate获取token判断用户的登陆状态来决定数据是存储在线上还是本地,但是这里需要根据按钮状态来决定是否可以删除,如果按钮是保存状态那表示可以删除如果是编辑状态则点击跳转到对应的页面。
1:当isEdit为false时候点击我的频道跳转到对应页面,并在滚动标签栏显示对应频道高亮,要给我的频道添加点击事件并在事件中通过isEdit变量判断是执行删除操作还是跳转操作
-
技术点:由于这里的跳转页面是通过控制滚动频道栏的active属性来控制具体跳转哪个页面的,所以需要对active做出修改,但是由于vue单项数据流的原因,无法在子组件中对简单数据做出修改,所以需要用到子传父的技术通知父亲修改
-
遇到的问题:由于我的频道中数组数据点击删除后,数组会实时更新索引,但是滚动频道栏的数组的active并没有实时更新,所以,会导致滚动栏的高亮与我的频道点击的不一致,这个时候需要做判断,当我点删除时,active的数据同时也要减1这样就可以让数据保持一致
//我的频道点击事件,过去频道数据和索引号
onMyChannelClick(channelItem, index) {
if (this.isEdit) {
// 执行删除操作
// 判断是否为推荐
if (this.fiexdarr.includes(channelItem.id)) return
if (index <= this.active) {
this.$emit('update-active', this.active - 1, true)
}
this.mychannel.splice(index, 1)
} else {
// 执行跳转操作
this.$emit('update-active', index, false)
}
- 封装一个数据持久化的删除函数
async deleteChannel(channel) {
try {
if (this.user) {
// 已登录,将数据存储到线上
await deleteUserChannel(channel.id)
} else {
// 未登录,将数据存储到本地
setItem('channles', this.userChannels)
}
} catch (err) {
console.log(err)
this.$toast('删除频道失败,请稍后重试')
}
}
- 在我的频道点击事件中调用,就可以完成删除频道的完整功能
onMyChannelClick(channelItem, index) {
if (this.isEdit) {
// 执行删除操作
// 判断是否为推荐
if (this.fiexdarr.includes(channelItem.id)) return
// 处理滚动栏active属性和删除后的索引不一致问题
if (index <= this.active) {
this.$emit('update-active', this.active - 1, true)
}
this.mychannel.splice(index, 1)
// 删除数据持久化
this.deleteChannel(channelItem)
} else {
// 执行跳转操作
this.$emit('update-active', index, false)
}
},