目录前言 一、watch是什么 二、watch不同的实际使用场景开发案例1.场景1:加载完成后登录监听 2.场景2:前面不同的选择框,影响下面的不同的选择框的选项内容3.场景3:深度监听 4.场景4:
顺晟科技
2022-09-13 11:10:47
371
观察成品可知,在地址栏会出现书名、分类的信息,而且可以在地址栏更改信息得到不同的书,这就利用了动态路由的技术。
{
path: \'/ebook\',
component: () => import(\'../views/ebook/index.vue\'),
children: [
{
//这里的冒号代表后面是参数,在EbookReader组件内部可以通过 $route.params.fileName来访问到
path: \':fileName\',
component: () => import(\'../components/ebook/EbookReader\')
}
]
}
简单功能实现完毕之后,来写:在地址栏输入 地址+分类+|+书名可以访问到电子书,其实也就是在刚刚基础上将EbookReader组件里的打印改为字符串拼接;
字符串输入样例:http://localhost:8080/#/ebook/History|2013_Book_FungalDiseaseInBritainAndTheUn
mounted () {
const fileName = this.$route.params.fileName.split(\'|\').join(\'/\')
const baseUrl = \'192.168.1.112:8082/epub/\'
console.log(`${baseUrl}${fileName}.epub`)
}
this.book = new Epub(url)
创建新book对象
获取rendition对象,主要用于电子书的渲染
this.rendition = this.book.renderTo(\'read\', {
width: window.innerWidth,
height: window.innerHeight
//这里课程里老师说要加,但是加上之后发现渲染出来的元素宽度为0,去掉就好了也不知道为什么
// method: \'default\'
})
this.rendition.display()
展示出电子书来
this.rendition.on(\'事件名\', \'事件处理函数\')
用来给book对象绑定事件this.rendition.on(\'touchstart\', event => {
this.touchStartX = event.changedTouches[0].clientX
this.touchStartTime = event.timeStamp
})
this.rendition.on(\'touchend\', event => {
const offsetX = event.changedTouches[0].clientX - this.touchStartX
const time = event.timeStamp - this.touchStartTime
if (time < 500 && offsetX < -40) {
this.nextPage()
} else if (time < 500 && offsetX > 40) {
this.prePage()
} else {
this.toggleTitleAndMenu()
}
event.passive = false
event.stopPropagation() //阻止事件传播
})
event.passive = false
,而不是老师的event.preventDefault()
是因为,滑动的时候会报错,设置passive为false也可以阻止默认行为import { mapGetters, mapActions } from \'vuex\'
export const ebookMixin = {
computed: {
...mapGetters([
\'menuVisible\',
\'fileName\'
])
}
}
import { ebookMixin } from \'../../utils/mixin\'
,原理和使用mapGetters一样差不多mixins: [ebookMixin]
this.$store.dispatch(\'方法名\',\'参数\')
,现在可以变为 this.方法名(\'参数\')
import { mapActions } from \'vuex\'
,但这是方法,所以...mapActions([\'\'])
要写在methods里哦(同样这一段也可以写在mixin里方便管理)字体的菜单栏部分会多出上面那一截,主要的实现思路是:
字体进度条左边是 最小的字体,右边是最大的字体
将菜单栏横着主要分成七个部分(这个数量是由总共有多少可以字号设置来决定的),每个部分分为左右两个部分 显示一个边框(视觉上就是一条直线)
几个部分由中间的小点隔开,其实每个小点的地方都是一个大点,但只有当选中某一个部分(字体)时,那个地方的大点才会显示出来表示选中
将fontSizeList这种静态数据都放在统一的文件下管理,这里放在utils文件夹下的book.js中
import { FONT_SIZE_LIST } from \'../../utils/book\'
引入进来export const FONT_SIZE_LIST = [
{ fontSize: 12 },
{ fontSize: 14 },
{ fontSize: 16 },
{ fontSize: 18 },
{ fontSize: 20 },
{ fontSize: 22 },
{ fontSize: 24 }
]
弹窗分为上下两个部分,上面是标题(后面支持中英切换),下面是字体列表
先对大致布局进行设置,再写css,就不再多说,但是都用弹性布局(非常好!!!)
下面的字体列表用v-for循环显示完之后,选中的那个要单独变颜色,用:class="{\'selected\': isSelected(item)}"
来控制加不加上那个selected的类
this.currentBook.rendition.themes.font(font)
,但这一步之后字体并没有发生变化// content代表iframe里的dom已经加载完毕可以访问
// contents是管理资源文件
// addStylesheet是手动添加style样式的函数
this.rendition.hooks.content.register(contents => {
Promise.all(
[contents.addStylesheet(\'http://10.69.198.212:8082/fonts/daysOne.css\'),
contents.addStylesheet(\'http://10.69.198.212:8082/fonts/cabin.css\'),
contents.addStylesheet(\'http://10.69.198.212:8082/fonts/montserrat.css\'),
contents.addStylesheet(\'http://10.69.198.212:8082/fonts/tangerine.css\').then(() => {})
])
})
http://10.69.198.212:8082
这个网址很可能在生产环境和开发环境是不一样的,所以在这里不能直接写死网址,而是要添加环境变量
环境变量
在项目根目录下添加文件 .env.development,在里面写上要替换的网址 只有以 VUE_APP_
开头的变量会被 webpack.DefinePlugin
静态嵌入到客户端侧的包中
// .env.development
VUE_APP_RES_URL=http://10.69.198.212:8082
// 替换之后
contents.addStylesheet(`${process.env.VUE_APP_RES_URL}/fonts/cabin.css`),
cookie localStorage sessionStorage三者异同
先安装 cnpm i --save web-storage-cache
在utils文件夹下创建localStorage.js文件用来封装localStorage的操作
// 基本操作
import Storage from \'web-storage-cache\'
const localStorage = new Storage()
export function setLocalStorage (key, value) {
return localStorage.set(key, value)
}
export function getLocalStorage (key) {
return localStorage.get(key)
}
export function removeLocalStorage (key) {
return localStorage.delete(key)
}
export function clearLocalStorage () {
localStorage.clear()
}
// 具体操作代码
export function setBookObject (fileName, key, value) {
let book = getLocalStorage(`${fileName}-info`)
if (!book) {
book = {}
}
book[key] = value
setLocalStorage(`${fileName}-info`, book)
}
export function getBookObject (fileName, key) {
const book = getLocalStorage(`${fileName}-info`)
if (book) {
return book[key]
} else {
return null
}
}
export function getFontFamily (fileName) {
return getBookObject(fileName, \'fontFamily\')
}
export function saveFontFamily (fileName, font) {
setBookObject(fileName, \'fontFamily\', font)
}
this.rendition.display().then(() => {
const font = getFontFamily(this.fileName)
if (font) {
this.currentBook.rendition.themes.font(font)
this.setDefaultFontFamily(font)
} else {
saveFontFamily(this.fileName, \'Default\')
}
})
cnpm i --save vue-i18n
这里主题依旧是静态资源文件, 所以在utils下的book.js中仍然要加上theme相关信息
主题的名字也用到了国际化语言, 所以book.js中也要使用插件vuei18n, 这里就有问题了
i18n is undefied
, 明明i18n已经在main.js的根组件中注册好了, 为什么还是使用不了?import i18n from \'../lang\'
设置主题要先在eBook对象中注册主题 分别需要名字以及对应的样式, 这里由于在EBook Reader组件以及EbookThemeSetting组件中都用到了themeList, 所以也将theme List的那个混入过程加入到mixin中, 这样只要引用了mixin就都能取到themeList
其余就和字体 字号一样, initTheme里判断默认主题什么什么的, 还有localStorage的存储~
小bug, 发现每个主题只能切换一次就不能再换回来了, 所以这里把epubjs的版本换成0.3.71 就行了
export function addClass (url) {
const link = document.createElement(\'link\')
link.setAttribute(\'rel\', \'stylesheet\')
link.setAttribute(\'href\', url)
link.setAttribute(\'type\', \'text/css\')
document.querySelector(\'head\').appendChild(link)
}
这里的link标签需要url,我们将主题文件放到nginx服务器下, (注意这里的地址还是要使用环境变量, ~包括之前的book的地址也要). 每次切换主题的时候就调用addClass这个函数
每次选择切换一次主题, 不仅电子书的主题要切换 全局主题也要切换, 写另外一个函数来根据不同的电子书主题同步切换到全局主题
// 这个函数在EbookSettingTheme和EbookReader中都要用到,所以写在mixin中供全局调用
initGlobalStyle () {
switch (this.defaultTheme) {
case \'Default\': addClass(`${process.env.VUE_APP_RES_URL}/theme/theme_default.css`)
break
case \'Gold\': addClass(`${process.env.VUE_APP_RES_URL}/theme/theme_gold.css`)
break
case \'Eye\': addClass(`${process.env.VUE_APP_RES_URL}/theme/theme_eye.css`)
break
case \'Night\': addClass(`${process.env.VUE_APP_RES_URL}/theme/theme_night.css`)
break
default: addClass(`${process.env.VUE_APP_RES_URL}/theme/theme_default.css`)
}
}
09
2022-11
23
2022-09
23
2022-09
23
2022-09
13
2022-09
13
2022-09