操操操

Vue中如何创建新的跳转界面

2021-11-08
8分钟阅读时长
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完毕以后,这些变量值在页面中就是可用态,你想怎么玩就怎么玩就可以了。至于computedcreatedmountedpropagate都是事件传播过程中,实现控制的手段。比如:

  • created:在模板渲染完成之前调用,即初始化某些值,然后再渲染成视图
  • mounted:在模板渲染成html之后调用,通常在页面初始化完毕以后,再对html中相应dom节点进行需要的操作。比如表单选项变化时,要向后端接口请求查重,看该选项能否选择。
  • template通常成对出现,用于页面解构成不同部分组成时,每部分有自己的样式,又要汇总在一个界面里展示,这个时候需要用到template
  • 有些建立在layouts下相应业务目录下的xx.vue文件,可以作为component被很多界面引入使用
  • 如果你不想新建文件用于创建component,你可以用let声明的方式,之后把它声明到应用界面的components部分,这样,let指定的变量名称就直接可以在界面中当component用成对标签形式使用了。
  • beforeCreate:创建之前,已经完成了初始化事件和生命周期
  • beforeMouted:已经完成了模板渲染
  • beforeDestory:摧毁之前,整个vue处在实时监控浸染和更新
  • destroyed:已经摧毁,已经摧毁了观察者,子元素和事件监听
  • props声明的意义?
      1. prop作为初始值传入后,子组件想把它当作局部数据来用
      1. prop作为初始值传入后,由子组件处理成其他数据输出
  1. 第一种方式
//局部组件登录模板声明
let login ={   //具体局部组件名称
  template:'<div><h2>用户登录</h2></div>'
};
const app = new Vue({
  el: "#app",
  data: {},
  methods: {},
  components:{  //用来注册局部组件
    login:login  //注册局部组件
  }
});
//局部组件使用 在Vue实例范围内
<login></login>
  1. 第二种方式,同样实现此功能,用符号来指定模板的名称,其它就跟上面方法一样了
//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形式解析。而requestpackage在请求层面相对比较原生,在响应层面,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)
  }
Avatar

Aisen

Be water,my friend.
扫码关注公众号,可领取以下赠品:
《夯实基础的go语言体系建设》645页涵盖golang各大厂全部面试题,针对云原生领域更是面面俱到;
扫码加微信,可领取以下赠品:
【完整版】本人所著,原价1299元的《爱情困惑者必学的七堂课》; 50个搞定正妹完整聊天记录列表详情点这里
【完整版】时长7小时,原价699元《中国各阶层男性脱单上娶指南》;