文章目錄
一、圖書列表頁面開發 + 列表 API 對接
新建src\pages\list\list.vue:
<template>
<div>
123
</div>
</template>
<script>
export default {
components: {},
data() {
return {
}
},
mounted() {
},
methods: {
}
}
</script>
<style lang="scss" scoped>
</style>
新建src\pages\list\main.js:
import Vue from 'vue'
import App from './list'
const app = new Vue(App)
app.$mount()
修改src\components\search\SearchList.vue的showList方法來跳轉到圖書列表頁:
showList(text, key) {
console.log(text, key)
this.$router.push({
path: '/pages/list/main',
query: {
text, key, title: text
}
})
},
在src\api\index.js中新建一個接口函數searchList,用來獲取圖書列表:
export function searchList(params) {
return get(`${API_URL}/book/shelf/search-list`, params)
}
修改src\pages\list\list.vue:
<template>
<div>
<SearchTable :data="data"/>
</div>
</template>
<script>
import SearchTable from '../../components/search/SearchTable'
import {searchList} from '../../api'
export default {
components: {SearchTable},
data() {
return {
data: []
}
},
mounted() {
this.getSearchList()
},
methods: {
getSearchList() {
const { key, text } = this.$route.query
const params = {}
if (key && text) {
params[key] = text
}
searchList(params).then(res => {
this.data = res.data.data
})
}
}
}
</script>
<style lang="scss" scoped>
</style>
預覽:
搜索頁點擊(出版社/作者/分類)標籤觸發
二、圖書列表標題動態切換+圖書詳情頁跳轉
在src\api\wechat.js中新建一個接口函數setNavigationBarTitle,用來動態設置標題:
export function setNavigationBarTitle(title) {
mpvue.setNavigationBarTitle({ title })
}
接下來在mounted中調用setNavigationBarTitle:
mounted() {
this.getSearchList()
const { title } = this.$route.query
setNavigationBarTitle(title)
},
由於SearchTable點擊是一定會跳轉到圖書詳情頁的,因此將跳轉直接加到SearchTable中,其他事件內容依舊通過$emit交給調用者處理:
src\components\search\SearchTable.vue
onClick(book) {
this.$router.push({
path: '/pages/detail/main',
query: {
fileName: book.fileName
}
})
this.$emit('onClick', book)
}
刪掉src\components\search\SearchList.vue中關於onBookClick的內容和調用
預覽:
三、圖書列表觸底自動刷新功能開發
data中新增page: 1
修改getSearchList方法:
getSearchList() {
const { key, text } = this.$route.query
const params = {}
if (key && text) {
params[key] = text
}
params.page = this.page
searchList(params).then(res => {
const { data } = res.data
if (data.length > 0) {
this.data.push(...data)
} else {
showToast('沒有更多數據了')
}
})
}
新增周期函數:
onReachBottom() {
this.page++
this.getSearchList()
},
在mounted中新增一句:this.page = 1
防止打開新list頁面時舊list頁面未銷燬時導致的page未初始化問題
這樣就實現了觸底刷新
四、分類列表頁面開發 + 分類 API 對接
新建src\pages\categoryList\main.json:
{
"navigationBarTitleText": "分類列表"
}
新建src\pages\categoryList\main.js:
import Vue from 'vue'
import App from './categoryList'
const app = new Vue(App)
app.$mount()
新建src\pages\categoryList\categoryList.vue:
<template>
<div>
</div>
</template>
<script>
export default {
}
</script>
<style lang="scss" scoped>
</style>
在首頁中新加跳轉到categoryList頁面,即爲onCategoryMoreClick完善內容:
onCategoryMoreClick() {
this.$router.push({
path: '/pages/categoryList/main'
})
},
在src\api\index.js中新建一個接口函數categoryList,用來拿到所有分類列表:
export function categoryList() {
return get(`${API_URL}/book/category/list/v2`)
}
完成分類列表頁面src\pages\categoryList\categoryList.vue:
<template>
<div>
<HomeBook
title="圖書分類"
:row="category.length / 2"
:col="2"
:data="category"
mode="category"
:show-btn="false"
:show-title="false"
/>
</div>
</template>
<script>
import HomeBook from '../../components/home/HomeBook'
import {categoryList} from '../../api'
export default {
components: { HomeBook },
data() {
return {
category: []
}
},
mounted() {
categoryList().then(res => {
this.category = res.data.data
})
}
}
</script>
<style lang="scss" scoped>
</style>
預覽
五、分類列表跳轉圖書列表功能開發
修改src\pages\index\index.vue中圖書分類HomeBook的事件監聽屬性onBookClick爲:@onBookClick="onCategoryClick"
新增onCategoryClick方法:
onCategoryClick(category) {
this.$router.push({
path: '/pages/list/main',
query: {
key: 'categoryId',
text: category.category,
title: category.categoryText
}
})
}
同樣也爲src\pages\categoryList\categoryList.vue中的HomeBook新增@onBookClick="onCategoryClick"
:
onCategoryClick(category) {
this.$router.push({
path: '/pages/list/main',
query: {
key: 'categoryId',
text: category.category,
title: category.categoryText
}
})
}
六、閱讀器頁面開發
1.學習重點
- webview 組件的使用(查看官方文檔)
- 閱讀器模塊的集成方法
2.閱讀器組件
組件名稱 | 屬性 | 參數 | 用途 | 默認值 |
---|---|---|---|---|
read | data | fileName | 圖書的唯一標識 | - |
opf | 圖書opf文件地址 | - | ||
navigation | 圖書目錄地址 | - |
3.動手操作
新建src\pages\read\main.json:
{
"navigationBarTitleText": "閱讀器"
}
新建src\pages\read\main.js:
import Vue from 'vue'
import App from './read'
const app = new Vue(App)
app.$mount()
新建src\pages\read\read.vue:
<template>
<web-view :src="url"></web-view>
</template>
<script>
export default {
data() {
return {
url: ''
}
},
mounted() {
const { query } = this.$route
let _url = 'https://www.youbaobao.xyz/book/#/ebook'
if (query.fileName) {
_url = `${_url}/${query.fileName}`
if (query.opf) {
_url = `${_url}?opf=${query.opf}`
}
if (query.navigation && query.opf) {
_url = `${_url}&navigation=${query.navigation}`
} else if (query.navigation) {
_url = `${_url}?navigation=${query.navigation}`
}
this.url = _url
}
}
}
</script>
<style lang="scss" scoped>
</style>
完善src\pages\detail\detail.vue頁面的readBook方法:
readBook(href) {
const query = {
fileName: this.book.fileName,
opf: this.book.opf
}
if (href) {
// 找到標記位置
const index = href.toString().indexOf('/')
if (index >= 0) {
// 標記存在則做截斷(從標記的下一個位置開始讀取)
query.navigation = href.slice(index + 1)
} else {
query.navigation = href
}
}
if (this.book && this.book.fileName) {
this.$router.push({
path: '/pages/read/main',
query
})
}
},
預覽:
這樣就可以閱讀圖書了
七、書架頁面開發
1.學習重點
- API對接:
- 加入時間API
- 書架列表API
2.書架視覺稿
http://www.youbaobao.xyz/mpvue-design/preview/#artboard6
3.用戶信息面板
組件名稱 | 屬性 | 參數 | 用途 | 默認值 |
---|---|---|---|---|
ShelfUserInfo | props | num | 書架圖書數量 | 0 |
readDay | 加入天數 | 0 | ||
userInfo | 用戶信息 | {} |
4.書架列表組件
組件名稱 | 屬性 | 參數 | 用途 | 默認值 |
---|---|---|---|---|
ShelfList | props | shelfList | 書架列表 | [] |
methods | gotoHome | 訪問首頁 | - | |
gotoBookDetail | 訪問圖書詳情 | - |
5.動手操作
新建src\pages\shelf\main.json:
{
"navigationBarTitleText": "書架"
}
新建src\pages\shelf\main.js:
import Vue from 'vue'
import App from './shelf'
const app = new Vue(App)
app.$mount()
新建src\pages\shelf\shelf.vue:
<template>
<div></div>
</template>
<script>
export default {
data() {
return {
}
},
mounted() {
}
}
}
</script>
<style lang="scss" scoped>
</style>
修改src\components\home\HomeCard.vue的gotoShelf方法爲:
gotoShelf() {
this.$router.push('/pages/shelf/main')
},
八、書架用戶面板組件開發
新建組件:src\components\shelf\ShelfUserInfo.vue:
<template>
<div class="user-info-wrapper">
<div class="user-info">
<div class="user-nick-name">{{userInfo.nickName}}</div>
<div class="user-read-time">您已經加入小慕讀書{{readDay}}天</div>
<div class="user-avatar-wrapper">
<img class="user-avatar" :src="userInfo.avatarUrl" mode="widthFix">
</div>
</div>
<div class="user-extra">
<div class="user-extra-text">您的書架中共有 {{num}} 本好書</div>
</div>
</div>
</template>
<script>
export default {
props: {
num: Number,
readDay: Number,
userInfo: Object
}
}
</script>
<style lang="scss" scoped>
.user-info-wrapper {
margin: 15px 25px;
background: #F8F9FB;
border-radius: 12px;
padding: 15px 20px;
border: 1px solid #E0E1E2;
.user-info {
position: relative;
height: 60px;
border-bottom: 1px solid #E9E9E9;
.user-nick-name {
font-size: 17px;
font-weight: 500;
color: #333;
}
.user-read-time {
font-size: 12px;
color: #868686;
}
.user-avatar-wrapper {
position: absolute;
right: 0;
top: 0;
.user-avatar {
width: 40px;
border-radius: 50%;
}
}
}
.user-extra {
margin-top: 15px;
.user-extra-text {
font-size: 12px;
color: #666;
font-weight: 500;
}
}
}
</style>
在src\api\index.js中新增接口調用,用來獲取用戶註冊天數:
export function userDay(params) {
return get(`${API_URL}/user/day`, params)
}
修改src\pages\shelf\shelf.vue爲:
<template>
<div>
<ShelfUserInfo
:user-info="userInfo"
:read-day="readDay"
:num="shelfList.length"
/>
</div>
</template>
<script>
import ShelfUserInfo from '../../components/shelf/ShelfUserInfo'
import {getStorageSync} from '../../api/wechat'
import {bookShelf, userDay} from '../../api'
export default {
components: {ShelfUserInfo},
data() {
return {
userInfo: {},
readDay: 0,
shelfList: []
}
},
mounted() {
this.userInfo = getStorageSync('userInfo')
const openId = getStorageSync('openId')
userDay({ openId }).then(res => {
this.readDay = res.data.data.day
})
bookShelf({ openId }).then(res => {
this.shelfList = res.data.data
})
}
}
</script>
<style lang="scss" scoped>
</style>
這裏已經修改bookIsInShelf接口名稱爲bookShelf
預覽:
九、書架列表組件開發
新建src\components\shelf\ ShelfList.vue:
<template>
<div class="shelf-list-wrapper">
<div class="shelf-list-inner">
<div
class="shelf-book"
v-for="book in shelfList"
:key="book.fileName"
>
<div
class="shelf-book-cover"
v-if="book && book.cover"
@click="() => gotoBookDetail(book)"
>
<ImageView :src="book.cover"></ImageView>
</div>
<div class="shelf-book-title" v-if="book && book.title">{{book.title}}</div>
<div class="shelf-book-add" v-if="!book.title" @click="gotoHome">
<div class="shelf-book-add-wrapper">
<div class="shelf-book-add-x"></div>
<div class="shelf-book-add-y"></div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import ImageView from '../base/ImageView'
export default {
components: { ImageView },
props: {
shelfList: Array
},
methods: {
gotoHome() {
this.$router.push('/pages/index/main')
},
gotoBookDetail(book) {
this.$router.push({ path: '/pages/detail/main', query: { fileName: book.fileName } })
}
}
}
</script>
<style lang="scss" scoped>
.shelf-list-wrapper {
padding: 0 12.5px 20px 12.5px;
.shelf-list-inner {
display: flex;
flex-flow: row wrap;
.shelf-book {
flex: 0 0 33.33%;
width: 33.33%;
padding: 20px 12.5px 0 12.5px;
box-sizing: border-box;
.shelf-book-cover {
width: 100%;
height: 130px;
}
.shelf-book-title {
width: 100%;
font-size: 12px;
color: #333;
overflow: hidden;
text-overflow: clip;
line-height: 14px;
max-height: 28px;
margin-top: 10px;
}
.shelf-book-add {
width: 100%;
height: 130px;
border: 1px solid #CBCBCB;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
.shelf-book-add-wrapper {
position: relative;
width: 30px;
height: 30px;
.shelf-book-add-x {
position: absolute;
top: 50%;
width: 30px;
height: 2px;
margin-top: -1px;
background: #CACACA;
}
.shelf-book-add-y {
position: absolute;
left: 50%;
width: 2px;
height: 30px;
background: #CACACA;
}
}
}
}
}
}
</style>
直接在src\pages\shelf\shelf.vue中調用組件:
<ShelfList :shelfList="shelfList" />
修改mounted爲onShow並給shelfList push一個空對象:
onShow() {
this.userInfo = getStorageSync('userInfo')
const openId = getStorageSync('openId')
userDay({ openId }).then(res => {
this.readDay = res.data.data.day
})
bookShelf({ openId }).then(res => {
this.shelfList = res.data.data
this.shelfList.push({})
})
}
預覽:
mounted在頁面加載時只調用一次,而onShow是小程序頁面的生命週期函數,在每次頁面獲得焦點時都會調用,包括首次加載和再次返回
此處有大坑: