欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

AngularJS入门知识之MVW类框架的编程思想探讨

程序员文章站 2022-04-21 08:07:43
本文通过实现两个简单的业务需求,探讨angularjs和传统的javascript控制dom实现方式的差别,并尝试理解mvw此类框架在流行的web前端开发中的编程思想。...

本文通过实现两个简单的业务需求,探讨angularjs和传统的javascript控制dom实现方式的差别,并尝试理解mvw此类框架在流行的web前端开发中的编程思想。

这个需求很常见,比如,一个两级菜单,在第一级别菜单项点击时候,对应的子菜单项目应该显示或隐藏。

jquery的实现:


<!-- html -->
<ul class="parent">
    <li class="parent_item">
        item 1
        <ul class="child">
            <li class="child_item">item child 1</li>
        </ul>
    </li>
</ul>

// javascript
$('li.parent_item').click(function(){
    $(this).children('ul.child').toggle();
})

angularjs的实现:


<!-- html -->
<ul>
    <li ng-click="hide_child = !hide_child">
        item 1
        <ul ng-hide="hide_child">
            <li>item child 1</li>
        </ul>
    </li>
</ul>

传统操作dom的方式,不再赘述。angularjs的实现,相对代码要精炼很多,只有html的版本即可。以上代码,用到了angularjs这些知识点:

1.directives 

2.expressions

ng-clickng-hide都是框架自带的directives(指令),前者相当于给li标签提供了一个event handler,在该html元素(li)被点击的时候,会执行hide_child = !hide_child这个expression(表达式)。我们先看一下ng-hide这个指令,它会根据赋值的表达式结果(布尔值)来控制该html元素是否要显示(通过css实现)。也就是说,如果hide_child这个变量如果是true,那么ul就会被隐藏,否则结果相反。  

这里hide_child其实是上的一个变量,对它的值的变更,也可以用controller控制器包装一个方法来实现,只不过现在的语句比较简单,直接写在了指令的赋值里面。

通过以上简单的代码分析,我们可以看到angularjs两个比较明显的特点:

1.通过指令和表达式对dom的操作进行了封转,只需简单的代码便可省去额外的javascript代码
2.指令和表达式的应用,只直接嵌套在html中的,这和jquery推从的unobtrusive javascript的代码风格有些背道而驰

我们先看另外一个需求,再详细解释上面的结论。

需求2:通过点击div,触发选择form中的一个radio button
传统的html form元素,在如今的移动设备上,操作起来并不是十分友好。比如,radio button单选框,在触摸屏上,需要精确的位置定位,才能控制好这个组件,但是手指定位又很粗糙。常见的做法,是添加一个对应的label控件,但是文字本身占屏比例也并不理想,而且也不具备明确的信息传达效果。所以,通常会间接操作一个区域比较大的div或者li标签。

jquery的实现:


<!-- html -->
<ul>
    <li class="selection">
        <input type="radio"
            id="option1" />
        <label for="option1">option 1</label>
    </li>
</ul>

// javascript
$('li.selection').click(function(){
    $(this).children('input[type="radio"]').click();
})

angularjs的实现:


<!-- html -->
<ul>
    <li ng-repeat="option in options"
        ng-click="model.option = option.value"
        ng-class="{active: model.option == option.value}" >
        <input type="radio"
            ng-model="model.option"
            value="{{option.value}}"
            id="option1" />
        <label for="option1">option 1</label>
    </li>
</ul>

在这个解决方案中,我们同样没有涉及到额外的javascript代码,并且多用了几个指令。为了对比参照,我们只关心ng-click和ng-model这两个指令的表达式。

我们先看一下input这个元素的ng-model指令,这里赋值的意思是,我们把模板上的input和$scope.model对象的option属性进行了关联,深入了解数据绑定可以参考data binding。这种指定关联,使得模板控件直接和数据model进行了绑定,并且这种绑定是双向的。意味着,一旦用户修改控件中的值(勾选radio input),对应的model对象就会重新赋值(model.option);同时,如果model对象的值发生了变化,模板中的input控件也会对应反映变化。而这点,在上述jquery的实现中,其实是没有做到的。

所以,这里通过angularjs的数据绑定,点击li元素间接完成触发input的流程是这样子的:

1.点击li标签,给model.option赋值;
2.修改了model对象,定位到对应input控件(value的值为model.option那个);
3.激活input控件的checked属性

通过以上两个案例,我们对web前端的操作有了新的认识。

首先,技术实现上,通过引入新的指令,表达式,数据绑定等概念,我们可以完全新的方式去操作dom,而不仅仅局限在用户和html组件交互操作上的javascript代码的实现。这种思想的变化是巨大的。

从本世纪初,动态web编程的兴起开始,服务器端的编程技术一直在改进。从一开始的cgi/php/asp,由语言和平台产生了.net vs. java,开发效率和软件过程促进了mvc框架/orm/aop等,性能和大数据带来了nodejs/nosql/hadoop等,而浏览器前端的技术需求似乎没有那么激进过。一方面,通过服务器端和数据库,大部分b/s模型的业务需求都能满足;再者,浏览器本身存在不同平台的差异性,对脚本语言和渲染技术的标准不兼容,以及运算能力的欠缺和安全性的考虑。

在这种情况下,浏览器端的需求,大部分时候只需要考虑渲染页面和简单的用户交互。html/dom加上javasript/css就这样成就了前端的主要工作。所以,以前是没有前端工作师,只需要web设计师的。慢慢对前端的要求多起来,jquery成为使用程度最高的一个javascript操作dom的封装库。而在这个阶段,jquery/javascript的主要任务,仍然只是作为面向用户浏览器终端呈现和交互的工具。

理解了jquery的起源,我们不难发现,以前追求的一些规则,譬如unobtrusive javascript,当时局限于实现的手段和方式,为了分离dom和javascript代码逻辑,我们优先选择了维护性更高的方式。前端对javascript的需求加大之后,出现了很多mvc/mvp的前端框架,以及angularjs所谓的mvw(model-view-whatever),javascript和dom一刀切的方式发生了变化。原先我们考虑界面显示和用户交互的直接操作,现在我们有了客户端的数据绑定,丰富的指令,依赖注入,等待我们的将是全新的编程模型和思维方式。