The main functions to be implemented are as follows:
Information list, TAB page switch, article report, channel management, article details, reading memory, focus on function, like function, comment function, reply to comment, search function, login function, personal center, edit information, xiaozhi students…
Today to achieve the main function is: channel add delete function
Channel 1 Management
1.1 Understanding Requirements
On the right side of the channel list, put a button, click this button can pop layer, to pop layer components to display the channel management page
1.2 inviews/home/home.vue
Add button and elastic layer in
<div class='index'> <! -- V-model bidirectional binding: which subscript channels are active --> <van-tabs V-model ="activeIndex">....... </van-tabs> <! <div class="bar-btn" @click="isShowChannelEdit=true"> <van-icon name="wap-nav"/> </div> <! <van-action-sheet v-model="isShowChannelEdit" title=" title "> <p> channel management </p> <p> channel management </p> <p> Channel management </p> </van-action-sheet> </div>Copy the code
Add a variable to data that controls channel editing
data() { return { // .... + isShowChannelEdit: false, // Show channel edit layer}}Copy the code
1.3 Add styles to buttons in Style (Local Styles)
// Channel management switch button. Bar-btn {position: fixed; right: 5px; top: 57px; display: flex; align-items: center; background-color: #fff; Opacity: 0.8; z-index:1; .van-icon-wap-nav{ font-size: 20px; }}Copy the code
1.4 Click the button to test the effect
2 Architecture channel management component
2.1 Because of the complexity of the function, we added a component channelEdit.vue in the home class
<div> </template> <script> export default {name: 'ChannelEdit',} </script>Copy the code
2.2 Introduce components in home.vue to establish parent-child relationship
+ import ChannelEdit from './channelEdit'
components: {
ArticleList,
MoreAction,
+ ChannelEdit
}
Copy the code
<! <ChannelEdit></ChannelEdit> </van-action-sheet>Copy the code
2.3 Test again whether the display content of shell function is: ‘The content of channel management will be placed here’
3 channel management – Component layout
3.1 home/channelEdit.vue
As follows:
<template> <div class="channel-edit"> <! <div class="channel"> <van-cell title=" my channel" :border="false"> <van-button size="mini" Type ="info"> Edit </van-button> </van-cell> <van-grid> <van-grid-item v-for="index in 8" :key="index"> < span > channel {{index}} < / span > < van - icon name = "cross" class = "BTN" > < / van - icon > < / van - the grid - item > < / van - grid > < / div > <! <div class="channel"> <van-cell title=" optional channel" :border="false"></van-cell> <van-grid> <van-grid-item V - for = "index in 8" : the key = "index" > < span > channel {{index}} < / span > < / van - the grid - item > < / van - grid > < / div > < / div > < / template > <script> export default { name: 'ChannelEdit', data () { return { } } } </script> <style lang="less" scoped> .channel{ padding:15px; font-size:14px; } .btn { position: absolute; top: 0; right: 0; font-size: 24px; } </style>Copy the code
3.2 View the layout structure again
3.3 Import my channel information into the structure
Since my channel information was obtained before, we just need to import it from parent to child in home.vue
<! -- https://vant-contrib.gitee.io/vant/#/zh-CN/action-sheet --> <van-action-sheet v-model="showChannelEdit" title=" channel management "> <! -- 1. Father passes son. <channel-edit + :channels="channels"> </channel-edit> </van-action-sheet>Copy the code
In channelEdit. Vue
props: ['channels']
Copy the code
<! <div class="channel"> <van-cell title=" my channel" :border="false"> <van-button size="mini" Type ="info"> Edit </van-button> </van-cell> <van-grid> <van-grid-item v-for="channel in channels" :key="channel. Id "> <span>{{channel.name}}</span> <van-icon name="cross" class="btn"></van-icon> </van-grid-item> </van-grid> </div>Copy the code
3.3 View my channel rendering effect
3.4 Render of optional channels
3.4.1 track analysis
Content of optional channels: All channels retrieved – the channels selected by the user
To dynamically detect content changes => Recalculation is required when users are added or deleted
3.4.2 To obtain all channel contents, a new interface needs to be called
Continue to encapsulate it inapi/channel.js
Add an interface to the
/ / export const getAllChannels = () => {return request({method: 'GET', url: 'v1_0/channels'})}Copy the code
3.4.3 Load the call in the child component channelEdit.vue
All obtained channel contents are stored in allChannels array for convenient subtraction later
<script>
import { getAllChannels } from '@/api/channel.js'
export default {
name: 'ChannelEdit',
props: ['channels'],
data () {
return {
allChannels: []
}
},
created () {
this.loadAllChannels()
},
methods: {
async loadAllChannels () {
const res = await getAllChannels()
this.allChannels = res.data.data.channels
}
}
}
</script>
Copy the code
3.4.4 Write code in computed property computed
// Generate new data based on existing data ---- Computed properties computed: { recommendChannels () { const arr = this.allChannels.filter(channel => { const idx = this.channels.findIndex(item => item.id === channel.id) if (idx === -1) { return true } }) return arr // return this.allChannels - this.channels } }Copy the code
It can also be reduced to a single line of code:
return this.allChannels.filter((item) => ! this.channels.some(index => index.id === item.id))Copy the code
3.4.5 Render subtracted data to the page
<! <div class="channel"> <van-cell title=" optional channel" :border="false"></van-cell> <van-grid> <van-grid-item v-for="channel in recommendChannels" :key="channel.id"> <span>{{channel.name}}</span> </van-grid-item> </van-grid> </div>Copy the code
3.4.6 Checking whether the Function is implemented
We found that there was still duplicate content. When we opened the vue debugging tool, we found that the ID value in my channel was in string format and we used congruence when judging, which was the key cause of the problem. There are two solutions
-
Change === to == (here because MY Eslint doesn’t allow us to use ==)
-
Change the route location to Number(item.id) and convert
Double check (already ok)
4 Realize the channel jump by clicking
4.1 Realize click channel hopping
Add a custom event listener for change-channel to the parent component home.vue
<! -- https://vant-contrib.gitee.io/vant/#/zh-CN/action-sheet --> <van-action-sheet v-model="showChannelEdit" title=" channel management "> <! -- 1. Father passes son. <channel-edit :channels="channels" + @change-channel="hChangeChannel" ></channel-edit> </van-action-sheet>Copy the code
Add a callback
HChangeChannel (curIdx) {console.log(' Parent component received my channel clicked in child component ', curIdx) // 1. This. active = curIdx // 2. Turn off this. IsShowChannelEdit = false},Copy the code
4.2 Sub-component channelEdit component
<! <div class="channel"> <van-cell title=" my channel" :border="false"> <van-button size="mini" Type ="info"> edit </van-button> </van-cell> <van-grid> <van-grid-item + v-for="(channel, idx) in channels" :key="channel.id" + @click="hClickMyChannel(idx)" > <span>{{channel.name}}</span> <! -- <van-icon name="cross" class="btn" ></van-icon> --> </van-grid-item> </van-grid> </div>Copy the code
HClickMyChannel (idx) {this.$emit('change-channel', idx)};Copy the code
4.3 Highlight the current channel after entering the channel
<channel-edit
+ :curIndex="active"
@change-channel="hChangeChannel"
:channels="channels"
></channel-edit>
</van-action-sheet>
Copy the code
In the child component:
Props: ['channels', // current channels + 'curIndex' // index of the currently selected channel],Copy the code
<van-grid-item v-for="(channel,idx) in channels" ...... + :class="{red:idx===curIndex}" > <span>{{channel.name}}</span> <! -- <van-icon name="cross" class="btn"></van-icon> --> </van-grid-item> </van-grid>Copy the code
Add style to class name
<van-cell title=" mY channel ":border="false"> + <van-button class="bg" size="mini" type="info"> Edit </van-button> </van-cell> // Highlight. Red {color: red; font-weight: bold; } .bg { background-color: #fff; color: red; border-color: red; }Copy the code
View the effect:
5 Add my channel
5.1 Click optional Channels to add to my channel
insrc/api/channels.js
Add method to
Return request({url: '/v1_0/user/channels', // method: 'PATCH', data: { channels } }) }Copy the code
5.2 Register click events for channels in recommended channels
<! <div class="channel"> <van-cell title=" optional channel" :border="false" ></van-cell> <van-grid> <van-grid-item v-for="channel in recommendChannels" :key="channel.id" + @click="hAddChannel(channel)" > <span>{{channel.name}}</span> </van-grid-item> </van-grid> </div>Copy the code
5.3 Complete core functions
Async hAddChannel (channel) {try {// 1. Const res = await addChannels([channel]) // 2. Console. log(res)} catch (err) {console.log(err) this.$toast.fail(' failed to add channel ')}},Copy the code
5.4 Add My Channels – Complete the update on the view
Add the code in the previous update view
this.channels.push(channel)
Copy the code
Channel 6 management – Delete my channel
Requirements: users click “edit”, in my channel, display X, and then click X, you can delete the designated channel.
6.1 Add isEditing data item to realize view interaction
Add to the child component
Data () {return {+ editing: false, // allChannels: [] // allChannels}}Copy the code
Modify the view
<div class="channel"> <van-cell title=" my channel" :border="false" > <van-button size="mini" class="editBtn" + @click="isEditing=! isEditing" + >{{isEditing ? "Cancel", "edit"}} < / van - button > < / van - cell > < van - grid > <! If the current index is the same as the curIndex passed in, add a new class: red --> <! -- :class="{class name: bool}" --> <van-grid-item v-for="(channel, idx) in channels" :key="channel.id" :class="{red: idx===curIndex}" @click="hClickMyChannel(idx)" > <span>{{channel.name}}</span> + <! -- Only if: editing is true and not recommended, show X --> <van-icon + v-show=" editing &&idx! ==0" name="cross" class="btn" ></van-icon> </van-grid-item> </van-grid> </div>Copy the code
6.2 Implement delete my channel
Add an interface to SRC \ API \channel.js:
@param {*} channelId Id of the channel to be deleted * @returns */ export const delChannel = (channelId) => {return request({} url: '/v1_0/user/channels/' + channelId, method: 'DELETE' }) }Copy the code
6.3 Adding Event processing
Import {getAllChannels, addChannel, delChannel} from '@/ API /channel.js' Normal condition: after clicking, do channel jump // 2. And when I did, HClickMyChannel (idx) {if (this.editing) {this.dodeletechannel (idx)} else { this.$emit('change-channel', idx) } }, async doDeleteChannel (idx) { // 1. Const channelId = this.channels[idx].channel Do delete try {await delChannel(channelId) // my channel less 1 item, This.channels.splice (idx, 1) this.$toasters. Success (' delete successful ')} Catch (err) {console.log(err)}},Copy the code
6.4 fix the BUG
6.4.1
inchannelEdit.vue
In the
async doDeleteChannel (idx) { // 1. Const id = this.channels[idx].id console.log(' You want to delete channel ID is ', id) // 2. Try {const res = await delChannel(id) console.log(res) this.$toast.success(' Delete channel succeeded ') // If you delete channel before current channel, Active + if (idx < this.curindex) {+ this.$emit('fixed-active-index') +} // 3. This.channels.splice (idx, 1)} Catch (err) {console.log(err) this.$toasters. Fail (' Delete channel failed ')}},Copy the code
In the home. In vue
<channel-edit
:curIndex="active"
@change-channel="hChangeChannel"
+ @fixed-active-index="hFixedActiveIndex"
:channels="channels"
></channel-edit>
Copy the code
supplement
Active -1 hFixedActiveIndex () {this.active--},Copy the code
6.4.2 Edit channel closed open or edit state
inhome.vue
Add the following code to:
<! + <div class="bar-btn" @click="openChannelList"> <van-icon name="wap-nav" /> </div> <! <van-action-sheet v-model="isShowChannelEdit" title=" title "> <! - note: Because the component's outer layer contains a van-action-sheet that is not created after the page is opened or refreshed, <channelEdit :channels="channels" + ref="channelEdit" @change-channel="hchangeChannel" :curIdx="active" @update-active="hUpdateActive" ></channelEdit> </van-action-sheet>Copy the code
Supplement methods to methods:
openChannelList () {
this.isShowChannelEdit = true
if (this.$refs.channelEdit) { this.$refs.channelEdit.isEditing = false }
},
Copy the code
6.4.3 Deleting the recommended problems by editing the status
inchannelEdit.vue
Add the following code to the
Async doDeleteChannel (index) {const id = this.channels[index].id try {await delChannels(id)} catch (err) If (index < this.curIdx) {this.$emit('update-active')} + if (index ! == 0) {+ // Delete the current item from channels $channels. Splice (index, 1) + this.channels.splice(index, 1) + this.$toast.success(' delete successful ')}},Copy the code