Skip to content

zexiplus/TVVM

Folders and files

NameName
Last commit message
Last commit date

Latest commit

9852ac9 · Aug 12, 2020

History

41 Commits
Nov 25, 2018
Dec 11, 2018
Aug 11, 2020
Nov 25, 2018
Dec 10, 2018
Dec 10, 2018
Nov 23, 2018
Nov 23, 2018
Nov 26, 2018
Nov 23, 2018
Nov 21, 2018
Nov 23, 2018
Aug 12, 2020
Nov 23, 2018
Nov 25, 2018
Dec 12, 2018

Repository files navigation

TVVM

build no-dependency

轻量级 TV 端 WEB 应用开发框架

TVVM 是一个专门为 TV WEB APP 开发的 MVVM 模式框架, 它帮助开发者快速开发应用而无需关心焦点控制,键盘绑定,数据绑定等通用逻辑。它没有依赖,体型小巧(20 kb, 官方文档请参考 offcial web

使用

通过 npm 下载

你的系统上需要安装有 nodejs

$ npm install -S tvvm
import * as TVVM from 'tvvm'

var tv = new TVVM({
    ...options
})

手动下载

你也可以通过手动下载的方式, 然后通过<script>标签进行引用, 下载链接

<script src="https://unpkg.com/tvvm/dist/tvvm.min.js"></script>
<script>
    var tv = new TVVM({
        ...options
    })
</script>

特色

焦点自动控制

TV 应用的特点是使用遥控器控制焦点移动, 而并非鼠标点击/手势触摸事件来触发控件,从而进行下一步操作。

这需要我们通过编程的方式控制焦点的移动和跳转。TVVM 致力于减少焦点移动的代码逻辑, 通过配置 t-index 索引, 而非编程的方式解决焦点的移动。

TVVM把应用分成横轴空间和纵轴空间, 例如 声明 t-index="0-1" 代表应用是第1行 (row=0) 第2列 (col=1)为当前焦点 , 当你点击遥控器的向下移动按钮时 row 增加,col 不变, 此时焦点从 t-index="0-1"移动至 t-index="1-1"的元素上 。这些在TVVM内部已经做好了, 开发者只需要在焦点块元素上声明 t-index 索引即可。

除此之外, TVVM 还提供了丰富的选项,例如默认焦点,焦点元素样式,边界穿越,按键值配置等。

focus选项

new TVVM({
    ...,
    focus: {
    	defaultFocusIndex: '0-1', // 默认焦点
    	circle: {
    		horizontal: true, // 当焦点移动到边界时在水平方向可穿越
    		vertical: true // 当焦点移动到边界时在垂直方向可穿越
		},
        ...options
	}
})

html模板

<style>
    *:focus {
        outline: none;
        border: 2px solid #fff;
    }
</style>
<div class="tv">
    <div>
        <div>
            <div t-index="0-1">0-1</div>
            <div t-index="0-2">0-2</div>
            <div t-index="0-3">0-3</div>
        </div>
    </div>
    <div>
        <div t-index="1-0, 2-0" real-focus="true">
            <span>1-0,</span> <span>2-0</span>
        </div>
        <div>
            <div t-index="1-1, 1-2, 1-3">
                <span>1-1,</span> <span>1-2,</span> <span>1-3</span>
            </div>
            <div>
                <div t-index="2-1">2-1</div>
                <div t-index="2-2">2-2</div>
                <div t-index="2-3">2-3</div>
            </div>
        </div>
    </div>
</div>

显示结果

t-index-demo

按键去抖优化

某些物理遥控器在按下按钮时, 有可能高速触发按键事件, 这对应用会产生不良后果, TVVM 在绑定事件的同时在内部会优化操作逻辑, 利用函数去抖控制按键触发频率, 防止因为物理设备差异导致应用逻辑混乱。

数据驱动

TVVM 与大多数 mvvm 思想的前端框架一样, 采用数据驱动的开发模式, 简单来讲,数据驱动使开发者只用关系数据的修改, 而无需手动将数据同步至视图。以下是 t-value 指令来实现双向数据绑定的例子, span 标签内的内容会随着 input 输入框的值的改变而改变

data: function () {
    return {
        demoInputValue: 'demo'
    }
}
<input t-value="data.demoInputValue" />
<span>{{data.demoInputValue}}</span>

API

new TVVM(options)

new TVVM 返回一个tv实例, 作为该页面的全局单例入口

var tv = new TVVM({
	el: '#tv',
    data () {
        return {
			dialogVisible: true
        }
    },
    focus: {

    },
    methods: {
        testFn: function (a, b) {

        }
    }
})

选项

new TVVM接收一个选项对象作为唯一参数

el

new TVVM() 实例挂载的dom元素, 可以是一个元素查找符或者dom节点对象

new TVVM({
    el: '#tv',
})

data

tm单例的数据对象, 可以是一个函数或者对象, 当该参数为函数时, 取值为该函数的返回值

new TVVM({
    data: function () {
        return {
            title: 'tvvm demo page',
            index: '0'
        }
    }
})

methods

该参数是一个对象, 存放所有的方法函数

methods: {
    methods1: function () {
        console.log('methods1')
    }
}

focus

focus选项用于设置焦点移动, 键值绑定, 默认焦点等逻辑

	new TVVM({
        focus: {
            defaultFocusIndex: '1-0',
            activeClass: 'high-light',
            keysMap: {
              'up': {
                codes: [38, 103],
                handler: function (event, node, index, prevNode) {

                }
              },
              'g': {
                codes: [71],
                handler: function (event, node, index, prevNode) {
                  console.log('you press g')
                }
              },

            },
            keysMapMergeCoverage: false,
            circle: {
              horizontal: true,
              vertical: true,
            },
          }
    })
  • defaultFocusIndex (可选)

    进入应用默认聚焦的元素的索引, 该参数为空时, 默认聚焦到页面首个焦点元素上

    focus: {
        defaultIndex: '0-1'
    }
  • activeClass

    焦点元素的样式名

    focus: {
        activeClass: 'high-light'
    }
  • circle (可选)

    • horizontal (可选) 焦点元素在水平方向是否可以循环移动, 默认false
    • vertival (可选) 焦点元素在水平方向上是否可以循环移动, 默认false
    focus: {
        circle: {
            horizontal: true,
            vertical: true
        }
    }
  • keysMap (可选)

    遥控器键盘键值码映射表, 该参数为空时使用默认键值码映射表

    - 'alias' 对应键值的别名

    - codes 对应键值数组

    • handler 对应按键值绑定的事件处理函数 参数分别是event(事件), node(当前焦点dom节点索引), index (当前焦点dom节点的t-index值), prevNode(上一个焦点dom节点索引)

    • up 方向上键

    • down 方向下键

    • left 方向左键

    • right 方向右键

    • enter 确定键

    • space 空格键

    • home 主页键

    • menu 菜单键

    • return 返回键

    • addVolume 增加音量键

    • subVolume 减少音量键

    focus: {
        keysMap: {
        'up': {
          codes: [38, 104],
          handler: function (event, node, index, prevNode) {
    
          }
        },
        'down': {
          codes: [40, 98],
          handler
        },
        'left': {
          codes: [37, 100],
          handler
        },
        'right': {
          codes: [39, 102],
          handler
        },
        'enter': {
          codes: [13, 32],
          handler
        }
      },
    }
  • keysMapMergeCoverage (可选)

    键值映射表合并策略 true 为覆盖, false 为合并

    focus: {
        keysMapMergeCoverage: false,
    }

hooks

生命周期钩子函数集合

  • beforeCreate

    在实例化之前调用, 此时不可访问 data

  • created

    在实例化后调用,此时 data 已经设置响应式, 并可访问

  • beforeMount

    在实例被挂在到真实 dom 前调用

  • mounted

    在实例被挂在到 dom 上时调用

  • beforeUpdate

    响应式 data 变动从而导致视图更新前调用

  • updated

    响应式 data 变动从而导致视图更新后调用

  • beforeDestory

    在实例被销毁前调用

hooks: {
    beforeCreate: function () {
        // this 指向tv实例
    },
    mounted: function () {
    	        
    },
    ...
}

指令

TVVM 内置指令系统, 包含了一些常用的指令, 用于处理简单的模版逻辑.TVVM 内置指令通常以 t-开头作为标识

<html>
    <head></head>
    <body>
        <div id="tv">
            <div t-if="data.dialogVisible" class="dialog">{{data.dialog.title}}</div>
            <nav>
                <a t-for="item in data.linkList">{{item.label}}</a>
            </nav>
            <form>
            	<input t-model="data.dialog.title" />
            </form>
            <button @click="methods.testFn"></button>
        </div>
    </body>
</html>

t-index

用于指定焦点区块元素的二维空间索引,以便用户点击遥控器方向按键时移动焦点,t-index="x-y", 例如t-index="0-0"代表第一排第一列的元素

<div class="tv">
    <div t-index="0-0">0-0</div> <!-- 第1排第1个元素 -->
    <div t-index="0-1">0-1</div>
    <div t-index="0-2">0-2</div>
    <!-- 第2排第1个元素, 纵向占据2个空间 -->
    <div t-index="1-0, 2-0">1-0, 2-0</div> 
    <div>
        <!-- 第2排第2个元素, 横向占据3个空间 -->
        <div t-index="1-1, 1-2, 1-3">1-1, 1-2, 1-3</div> 
        <div>
            <div t-index="2-1">2-1</div> <!-- 第3排第2个元素 -->
            <div t-index="2-2">2-2</div> <!-- 第3排第3个元素 -->
            <div t-index="2-3">2-3</div> <!-- 第3排第4个元素 -->
        </div>
    </div>
</div>

效果如图

t-if

用于显示/隐藏 dom 节点, 该指令接收一个在 data 参数上存在的布尔值

<div t-if="data.dialogVisible"></div>

t-for

用于循环指定的 dom 节点, 该指令接收一个表达式,如下 item 代表数组的每一项, data.array是 data 上定义的一个数组

data: function () {
    return {
        array: [
            {label: 'first', value: 0},
            {label: 'second', value: 1},
            {label: 'third', value: 2}
        ]
    }
}
<ul>
    <li t-for="item in data.array">{{item.label}}</li>
</ul>
<!-- 渲染为 -->
<ul>
    <li>first</li>
    <li>second</li>
    <li>third</li>
</ul>

{{value}}

数据插值, 双花括号内接收一个 data 的属性.用于页面内数据插值

data: function () {
    return { name: 'float' }
}
<span>{{data.name}}</span>
<!-- 渲染为 -->
<span>float</span>

t-class

样式表绑定, t-class 接收一个 data 上已经定义的样式名数组或对象

data: function () {
    return {
        classList1: ['container', 'container-row'],
        classList2: {
            'container': true,
            'container-row': false,
            'container-col': true
        }
    }
}
<div t-class="data.classList2"></div>
<!-- 渲染为 -->
<div class="container container-col"></div>

t-bind

属性绑定,t-bind:name="data.name" 简写形式为 :name="data.name"

data: function () {
    return {
        id: 'billboard',
        height: '365',
        classname: 'spin'
    }
}
<div :id="data.id" :height="data.height" :class="data.classname"></div>
<!-- 渲染为 -->
<div id="billboard" height="365" class="spin"></div>

t-value

用于 input 输入数据与 data 上数据的绑定,input 的 value 会实时同步至t-model 绑定的数据

data: function () {
    return {
        demoInputValue: 'demo'
    }
}
<input t-value="data.demoInputValue" />
<span>{{data.demoInputValue}}</span>

event bind

事件绑定

methods: {
    clickHandler: function () {
        // do something
    },
    clickHandler2: function (param1, param2) {
    	     
    }
}
<div @click="methods.clickHandler"></div>
<div @click="methods.clickHandler2(data.inputValue)"></div>

协议

TVVM 采用MIT协议,详情查看LICENSE

链接

About

轻量级TV端WEB应用开发框架

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published