0%

ts+webpack视频播放器组件(三)

day3,弹层创建

  1. 在index.html中,定义一个class为view的div,展示一张图片,作为点击触发视频播放器弹层的入口
    1
    2
    3
    <div class="view">
    <img>
    </div>
  2. 在main.ts中,通过querySelector()获取.view绑定的dom元素,并监听他的点击事件
    1
    2
    3
    4
    5
    6
    let view = document.querySelector(".view")

    view.addEventListener('click',function (){
    let dom = document.querySelector('body')
    console.log('222')
    })
  3. 根目录下创建一个组件目录,在内部新建有关弹出的组件js,这里我创建了components/popView/index.ts
  4. 在index.ts中定义popView函数、view类,在函数内返回view的对象实例,并将他导出。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    //index.js
    function popView(){
    return new view()
    }

    class view{
    constructor(){}
    }

    export default popView
  5. 为了对popView和view进行约束,防止他传入错误的参数,我们需要定义接口iView和接口iComponents并使用。让popView的参数根据iView定义。iView接口里声明了和创建播放器相关的参数,例如播放器的宽高、位置等,其中content是定义弹出的容器,例如弹出播放器,还是表单等等。iComponents接口对view内需要具备哪些方法,初始化方法init()、模板创建template()。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    //index.ts
    //参数的定义
    interface iView{
    width?:string,
    height?:string,
    title?:string,
    pos?:string,
    mask?:boolean,
    content?:()=>void
    }
    //组件的定义
    interface iComponents{
    //初始化
    init(),
    template()
    }

    function popView(options:iView){
    return new view(options)
    }

    class view implements iComponents{
    constructor(private settings:iView) {
    }
    init() {
    }
    template() {
    }
    }

    export default popView
  6. 先尝试点击后,在body中新增一个dom元素。首先在iComponents接口里新增tempContainer,声明为HTMLElement,然后再template函数中,将他作为虚拟dom进行操作,并挂载到body内。将template写进init(),然后把init()写进构造器,使对象被创建时就会初始化。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    //参数的定义
    interface iView{
    width?:string,
    height?:string,
    title?:string,
    pos?:string,
    mask?:boolean,
    content?:()=>void
    }
    //组件的定义
    interface iComponents{
    tempContainer:HTMLElement
    //初始化
    init(),
    template(),
    handel:()=>void
    }

    function popView(options:iView){
    return new view(options)
    }

    class view implements iComponents{
    tempContainer;
    constructor(private settings:iView) {
    this.init()
    }
    init() {
    this.template()
    }
    template() {
    this.tempContainer = document.createElement('div')
    this.tempContainer.innerHTML= `<h1>222</h1>`
    document.body.appendChild(this.tempContainer)
    }
    handel() {
    }
    }

    export default popView
  7. 测试添加dom元素成功,接着为view对象弄上默认值。这里用Object.assign方法,把默认值写在第一个参数,构造器接收的参数写在第二个参数。这样就可以实现,如果构造器有对应参数就进行覆盖。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    //参数的定义
    interface iView{
    width?:string,
    height?:string,
    title?:string,
    pos?:string,
    mask?:boolean,
    content?:()=>void
    }
    //组件的定义
    interface iComponents{
    tempContainer:HTMLElement
    //初始化
    init(),
    template(),
    handel:()=>void
    }

    function popView(options:iView){
    return new view(options)
    }

    class view implements iComponents{
    tempContainer;
    constructor(private settings:iView) {
    //写好默认值,如果后面有参数,用assign复制就可以覆盖默认值
    this.settings = Object.assgin({
    width:'100%',
    height:'100%',
    title:'',
    pos:'center',
    mask:true,
    //定义弹层的容器,是弹出表单还是弹出视频等等
    content:()=>{}
    },settings)
    this.init()
    }
    init() {
    this.template()
    }
    template() {
    this.tempContainer = document.createElement('div')
    this.tempContainer.innerHTML=
    `
    <h1>
    222
    </h1>
    `
    document.body.appendChild(this.tempContainer)
    }
    handel() {
    }
    }

    export default popView
  8. 测试发现没有问题,就开始进行真正的需求,弹出一个窗口。先进行基本的窗口HTML。一部分navbar,一部分content。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    template() {
    this.tempContainer = document.createElement('div')
    //样式添加
    this.tempContainer.style.width = this.settings.width
    this.tempContainer.style.height = this.settings.height
    this.tempContainer.innerHTML =
    `
    <div>
    <h3>${this.settings.title}</h3>
    <i class="iconfont player-icon_close"></i>
    </div>
    <div>
    </div>
    `
    //挂载
    document.body.appendChild(this.tempContainer)
    //使pos生效
    switch (this.settings.pos) {
    case 'left':
    this.tempContainer.style.left = 0
    this.tempContainer.style.top = (window.innerHeight - this.tempContainer.offsetHeight) + 'px'
    break;
    case 'right':
    this.tempContainer.style.right = 0
    this.tempContainer.style.top = (window.innerHeight - this.tempContainer.offsetHeight) + 'px'
    break;
    default:
    this.tempContainer.style.left = (window.innerWidth - this.tempContainer.offsetWidth) / 2 + 'px'
    this.tempContainer.style.top = (window.innerHeight - this.tempContainer.offsetHeight) / 2 + 'px'
    break;
    }
    if(this.settings.mask){
    this.mask = document.createElement('div')
    this.mask.className = styles.mask
    this.mask.style.width = '100%'
    this.mask.style.height = document.body.offsetHeight + 'px'
    document.body.appendChild(this.mask)
    }
    }
  9. 窗口写好了,但是没有样式,看起来贼奇怪,所有我们在组件所在目录,增加一个index.css,在index.ts中进行导入。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    .popup{
    position: fixed;
    z-index: 20;
    }
    .popup-title{
    height: 60px;
    background-color: #f5f5f5;
    display: flex;
    justify-content: space-between;
    align-items: center;
    }
    .popup-title h3{
    font-size: 18px;
    margin-left: 20px;
    }
    .popup-title i{
    font-size: 18px;
    margin-right: 20px;
    cursor: pointer;
    }
    .popup-content{
    height: calc(100% - 60px);
    background-color: white;
    }
    .mask{
    position: absolute;
    left: 0;
    top: 0;
    z-index: 10;
    background-color: rgba(0, 0, 0, .5);
    }
  10. 但是此时又诞生一个新的问题,ts会提示找不到css模块。所以在组件的目录下,我们还需要创建一个index.css.d.ts文件,帮助ts识别。
    1
    2
    3
    4
    5
    declare const styles : {
    readonly "popup" : string
    readonly "popup-title" : string
    }
    export default styles
  11. 导入css文件后,需要把相应属性绑定到dom上,所以我们通过$在模板字符串内绑定。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    let styles = require('./index.css')

    //参数的定义
    interface iView{
    width?:string,
    height?:string,
    title?:string,
    pos?:string,
    mask?:boolean,
    content?:()=>void
    }
    //组件的定义
    interface iComponents{
    tempContainer:HTMLElement
    //初始化
    init(),
    template(),
    handel:()=>void
    }

    function popView(options:iView){
    return new view(options)
    }

    class view implements iComponents{
    //虚拟dom对象
    tempContainer;
    //遮罩层对象
    mask;

    constructor(private settings:iView) {
    //写好默认值,如果后面有参数,用assign复制就可以覆盖默认值
    this.settings = Object.assign({
    width: '100%',
    height: '100%',
    title: '',
    pos: 'center',
    mask: true,
    content: function () { }
    }, this.settings)
    // this.settings = {
    // width: settings.width || '100%',
    // height: settings.height || '100%',
    // title: settings.title || '',
    // pos: settings.pos || 'center',
    // mask: settings.mask !== undefined ? settings.mask : true,
    // content: settings.content || (() => console.log('22'))
    // };
    this.init()
    }
    init() {
    this.template()
    // this.settings.mask && this.createMask()
    }
    template() {
    this.tempContainer = document.createElement('div')
    //样式添加
    this.tempContainer.style.width = this.settings.width
    this.tempContainer.style.height = this.settings.height
    this.tempContainer.className = styles.popup
    this.tempContainer.innerHTML =
    `
    <div class="${styles['popup-title']}">
    <h3>${this.settings.title}</h3>
    <i class="iconfont player-icon_close"></i>
    </div>
    <div class="${styles['popup-content']}">
    </div>
    `
    //挂载
    document.body.appendChild(this.tempContainer)
    //使pos生效
    switch (this.settings.pos) {
    case 'left':
    this.tempContainer.style.left = 0
    this.tempContainer.style.top = (window.innerHeight - this.tempContainer.offsetHeight) + 'px'
    break;
    case 'right':
    this.tempContainer.style.right = 0
    this.tempContainer.style.top = (window.innerHeight - this.tempContainer.offsetHeight) + 'px'
    break;
    default:
    this.tempContainer.style.left = (window.innerWidth - this.tempContainer.offsetWidth) / 2 + 'px'
    this.tempContainer.style.top = (window.innerHeight - this.tempContainer.offsetHeight) / 2 + 'px'
    break;
    }
    }
    //事件操作
    handel() {
    }
    }

    export default popView
  12. 这种场景的窗口,一般都会有遮罩层,所有我们在模板创建方法里,增加一个判断,如果遮罩层选项为true,就多增加一个遮罩层。
    1
    2
    3
    4
    5
    6
    7
    if(this.settings.mask){
    this.mask = document.createElement('div')
    this.mask.className = styles.mask
    this.mask.style.width = '100%'
    this.mask.style.height = document.body.offsetHeight + 'px'
    document.body.appendChild(this.mask)
    }
  13. 给了css之后,发现弹出的窗口是全屏的,因为我们默认的长宽是100%的,我们要在main.js里,对popView传参
    1
    2
    3
    4
    5
    6
    popView({
    width:'880px',
    height:'556px',
    pos:'center',
    mask:true,
    })