• 一篇知乎的故事


    前言  

    本文的发表源于知乎的一篇文章。文章链接如下:如果你想靠前端技术还房贷,你不能连这个都不会

    前提

    1. 本文是一个vue的小组件功能,你需要有vue的经验,并且了解vue的组件。

    2. 本文会贴出一个盗版的jQuery.queue函数,这个函数是之前读jq源码自己写的,就是偷得jq,比不上jq强大,但是基本功能还是有的。

    3. 本文不适合新手。

    切入正文

    上面是问题,我们来解读一下需求:

    1. 首先要有一个模块,这个模块包括一个input,两个button

    2. 模块实现了点击 A,发送urlA请求,并将input值改为请求返回的值,点击B,雷同

    3. 用户依次点击A、B,input首先需要改为urlA请求返回的值,再改为urlB返回的值。也就类似于同步请求。

    代码如下:

    <div id="app">
        <my-component></my-component>
     </div>
    <template id="tpl">
        <div>
          <input type="text" v-model="inputData" readonly="readonly">
          <p>
    
            <button @click="request1">按钮A</button>
            <button @click="request2">按钮B</button>
          </p>
        </div>
      </template>
    
    
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    //    resource.min.js  自己下载的
    <script type="text/javascript" src="./resource.min.js"></script>
    
    <script>
      Vue.use(VueResource)
      new Vue({
        el: '#app',
        components: {
            'my-component': {
              template: '#tpl',
              data: function () {
                return {
                  inputData: '默认的',
                  ajax2: null
                }
              },
              methods: {
                request1: function () {
                  var url = '我的测试地址:睡眠2秒再返回值'
                  this.$http.get(url).then(function(res)  {
                    this.inputData = res.data
                    this.ajax2()
                  })
                },
                request2: function () {
                  this.ajax2 = function () {
                    var url = '我的测试地址:睡眠1秒返回值'
                    this.$http.get(url).then(function(res)  {
                      this.inputData = res.data
                    })
                  }
                },
              },
            }
        }
      })
    </script>

    我定义了一个vue实例,在#app元素内有效。定义个组件,给这个组件一个inputData属性存储input框中的数据,定义一个ajax2属性存储点击B按钮时的发起请求的函数。我们在点击A后返回值后,调用ajax2这个方法,这样就实现了上面的需求,当然仅仅是实现了上面的需求而已,并且代码看上去很难看,因为我们为了实现这个功能不得不在模型上加了个ajax2这个很鸡肋的中间量,为了让代码更好看一些,功能更强一些,不防试一试用队列来解决。

    队列的作用

    我们不仅要实现上面这个简单的例子,我们需要实现的效果更强壮: 

    1. 连续交替点击A、B按钮,将返回值有顺序的显示到input上面

    2. 每一次点击都会产生一个ajax请求,但是不会立刻发起,会根据点击顺序依次请求。

    3. 利用一个队列对象来实现,使代码变得更简洁更美观。

    代码如下:

      <div id="app">
        <my-component :q="q"></my-component>
      </div>
      <template id="tpl">
        <div>
          <input type="text" v-model="inputData" readonly="readonly">
          <p>
            <button @click="request('测试地址1:睡眠2秒')">按钮A</button>
            <button @click="request('测试地址2:睡眠1秒')">按钮B</button>
          </p>
        </div>
      </template>
      <script src="https://unpkg.com/vue/dist/vue.js"></script>
      <script type="text/javascript" src="./vue-resource.min.js"></script>
      <script type="text/javascript" src="http://git.oschina.net/xuazheng/myJquery/raw/master/queue/queue.js?dir=0&filepath=queue%2Fqueue.js&oid=b23c3bf7212ff41aad350bdb505a1afc59929ce6&sha=d0298a8907c9ed1cf25c176807fadbcd14c3e571"></script>
      <script type="text/javascript">
        Vue.use(VueResource)
        new Vue({
          el: '#app',
          data: {
            q: Queue()
          },
          components: {
            'my-component': {
              template: '#tpl',
              data: function () {
                return {
                  inputData: '默认的'
                }
              },
              methods: {
                request: function (url) {
                  this.q.queue('fx', function (next){
                    this.$http.get(url).then(function(res)  {
                      this.inputData = res.data
                      next()
                    })
                  }.bind(this))
                }
              },
              props: ['q']
            }, 
          }
        })
      </script>

    引入了我的queue,在vue实例上,创建一个q属性存储queue对象并传递给子组件。在子组件中,我们每次点击一个按钮,都会将一个ajax请求的函数添加到fx队列中,在jquery中,fx类型的队列存储着动画函数,可以处理异步函数队列的有序执行。不传递这个值会默认fx类型,所以也可以直接在queue方法中传递一个方法就行。

    队列的代码如下:

    ;function Queue() {
    
      // 数据缓存对象
      var cache = {};
    
      var queueList = {
        // type默认是fx,是动画队列
        queue: function(type,data) {
          var args = arguments;
          //没有参数直接返回
          if(!args.length){
            return;
          }
    
          var q = null;
          // 只有一个参数并且是个函数
          if(args.length == 1 && typeof type === 'function') {
            data = type;
            type = 'fx';
          }
    
          q = cache[type] || [];
    
          // 添加缓存
          if( data instanceof Array) {
            q = data;
          }else {
            q.push(data)
          }
          cache[type] = q;
    
          //如果是动画队列并且没有开始的动画,执行第一个动画函数
          if(type == 'fx' && q.toString().indexOf('inprogress') === -1) {
            queueList.dequeue()
          }
    
          return q;
    
        },
        dequeue: function(type) {
          var fn, queue;
            type = type || 'fx';
            queue = cache[type];
            if(queue.length == 0 ) {
              return;
            }
    
            fn = queue.shift();
    
            if( fn === 'inprogress' ) {
              fn = queue.shift();
            }
            if( fn ) {
              if(type === 'fx') {
                queue.unshift('inprogress');
              }
              fn.call(null,function() {
                queueList.dequeue(type);
              })
            } 
        },
        // 延迟使用setTimeout来实现
        delay: function(type,timeout) {
          if(!type) {
            return;
          }
          if(arguments.length == 1) {
            timeout = type;
            type = 'fx';
          }
    
          if(typeof timeout == 'number') {
            var q = cache[type];
            if(!q) {
              q = cache[type] =  [_delay];
            }else {
              q.push(_delay)
            }
    
          }
          function _delay() {
            setTimeout(queueList.dequeue, timeout);
          }
    
          return this;
    
        },
        get: function(type) {
          type = type || 'fx';
          return cache[type];
        }
      }
    
    
      return queueList;
    }

    这个就不解释了,比起jquery源码,这个代码就显得很简单,jquery中做了大量的处理,然而博主并没有那么厉害,只能简单的写了这点。有js基础的应该看得懂,如果想学jq源码,推荐 艾伦 Aaron 的博客园

    感谢阅读

  • 相关阅读:
    C#操作REDIS例子
    A C# Framework for Interprocess Synchronization and Communication
    UTF8 GBK UTF8 GB2312 之间的区别和关系
    开源项目选型问题
    Mysql命令大全——入门经典
    RAM, SDRAM ,ROM, NAND FLASH, NOR FLASH 详解(引用)
    zabbix邮件报警通过脚本来发送邮件
    centos启动提示unexpected inconsistency RUN fsck MANUALLY
    rm 或者ls 报Argument list too long
    初遇Citymaker (六)
  • 原文地址:https://www.cnblogs.com/xujiazheng/p/6413104.html
Copyright © 2020-2023  润新知