迷你MVVM框架 avalonjs 学习教程6、插入移除处理

ms-if是属于流程绑定的一种,如果表达式为真值那么就将当前元素输出页面,不是就将它移出DOM树。它的效果与上一章节的ms-visible效果看起来相似的,但它会影响到:empty伪类,并能更节约性能。ms-if还有一个分支,叫ms-if-loop,它是配合ms-repeat绑定使用,因此以后再说。

我们可以通过以下例子比较一下两者:


<!DOCTYPE HTML>

<html>

    <head>

        <title>ms-if</title>

        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

        <script src="avalon.js" ></script>

        <script>

            var vmodel = avalon.define({

                $id: "test",

                object: {}

            })



            setTimeout(function() {

                vmodel.object = {id: "132", message: "显示!!"}

            }, 3000)



            setTimeout(function() {

                vmodel.object = {}

            }, 5000)



        </script>

    </head>

    <body>

        <div ms-controller="test" >

            这是比较输出结果:{{object.id != null}}

            <div ms-visible="object.id != null">

                这是visible的:

                <span>{{object.message}}</span>

            </div>

            <div ms-if="object.id != null">

                这是if的:

                <span>{{object.message}}</span>

            </div>

        </div>

    </body>

</html>

enter image description here

ms-if的实现比ms-visible复杂多了,如果一开始扫描到此元素,计算其值为false,它就不会再扫描里面的元素,并且立即移除此元素。这正是它比ms-visible性能更优的关键。为了能在重新插入DOM时找到正确的位置,avalon还得创建一个注释节点做路标。而被移除的元素是放在一个叫ifSanctuary的DIV中,方便统一管理。

"if": function(data, vmodels) {//这里是第一次扫描时的执行函数

    var elem = data.element

    elem.removeAttribute(data.name)

    if (!data.placehoder) {

        data.msInDocument = data.placehoder = DOC.createComment("ms-if")

    }

    data.vmodels = vmodels

    parseExprProxy(data.value, vmodels, data)

},





"if": function(val, elem, data) {//这是每次改变ViewModel对应属性时的执行函数

    var placehoder = data.placehoder

    if (val) { //插回DOM树

        if (!data.msInDocument) {

            data.msInDocument = true

            if(placehoder.parentNode)

                placehoder.parentNode.replaceChild(elem, placehoder)

            } 

        }

        if (rbind.test(elem.outerHTML.replace(rlt, "<").replace(rgt, ">"))) {

            scanAttr(elem, data.vmodels)

        }

    } else { //移出DOM树,放进ifSanctuary DIV中,并用注释节点占据原位置

        if (data.msInDocument) {

            data.msInDocument = false

            if(elem.parentNode)

                elem.parentNode.replaceChild(placehoder, elem)

            } 

            placehoder.elem = elem

            ifSanctuary.appendChild(elem)

        }

    }

},

最后,我们还是用切换卡例子结束本章吧。

<!DOCTYPE html>

<html>

    <head>

        <title>TODO supply a title</title>

        <meta charset="UTF-8">

        <meta name="viewport" content="width=device-width">

        <script src="avalon.js"></script>

        <script >

            var model = avalon.define({

                $id: "test",

                currentIndex: 0,

                toggle: function(index) {

                    model.currentIndex = index

                }

            })

        </script>

        <style>

            button{

                width:150px;

                height:30px;

                line-height: 30px;

                text-align: center;

            }

            .ms-tabs{

                border:1px solid violet;

                width: 430px;

                padding:5px;

                height: 200px;

            }

        </style>



    </head>

    <body ms-controller="test" >

        <button ms-click="toggle(0)">触发器1</button> 

        <button ms-click="toggle(1)">触发器2</button>

        <button ms-click="toggle(2)" >触发器3</button>

        <div class="ms-tabs" ms-if="currentIndex === 0">切换卡1<br/>其他内容</div>

        <div class="ms-tabs" ms-if="currentIndex === 1">切换卡2<br/>及司徒正美</div>

        <div class="ms-tabs" ms-if="currentIndex === 2">切换卡3<br/>最后一个了</div>

    </body>

</html>

enter image description here

你可能感兴趣的:(val)