Skip to content

子模块

xuwhale6 edited this page Aug 19, 2020 · 10 revisions

子模块

一、概述

增加以函数为基础的模块化功能,抽取公共代码,实现复用,减少冗余。

  • 原因:
ui {
    --这里写全部页面逻辑,代码会变得臃肿,需要提供模块化能力
}
  • 模块化说明:
  1. table名作为函数名(如下mLabel
  2. 支持传递参数
  3. 声明式代码里不需要return,构建出的view作为返回值

二、基本用法

关键代码:
--定义子模块
mLayout(str) {
   --子模块具体实现
   Label().text(str)
}

ui{
   --使用子模块,传入参数
   mLayout("哈哈哈")
}
  • 示例demo使用如下:
img1 = "https://s.momocdn.com/w/u/others/custom/MLNUI/MLNUI/ico_watch.png"
img2 = "https://s.momocdn.com/w/u/others/custom/MLNUI/MLNUI/ico_vip.png"
img3 = "https://s.momocdn.com/w/u/others/custom/MLNUI//MLNUI/ico_order.png"

--定义子模块
mLayout(imgUrl, title, bgColor, num) {
    VStack()
    .crossAxis(CrossAxis.CENTER)
    .subs(
        HStack()
        .mainAxis(MainAxis.CENTER)
        .bgColor(bgColor)
        .cornerRadius(40)
        .width(60)
        .height(60)
        .subs(
            ImageView().width(35)
            .height(35)
            .image(imgUrl)
            .crossSelf(CrossAxis.CENTER)
            ,
            Label()
            .bgColor(Color(0xdd6600))
            .text(tostring(num))
            .padding(2, 8, 2, 8)
            .cornerRadius(30)
            .fontSize(10)
            .textColor(Color(0xffffff))
            .positionType(PositionType.ABSOLUTE)
            .positionTop(0)
            .positionRight(0)
        )
        ,
        Label(title)
    )
}
---
--- UI
ui {
    HStack()
    .widthPercent(100)
    .mainAxis(MainAxis.SPACE_EVENLY)
    .subs(
        --使用子模块
        mLayout(img1, "谁看过我", Color(0xaadd00), 12),
        mLayout(img2, "会员中心", Color(0xaadddd), 0),
        mLayout(img3, "订单", Color(0xddaa00), 3)
    )
}.safeArea(SafeArea.TOP)
---
--- preview
local function preview()

end
  • UI显示如下:

三、值传递、引用传递

  • 值传递

默认是值传递,方便子模块成为纯函数。

function(model)
  • 引用传递

使用make_refmodel标记为引用传递。

function(make_ref(model))

先来看下面的代码:

model(userData)

function updata(model)
    --值传递:传入的userData未被修改。
    --引用传递:传入的userData被修改。
    model.name = "update"
    print(userData.name)
end
---
--- UI
ui {
    --- layout views
    Label(userData.name)
    .width(100)
    .height(100)
    .bgColor(200, 0, 0, 0.5)
    .textAlign(TextAlign.CENTER)
    .onClick(function()
        --默认是值传递。这里我们想将model作为参数传入函数中,在函数中修改model值,会发现userData未被修改。
        --updata(userData)
        --使用make_ref将model标记为引用传递,并作为函数的参数传入即可实现函数中修改userData值。
        updata(make_ref(userData))
    end)
}

---
--- preview
local function preview()
    userData.name = "点我"
end
--默认是值传递。这里我们想将model作为参数传入函数中,在函数中修改model值,会发现model未被修改。
updata(userData)
--使用make_ref将model标记为引用传递,并作为函数的参数传入即可实现函数中修改model值。
updata(make_ref(userData))

四、函数式用法

  • 子模块提供封装性
参考基本用法中示例,我们抽取公共代码,可多次复用,即为封装性。如下图:    
  • 组合替代继承
我们可以在现有子模块的基础上进行组合拓展产生新的子模块。

--关键代码:我们可以使用子模块mLayout,延伸出新的子模块mItem
mItem(imgUrl, title, bgColor, num, desc) {
    HStack()
    .padding(10, 10, 10, 10)
    .widthPercent(100)
    .bgColor(Color(0xadadad))
    .subs(
        mLayout(imgUrl, title, bgColor, num)
        ,
        mDescLayout(title, desc)
    ).crossAxis(CrossAxis.CENTER)
}
img1 = "https://s.momocdn.com/w/u/others/custom/MLNUI/MLNUI/ico_watch.png"
img2 = "https://s.momocdn.com/w/u/others/custom/MLNUI/MLNUI/ico_vip.png"
img3 = "https://s.momocdn.com/w/u/others/custom/MLNUI//MLNUI/ico_order.png"

--定义子模块mLayout
mLayout(imgUrl, title, bgColor, num) {
    VStack()
    .crossAxis(CrossAxis.CENTER)
    .subs(
        HStack()
        .mainAxis(MainAxis.CENTER)
        .bgColor(bgColor)
        .cornerRadius(40)
        .width(60)
        .height(60)
        .subs(
            ImageView().width(35)
            .height(35)
            .image(imgUrl)
            .crossSelf(CrossAxis.CENTER)
            ,
            Label()
            .bgColor(Color(0xdd6600))
            .text(tostring(num))
            .padding(2, 8, 2, 8)
            .cornerRadius(30)
            .fontSize(10)
            .textColor(Color(0xffffff))
            .positionType(PositionType.ABSOLUTE)
            .positionTop(0)
            .positionRight(0)
        )
        ,
        Label(title)
    )
}
--定义子模块mLayout、mDescLayout
mDescLayout(title, desc) {
    VStack().subs(
        Label(title).textColor(Color(0xffff00))
        ,
        Label(desc).textColor(Color(0xffffff)).top(5)
    ).left(20)
}
--使用mLayout、mDescLayout组合产生新的子模块mItem
mItem(imgUrl, title, bgColor, num, desc) {
    HStack()
    .padding(10, 10, 10, 10)
    .widthPercent(100)
    .bgColor(Color(0xadadad))
    .subs(
        mLayout(imgUrl, title, bgColor, num)
        ,
        mDescLayout(title, desc)
    ).crossAxis(CrossAxis.CENTER)
}
---
--- UI
ui {
    HStack()
    .widthPercent(100)
    .mainAxis(MainAxis.SPACE_EVENLY)
    .subs(
    --使用子模块
        mLayout(img1, "谁看过我", Color(0xaadd00), 12),
        mLayout(img2, "会员中心", Color(0xaadddd), 0),
        mLayout(img3, "订单", Color(0xddaa00), 3)
    ).bottom(20)
    ,
    mItem(img1, "熊大", Color(0xdddddd), "vip", "哈哈哈哈哈哈哈哈")
    ,
    mItem(img1, "熊二", Color(0xaddddd), "svip", "太赞了,666")
}.safeArea(SafeArea.TOP)
---
--- preview
local function preview()

end
  • 高阶函数代替多态
不同子模块中具体实现基本子模块的函数,实现多态

--基本子模块
mLayout(func) {
    VStack().onClick(func)
}
mItem1() {
    --mItem1继承mLayout子模块,并实现function
    mLayout(function()
        --具体实现1 
    end)
}
mItem2() {
    --mItem2继承mLayout子模块,并实现function
    mLayout(function()
        --具体实现2 
    end)
}
model(uData)
img1 = "https://s.momocdn.com/w/u/others/custom/MLNUI/MLNUI/ico_watch.png"
img2 = "https://s.momocdn.com/w/u/others/custom/MLNUI/MLNUI/ico_vip.png"
img3 = "https://s.momocdn.com/w/u/others/custom/MLNUI//MLNUI/ico_order.png"

--定义子模块mLayout
mLayout(imgUrl, title, bgColor, num, func) {
    VStack()
    .crossAxis(CrossAxis.CENTER)
    .subs(
        HStack()
        .mainAxis(MainAxis.CENTER)
        .bgColor(bgColor)
        .cornerRadius(40)
        .width(60)
        .height(60)
        .subs(
            ImageView().width(35)
            .height(35)
            .image(imgUrl)
            .crossSelf(CrossAxis.CENTER)
            ,
            Label()
            .bgColor(Color(0xdd6600))
            .text(tostring(num))
            .padding(2, 8, 2, 8)
            .cornerRadius(30)
            .fontSize(10)
            .textColor(Color(0xffffff))
            .positionType(PositionType.ABSOLUTE)
            .positionTop(0)
            .positionRight(0)
        )
        ,
        Label(title)
    ).onClick(func)
}
--定义子模块mDescLayout
mDescLayout(title, desc) {
    VStack().subs(
        Label(title).textColor(Color(0xffff00))
        ,
        Label(desc).textColor(Color(0xffffff)).top(5)
    ).left(20)
}
--继承mLayout产生新的子模块mItem1
mItem1(imgUrl, title, bgColor, num, desc) {
    HStack()
    .padding(10, 10, 10, 10)
    .widthPercent(100)
    .bgColor(Color(0xadadad))
    .subs(
        mLayout(imgUrl, title, bgColor, num, function()
            uData.name1 = "mItem1"
        end)
    ).crossAxis(CrossAxis.CENTER)
}
--继承mLayout产生新的子模块mItem2
mItem2(imgUrl, title, bgColor, num, desc) {
    HStack()
    .padding(10, 10, 10, 10)
    .widthPercent(100)
    .bgColor(Color(0xad7dad))
    .subs(
        mLayout(imgUrl, title, bgColor, num, function()
            uData.name2 = "mItem2"
        end)
        ,
        mDescLayout(title, desc)
    ).crossAxis(CrossAxis.CENTER)
}
---
--- UI
ui {
    VStack()
    .widthPercent(100)
    .subs(
        mItem1(img1, uData.name1, Color(0xdddddd), "vip", "哈哈哈哈哈哈哈哈")
        ,
        mItem2(img1, uData.name2, Color(0xaddddd), "svip", "太赞了,666")
    )
}.safeArea(SafeArea.TOP)
---
--- preview
local function preview()
    uData.name1 = "熊大"
    uData.name2 = "熊二"
end
Clone this wiki locally