js怎么实现这个功能?

发布网友 发布时间:2022-04-23 19:10

我来回答

2个回答

懂视网 时间:2022-05-15 01:33

下面我就为大家分享一篇js实现一个简单的MVVM框架示例,具有很好的参考价值,希望对大家有所帮助。

以前都是默默地看园子里的文章,猥琐的点赞,今天也分享一下自己用js实现的一个简单mvvm框架。

最初只做了自动绑定事件,后面又参考学习了vue,knouckout以及argular实现方式,以及结合自己做WPF的一些经验,增加了属性绑定,今天又稍微整理了下,完善了部分功能,把代码提交到了码云:https://gitee.com/zlj_fy/Simple-MVVM

先简单介绍下用法:

<form class="form-horizontal" role="form" data-context="TestController">
 <p class="form-group">
 <legend>Form title</legend>
 </p>
 <p class="form-group">
 <p class="col-sm-6 col-sm-offset-2">
 <input type="text" class="form-control" bind-val="age,format=format" style="margin:5px 0" />
 <input type="text" class="form-control" bind-val="desc" style="margin:5px 0" />
 <input type="range" min="10" max="300" bind-val="age" step="10" class="form-control" style="margin:5px 0" />
 <input type="button" class="btn btn-primary" value="更新" style="margin:5px 0" on-click="update" />
 </p>
 </p>
 </form>
 <script>
 var TestController = {
 data: {
 name: 'xiaoming',
 age: 3,
 desc: function() {
            return this.name + ' likes looking little movie. he should take care of his body' 
 }
 },
 format: function(val) {
 return val + '岁'
 },
 update: function() {
 this.name = 'this is a test'
 this.age = 18
 }
 }
 $('body').controller()
 </script>

首先定义一个控制器,可以是json对象,也可一是一个function,然后在顶层的元素定义data-context=“[控制器名称]”就可以将该控制器绑定到该节点底下所有元素。如果元素后代存在嵌套Controller,则其所在的元素以下子元素作用域指向子控制器。

1.监控属性以及复杂属性

所有属性必须定义在data节点下,如果里面的属性定义成function则认为是复杂属性(例如desc),复杂属性是只读的,重新赋值的话会提示错误。

绑定到html元素上的格式:"{属性名,fomat=[控制器方法]}",属性名支持嵌套属性,例如(a.b);属性名不支持表达式,考虑了觉得不是很有必要,完全可以使用复杂属性去代替,当前缺点是业务复杂的话可能造成大量复杂属性;属性名右边是可选参数,目前只有format,也就是属性显示在html上的转换方法。

2.指令

绑定指令语法是 bind-{指令}的形式,目前只实现了val,attr,text,html,template,其实可以看出,前面4个都只是简单封装了jqeury方法,template是用到了jquery-tmpl插件实现的,如果你需要更多的指令,你可以自己去扩展,只需要实现init初始加载方法(接收当前的observer参数),以及update方法(参数说明:对应的jquery元素,最新的值,当前控制器实例);如果是扩展已有的指令,默认会覆盖原有的。如下:

$.controller.addDirective("val", {
 init: function (observer) {
 if (observer.$ele.is('input,select')) {
 //监听onchange事件
 observer.$ele.on('input propertychange', function () {
 var newVal = $(this).val()
 observer.writeValue(newVal)
 })
 }
 },
 update: function ($ele, newVal, controller) {
 $ele.val && $ele.val(newVal)
 }
 })

3.事件

绑定事件语法:on-{事件}=“{控制器方法},type=on/one”,控制器方法右边是可选参数,目前只有绑定类型on/one,默认是on;控制器方法接收两个参数,一个是可在对应事件的元素上设置初始参数,一个是event事件参数;

<button type="button" class="btn btn-primary" data-page="1" on-click="refesh">查询</button>

4.方法

直接使用this.属性名,就可以直接访问对应data节点下的属性。

5.钩子

init以及created,init是在监听所有属性之后编译dom之前,可以在这方法上初始化参数;created是编译dom元素之后。

