Vue中如何创建新的跳转界面
由于自己在线教育网站距离上线的日子越来越近了,之前专注研究的都是有关如何用k8s
部署相关的东西,没有太关注一些页面的东西。临近上线前,要把一些功能完善出来,于是乎就有了今天这篇文章。
由于解决的问题是在vue
中进行页面跳转,最终会在跳转到的界面里达到能够支持播放视频的目的,由于已经很久没碰前端相关的东西,上次搞前端相关的还是刚进小米的时候,做小米零售通后台门店相关的省总、副省总、小区总之类的后台管理界面。维护当时的小米米粉社区后台界面也用到vue
相关的东西,但是大概都是二年前了,感觉都要忘光了,今天索性算是也捡捡旧知识。这篇文章会分成三部分,第一部分,总结一些可能在做前端界面时候我掌握的一些知识,由于不是专业前端开发,所以我的观点可能更加实用主义。第二部分,结合我本次的需求,将整个实现过程实录下来,如果有类似需求,也做抛砖引玉。第三部分对于本文重点做下总结,方便对于自己知识库的添砖加瓦有个直观认识。
下面文章开始。
第一部分:我做前端界面时候一些知识分享
其实对于vue
框架要灵活使用,要扭转一个因长期使用jQuery
导致的思维定势。我最开始接触javascript
相关内容,都是在一步步接触开源框架过程中得到的机会。最开始接很多外包,自己对html和css
知识知之甚少,所以,当时也真就是全凭一张嘴,跟着客户砍大山,能把外包单子接下来,自己转头就是一个“接包转包”得心应手的操作,但是距离毕业时间越来越近,同时有些单子可能谈到手的价格都不高,有时也想锻炼一下自己的能力,所以,尝试着自己来处理一些html和css
相关的问题。最开始接触的是修改discuz、wordpress、zblog、phpwind
等一些开源论坛或者博客程序,如果仔细观察这些,你可能也清晰知道,这些都属于php
系。我现在有些网站仍然用着wordpress
,我很感谢php
这门语言,虽然现在随着互联网时代的发展,它已经没有当初我接触时候的15、16
年火爆,但是作为一个非科班(本人医学专业)出身转行互联网的野路子程序员来说,很感谢这门语言给我窥探互联网门径的机会,也因为它的不断使用,夯实了我的后端开发相关技术栈的知识,使我学起其他语言更加得心应手。
而在改界面相关东西的时候,不可回避就要调整相关的js
。我对于vue
的理念最开始接触是在迈外迪,当时的后台是重度使用了avalon
这个框架的,而关于事件模型绑定
的最初印象就是这个框架带给我的。你在监听事件再随后做处理的时候,自然而然的思维就是要操作什么就定位什么,然后再把拿到的数据与后端api
做rwkt。但是vue
让你开始不太习惯的就是,你api
拿到数据之后,直接就支持把相关item
渲染到界面上,同时,如果有针对表单的监听,你在相应vue的html文件xx.vue
中声明对该表单的监听行为,如click
,如change
,再声明好监听的函数,在界面的export default{...}
中的methods
就可以放置相应的回调函数,实现相应交互行为。针对于后端封装好的接口调用,vue
通常的使用方式,就是把接口调用的js
作为一个module
封包出来,你使用时候,引入进来就好了。同时,由于后端返回的数据可能解包后要再处理,才能满足页面上的使用要求,通常作法都是把引入的后端封包js module
再在调用界面封装一遍,并把值赋到export default{}
声明中的props
部分,或者是data
部分,这样页面loaded
完毕以后,这些变量值在页面中就是可用态,你想怎么玩就怎么玩就可以了。至于computed
、created
、mounted
、propagate
都是事件传播过程中,实现控制的手段。比如:
created
:在模板渲染完成之前调用,即初始化某些值,然后再渲染成视图mounted
:在模板渲染成html之后调用,通常在页面初始化完毕以后,再对html中相应dom节点进行需要的操作。比如表单选项变化时,要向后端接口请求查重,看该选项能否选择。template
通常成对出现,用于页面解构成不同部分组成时,每部分有自己的样式,又要汇总在一个界面里展示,这个时候需要用到template
- 有些建立在
layouts
下相应业务目录下的xx.vue
文件,可以作为component
被很多界面引入使用 - 如果你不想新建文件用于创建
component
,你可以用let
声明的方式,之后把它声明到应用界面的components
部分,这样,let
指定的变量名称就直接可以在界面中当component
用成对标签形式使用了。 beforeCreate
:创建之前,已经完成了初始化事件和生命周期beforeMouted
:已经完成了模板渲染beforeDestory
:摧毁之前,整个vue
处在实时监控浸染和更新destroyed
:已经摧毁,已经摧毁了观察者,子元素和事件监听props
声明的意义?-
- prop作为初始值传入后,子组件想把它当作局部数据来用
-
- prop作为初始值传入后,由子组件处理成其他数据输出
-
- 第一种方式
//局部组件登录模板声明
let login ={ //具体局部组件名称
template:'<div><h2>用户登录</h2></div>'
};
const app = new Vue({
el: "#app",
data: {},
methods: {},
components:{ //用来注册局部组件
login:login //注册局部组件
}
});
//局部组件使用 在Vue实例范围内
<login></login>
- 第二种方式,同样实现此功能,用符号来指定模板的名称,其它就跟上面方法一样了
//1.声明局部组件模板 template 标签 注意:在Vue实例作用范围外声明
<template id="loginTemplate">
<h1>用户登录</h1>
</template>
//2.定义变量用来保存模板配置对象
let login ={ //具体局部组件名称
template:'#loginTemplate' //使用自定义template标签选择器即可
};
//3.注册组件
const app = new Vue({
el: "#app",
data: {},
methods: {},
components:{ //用来注册局部组件
login:login //注册局部组件,也可以直接使用login,
}
});
//4.局部组件使用 在Vue实例范围内
<login></login>
- 无论是
scss、less、stylus
都可以用于界面效果的定制,起 到传统上css
的作用,但是想要vue
支持相应的语法,都需要安装package
并做相应的配置才能使其生效。我实际用过比较多的是scss和stylus
,前者是在之前golang
做后端开发游戏后台时后台管理系统中界面部分使用到的,后者是我最近在开发自己的在线教育网站过程中使用到的。我截取两段code
,大家感受下
//这是使用scss
<style scoped lang="scss">
.button-box {
padding: 10px 20px;
}
.el-button {
float: right;
}
.el-tag--mini {
margin-left: 5px;
}
.warning {
color: #dc143c;
}
</style>
//这是使用stylus
<style lang="stylus" scoped>
.course-detail
margin-bottom: 40px;
.lesson-information
margin-top: 24px;
display: flex;
justify-content: center;
flex-basis: auto;
align-items: flex-start;
.vjs-paused .vjs-big-play-button, .vjs-paused.vjs-has-started .vjs-big-play-button
display: block !important;
.video-js .vjs-time-control
display: block !important;
.video-js .vjs-remaining-time
display: none !important;
</style>
- 针对一些通用性的功能,比如说我开发在线教育网站,我需要播放器,免费课程作为课程的一种类型,付费类型也作为一种类型,可能整个组织方式都是完全不同的,后台可能抽象出不同的模型,前端也就对应了不同的界面,为了方便播放器可以复用,最好的方式就是封装成
components
。我的作法是在src/components
下创建对应业务的xx.vue
文件,在使用的界面中通过类似import {VideoPlayer} from "components/VideoPlayer.vue"
的方式把组件引入,随便哪个界面,想使用引入后就可以了。但是如果通用性不高,比如每个界面里所需求的播放器外观千差万别,那最好在各个界面内个性化定制就好了。 - 针对于接口请求,常用的
package
比如有axios、request
,两者区别在于axios
会自动根据发送数据的类型选择合适的Content-Type
,比如说默认的application/json
。针对于请求参数为字符串类型时,axios
则会尝试用JSON
格式进行处理,如果解析成功就按plain object
,否则就作为URLSearchParams
形式解析。而request
package在请求层面相对比较原生,在响应层面,axios
会根据responseType
响应数据,而request
返回值类型只有String和Buffer
,当指定返回值的encoding
未设置时,返回值为Buffer
类型,其他任何情况下都是以utf8
进行转换的字符串。两者请求响应之后都返回的是Promise
形式的对象,要对返回值捕获要配合着.then
进行使用,方能获取到常规处理值的类型,做进一步逻辑处理。举两个例子。
//这是request包的使用
import service from '@/utils/request'
export const getApiList = (data) => {
return service({
url: "/api/getMallApiList",
method: 'post',
data
})
}
//这是request包中响应值如何处理,注意前面的async,有它存在就相当于替代了.then之类的promise解包过程
async updateGoodApi(row) {
const res = await getRankingRewardById({id: row.ID})
this.form = res.data.api
this.openDialog('edit')
},
//这是axios包的使用
import axios from 'utils/axios.js'
export function getCourseChapterDetail(params) {
return axios.get('/api/v1/lesson/chapter/' params.id)
}
//这是axios包中响应值如何处理,注意then关键字的使用
getCourseChapterDetailData() {
const params = {
id: this.$route.params.id
}
getCourseChapterDetail(params).then(res => {
let {code, data, msg} = res
if (code === ERR_OK) {
this.courseChapterDetail = data.path
} else {
this.courseChapterDetail = {}
this.$message.error(msg)
}
}).catch(() => {
this.courseChapterDetail = {}
this.$message.error('接口异常')
})
}
第二部分:实录配置我如何给我的站点配置支持视频播放功能
- 我遇到的错误一
The element or ID supplied is not valid. (videojs)
,如何解决? 答:由于我没有使用el-dialog,所以没有遇到有网友发的是由于它的懒加载,导致videojs
找不到需要初始化的playerID
,这过程中为了防止hls
视频流一直刷新,所以必须要删除dom
,虽然直接用不了,但是对我有没有解决问题的借鉴意义呢?
dialog
捕获关闭事件,开启事件,开启后事件
<el-dialog title="视频播放" :visible.sync="videoVisible" customClass="customClass" @close="closevideo" @open="open" @opened="openvideo">
<div style="position:relative;" v-html="videohtml">
</div>
</div>
所涉及修改的相关methods
:
closevideo() {
if (this.player) {
this.player.dispose(); // 该方法会重置videojs的内部状态并移除dom
this.videohtml = '';
}
this.videoVisible = false;
},
handlePlay() {
this.videoVisible = true;
},
open(){
this.videohtml = '<video id="currentPlayer" class="video-js vjs-big-play-centered vjs-default-skin " style="width:700px;height:393.75px" muted></video>';
},
openvideo() {
setTimeout(() => {
this.$nextTick(() => {
this.player = Videojs("currentPlayer", this.options);
});
},300)
}