zoukankan      html  css  js  c++  java
  • 一篇知乎的故事

    前言  

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

    前提

    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 的博客园

    感谢阅读

  • 相关阅读:
    设计模式-享元模式
    设计模式-外观模式
    设计模式-桥接模式
    设计模式-适配器模式
    设计模式-代理模式
    java设计模式中用到的UML图
    VS code 初次安装配置
    CMD部分操作、BAT、以及VS SQL部分快捷键
    网络部分
    CMD 中certutil 操作命令
  • 原文地址:https://www.cnblogs.com/xujiazheng/p/6413104.html
Copyright © 2011-2022 走看看