前面介绍了快应用开发的环境搭建,项目结构
这一局就来好好写一下布局吧,看看各个组件是如何排兵布阵的!
项目目录下除了app.ux文件就剩下了Hello.ux文件,很明显,hello.ux 是我们今天的主角。
ux文件主要由三部分组成 template,style,script
第一部分 template(模板)
按照目前得到的全部信息我们可以推断出这一块主要是摆放视图组件的位置,比如放一个text,div什么的,但是需要注意的一点是teamplate只能有一个子view,例如下面的最外层div只能有一个,但是里面是可以有任意多级的。
<template>
<!-- Only one root node is allowed in template. -->
<div class="container">
<text class="title" style="font-size:20px;">
Hello {{title}}
</text>
<text if = "{{show}}">我是第二行,不服打我啊</text>
<text elif="{{dispaly}}">我其实是第三行</text>
<text else>我是第四行</text>
<text show="{{visible}}"> 我是show</text>
<div onclick="press">
<text>略略略</text>
</div>
<div class="list-container">
<text for="{{list}}" tid="id">
<span >{{$idx}}</span>
<span >{{$item.id}}</span>
</text>
</div>
<list>
<block for="cities">
<list-item type="city">
<text>{{$item.name}}</text>
</list-item>
<block for="$item.spots" if="false">
<list-item type="spot">
<text>{{$item.address}}</text>
</list-item>
</block>
</block>
</list>
</div>
</template>
这是我拓展了一些视图的代码
我们好好来理解一下这段代码主要讲了什么
1、<text>标签的编写就是很标准的HTML写法,但是数据绑定时(message)应用的时候用了{{}}符号来标识。
2、条件渲染
分为2种:if/elif/else和show。它们的区别在于:if为false时,组件会从VDOM中移除,而show仅仅是渲染时不可见,组件依然存在于VDOM中。
if/elif/else节点必须是相邻的兄弟节点,否则无法通过编译。
show等同于display=none,目前只用于系统原生组件,对自定义组件不生效。自定义组件可以通过props传入参数,在自己内部使用show来控制是否可见。
3、列表渲染:
标签中的tid用于指定作为定义数组元素唯一Id的字段名,如果没有指定,则默认采用数组索引($idx)作为唯一Id;tid的作用是为了元素节点重用,优化for循环的重绘效率。
例如 tid="id" 表示$item.id作为数组元素的唯一Id。
for循环支持的写法(其中{{}}可以省略):
● "fn":for="list":list为数组对象,默认元素变量为$item。
● "for="value in list":value为自定义的元素变量,默认元素索引为$idx。
● "for="(index,value) in list":index为元素索引,value为元素变量。
注意:
● tid指定的数据属性必须存在,否则可能引起运行异常。
● tid指定的数据属性要保证唯一,如果发生重复,可能会造成性能问题。
可以使用<block>实现更为灵活的循环/条件渲染; 注意<block>目前只支持for和if/elif/else属性,如果没有指定任何属性,<block>则在构建时被当作“透明”节点对待,其子节点被添加到<block>的父节点上。
引入组件,这个就有点像<include>标签了,可以在新定义一个ux文件,把ux布局引入到指定位置。其中IDE有很多可以引入的模板,比如分类栏,底部按钮等等。
<import name='comp' src='./comp'></import>
<template>
<div>
<comp prop1='xxxx' onevent1="bindParentVmMethod1" @event-type1="bindParentVmMethod1"></comp>
</div>
</template>
如果没有设置name属性,则默认采用src的文件名作为组件名。
src属性指定组件ux文件位置,可以省略.ux后缀。
注意:
● 组件名不区分大小写,默认统一采用小写。
● 通过(on|@)event1语法绑定自定义子组件的event1事件,触发事件childVm.$emit('event1', { params: '传递参数' })时执行父组件的方法:bindParentVmMethod1。
● 标签上声明事件名称采用-连接,不要使用驼峰式,来做响应与方法的关联,即:使用event-type1表示绑定eventType1事件。
组件中通过标签来定义子组件插入位置,例如:
组件com-a的模板定义为,其中下面的<slot>标签是占位标签,在这个地方会替换成用该组件包含的view:
<template>
<div>
<text>header</text>
<slot></slot>
<text>footer</text>
<div>
</template>
在页面使用组件comA,定义如下:
<import name="comp-a" src="./comp-a"></import>
<template>
<com-a>
<text>body</text>
</com-a>
</template>
则在页面渲染时,组件comA变为:
<div>
<text>header</text>
<text>body</text>
<text>footer</text>
</div>
第二部分:style (样式)
用于描述template模板的组件样式,决定组件如何显示。
样式布局采用CSS Flexbox(弹性盒)样式,针对部分原生组件,对 CSS 进行了少量的扩充以及修改。
为了解决屏幕适配问题,所有与大小相关的样式(例如width、font-size)均以基准宽度(默认750px)为基础,根据实际屏幕宽度进行缩放,例如width:100px,在1500px宽度屏幕上,width实际上为200px。
1、导入外部样式文件
<!-- 导入外部文件, 代替style内部样式 -->
<style src="./style.css"></style>
<!-- 合并外部文件 -->
<style>
@import './style.css';
.a{
}
</style>
2、内部样式
支持使用style、class属性来控制组件的样式
<!-- 内联inline -->
<div style="color:red; margin: 10px;" />
<!-- class声明 -->
<div class="normal append" />
3、选择器
支持的选择器如下表所示。
选择器 | 样例 | 样例描述 |
.class | .intro | 选择所有拥有 class="intro" 的组件。 |
#id | #firstname | 选择拥有 id="firstname" 的组件。 |
tag | div | 选择所有 div 组件。 |
, | .a, .b | 选择所有class=“.a” 以及class=“.b”的组件。 |
#id .class tag | #page .body text | 支持id,class,tag的后代选择器,也可以使用">"表示直接后代。
|
当前样式的选择器的优先级计算保持与浏览器一致,是浏览器CSS渲染的一个子集(仅支持:inline,id,class,tag,后代,直接后代)
选择器优先级规则如下(假设多条CSS声明匹配到同一个元素div),应用在该元素上的CSS声明总体优先级是:inline > #id > .class > tag,这四大类匹配到该元素的多个CSS声明,如:#page .class-div和.page .class-div,其优先级按照各选择器的分数高低之和来比较。
ID 选择器的权值为10000 ,Class 类选择器的权值为100 ,Tag 标签选择器的权值为1,那么以下CSS声明计算分数为:
● #page的分数为:10000
● #page .class-div的分数为:10100
● #page .class-div text的分数为:10101
● #page #body .container div text的分数为:20102
因此:
#page .class-div和.page .class-div比较,分数不一致,分数高优先级高;如果分数相同,则按照声明顺序:后者覆盖前者。
目前支持less,sass的预编译。
<!--导入外部文件, 代替style内部样式-->
<style lang="less" src="./lessFile.less">
</style>
<!--合并外部文件-->
<style lang="less">
@import './lessFile.less';
.page-less {
#testTag {
.less-font-text, .less-font-comma {
font-size: 60px;
}
}
}
</style>
任何组件中,如果某个属性是boolean类型且默认值为false时,均可通过该属性名字来声明伪类,当属性变为true时伪类生效,例如所有组件的disabled属性、input组件的checked属性等。
另外部分组件会有其他形式的伪类支持,比如input组件可以通过主动调用focus方法,或者用户操作获得焦点,使得focus伪类生效,详情请参考各组件内部说明。
伪类写法举例:
<template>
<input type="button" class="btn" disabled="{{btndisabled}}" value="Click"></input>
</template>
<style>
btn {
width: 360px;
height: 180px;
background-color: red;
}
btn:disabled {
background-color: green;
}
</style>
当组件的disabled属性变为true时,disabled伪类的样式生效,叠加到原有样式上,例子中background-color会从红色变成绿色。
支持的伪类如下:
名称 | 组件 | 效果 |
:active | all | 在屏幕上按下生效,抬起失效。 Tabs下的子组件相当于click效果,抬起不会失效。 说明:大屏设备不支持:active伪类。 |
:disabled | all | 组件disabled属性为true时生效 |
:focus | input textarea | 组件获取focus时生效 |
:checked | input(type="checkbox") switch | 组件checked属性为true生效 |
三:script(脚本)
支持ES6语法。
可以通过import引入功能模块,在代码中调用模块方法请参见API文档说明。
import fetch from "@system.fetch"
也可以一次引入所有的模块,例如:
import system from "@system"
在代码中使用system.network来调用接口方法。
JS代码引用推荐使用import来导入,例如:
import utils from '../Common/utils.js'
data{}:数据块
onInit{}:初始化函数入口
press:function(){
//自定义函数
}
script块中还有很多其他属性,比如生命周期,页面消息,数据方法,公共方法,事件方法,各种公共对象等等,我猜后面真正学习API的时候还会详细说明吧,毕竟就这样看一遍也是记不住的,要编写代码,逐步用上,才能更加透彻的理解。
这三大块就是UX文件的全部内容了,template负责视图的摆放,style负责视图的样式和位置,script负责整体的逻辑结构,页面的生命周期,事件的处理等。
so,那么!今天就这样了,下班下班
you see see you!
one day day !
do not good good study!
just know eat eat eat!
look look you fat!
下一节我们开始学习组件,毕竟我也是搞Android的,对H5的组件也是一知半解,趁这个机会再好好复习一次吧!如果有H5基础的臭弟弟应该可以很快入手了,哭唧唧。
对。就这样了!