其中控制器默认实现了extend继承方法,可以继承另一个控制器,必须在init方法中使用。当前你也可以自己使用原型继承的方式去实现。

init: function () {
 this.extend(PageController)
 },
 created: function () {
 //TODO
 },

6.扩展

相信大家在做项目的时候肯定都会有一套公用的组件,那么可以像下面那样扩展,默认对应的组件挂载到所有的控制器示例下面,就可以之间在对应的方法下直接调用了: this.http.post();

不过有一个建议,就是尽量统一将回调方法的作用域指向控制器,这样开发不至于老是出现作用域的问题。

$.controller.extend({
 utils: utils,
 notify: $.notify,
 modal: $.modal,
 http: $.http,
 alert: $.alert
 })

7.原理以及代码分析(待续...)

整个js代码量只有300多行,所以实现的比较简单,有很多方面是没有考虑到的,还有一些功能是想实现却没有去做的,目前不支持数组变化检测,以及局部更新相关dom。

上面是我整理给大家的,希望今后会对大家有帮助。

相关文章:

详细说明在vue2中使用axios解决http请求出现的问题(详细教程)

在vue中通过axios处理post请求传参的问题(详细教程)

通过vue实现添加axios组件,解决post传参数为null方面的问题(详细教程)

通过axios发送post请求发现springMVC接收不到参数问题(详细教程)

在vue中使用xe-utils函数库(详细教程)

jQuery+koa2实现简单的Ajax请求的示例

热心网友 时间:2022-05-14 22:41

如果用MVVM框架来搞,很容易。其实这种框架就是根据数据来生成界面。界面的模板写好,然后只需要修改数据就好啦!


比如我用vuejs来搞了一个简单的:

<!doctype html>
<html>
  <head>
    <script src="

    <style>
      .roomlist { float: left; }
      .room { border: 2px solid lightgreen; padding: 5px; width: 200px; }
      .clearfix { clear: both; }
      .roomnum { float: left; margin-left: 20px; }
      .status { float: right; margin-right: 20px; }
      .filter { float: left; }
    </style>
  </head>
  <body>
    <!-- 用html结合vuejs语法写好页面模板,数据改变之后,页面会自动更新! -->
    <div id="rooms">
      <div class="roomlist">
        <div class="room" v-for="room in filteredRooms">
          <div class="roomnum">{{room.num}}</div>
          <div class="status">
            <select name="status" v-model="room.status">
              <option value="已经清洁">已经清洁</option>
              <option value="正在清洁">正在清洁</option>
              <option value="没有清洁">没有清洁</option>
            </select>
          </div>
          <div class="clearfix"></div>
        </div>
      </div>
      <div class="filter">
        <div><label><input type="radio" name="showstatus" v-model="showstatus" value="" />全部</label></div>
        <div><label><input type="radio" name="showstatus" v-model="showstatus" value="已经清洁" />已经清洁</label></div>
        <div><label><input type="radio" name="showstatus" v-model="showstatus" value="正在清洁" />正在清洁</label></div>
        <div><label><input type="radio" name="showstatus" v-model="showstatus" value="没有清洁" />没有清洁</label></div>
      </div>
    </div>
    <script>
      var roomsCtrl = new Vue({
        el: '#rooms',
        data: {
          //这个就是所有房间的数据
          rooms: [
            {num: 801, status: '已经清洁'},
            {num: 802, status: '已经清洁'},
            {num: 803, status: '已经清洁'},
            {num: 804, status: '没有清洁'},
            {num: 805, status: '已经清洁'},
            {num: 806, status: '正在清洁'},
            {num: 807, status: '已经清洁'},
            {num: 808, status: '已经清洁'},
            {num: 809, status: '已经清洁'}
          ],
          //这个表示要显示哪种状态的房间,空串表示显示状态
          showstatus: ''
        },
        computed: {
          //这个用来根据showstatus过滤房间。
          filteredRooms: function() {
            var showstatus = this.showstatus;
            if (showstatus == '') { return this.rooms; }
            return this.rooms.filter(function(room) { return room.status == showstatus; });
          }
        }
      });
    </script>
  </body>
</html>

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com