Vue Quick 4 Hour

 

VueJS Introduction

Vue

课程介绍

image-20200919162437078

Vue 基础

Vue 简介

  1. JavaScript 框架.
    • 必须遵守一整套使用规则
  2. 简化 DOM 操作
  3. 响应式的数据驱动. (页面由数据驱动的)

image-20200919162643247

第一个 Vue 程序

创建文件 — > 引入 Vue

类似于 导包 用包

  1. 导入
  2. 再 HTML 写
  3. 再 js 里面写
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vue 基础</title>
    <!-- development version, includes helpful console warnings -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  </head>
  <body>
    <div id="app"></div>
    <script>
      var app = new Vue({
        el: "#app",
        data: {
          message: "您好!Vue!",
        },
      });
    </script>
  </body>
</html>

image-20200919163717726

#app 是 id 选择器

跑 Vue 的 hello world 总共散步

image-20200919163815292

el:挂载点

image-20200919163854552

挂在点中 的数据会从 data 中的数据更换.

问题:

  1. Vue 实例的作用范围是什么?

           
        <div id="app"></div>
    

    答案: 必须在 el 名中的元素内部.

  2. 是否可以使用其他的选择器?

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Vue 基础</title>
        <!-- development version, includes helpful console warnings -->
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
      </head>
      <body>
           
        <div class="app"></div>
        <script>
          var app = new Vue({
            el: ".app",
            data: {
              message: "您好!Vue!",
            },
          });
        </script>
      </body>
    </html>
    

    通过尝试发现是可以使用其他的选择器.

  3. 是否可以设置其他的 dom 元素呢?

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Vue 基础</title>
        <!-- development version, includes helpful console warnings -->
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
      </head>
      <body>
           
        <div class="app"></div>
        <script>
          var app = new Vue({
            el: ".app",
            data: {
              message: "您好!Vue!",
            },
          });
        </script>
      </body>
    </html>
    

    可以.

data: 数据对象

image-20200919164505149

data 里面可以 添加所有的 JavaScript 复杂的数据类型.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vue 基础</title>
    <!-- development version, includes helpful console warnings -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  </head>
  <body>
    <div id="app">
      
      <p></p>
      <p></p>
    </div>
    <script>
      var app = new Vue({
        el: "#app",
        data: {
          message: "您好!Vue!",
          organization: {
            name: "AzatAI",
            mobile: 87005201209,
          },
          university: ["KazNU", "Kimep"],
        },
      });
    </script>
  </body>
</html>

image-20200919164830686

本地应用

image-20200919164924530

  1. v-text
  2. v-html
  3. v-on
  4. v-show
  5. v-if
  6. v-bind
  7. v-for
  8. v-on
  9. v-model
  • 内容绑定, 事件绑定
    • v-text
    • v-html
    • v-on
  • 显示切换, 属性绑定
    • v-show
    • v-if
    • v-bind
  • 列表切换表单元素绑定
    • v-for
    • v-on
    • v-model

image-20200919165300440

v-text : 设置标签的文本值

<div id="app">
      <h2 v-text="message"></h2>
    </div>
<h2 v-text="message+'!'"></h2>
      <h2></h2>

v-text 可以将数据关联到标签的内部.

如果要替换部分内容,那么就要用 这种方式.

可以使用表达式

v-html 设置标签的 HTML (会渲染 HTML)

image-20200919165912804

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vue 基础</title>
    <!-- development version, includes helpful console warnings -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  </head>
  <body>
    <div id="app">
      <p v-text="content"></p>
      <p v-html="content"></p>
    </div>
    <script>
      var app = new Vue({
        el: "#app",
        data: {
          content: "AzatAI",
        },
      });
    </script>
  </body>
</html>

image-20200919170114926

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vue 基础</title>
    <!-- development version, includes helpful console warnings -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  </head>
  <body>
    <div id="app">
      <p v-text="content"></p>
      <p v-html="content"></p>
    </div>
    <script>
      var app = new Vue({
        el: "#app",
        data: {
          content: "<a href='https://azat.ai'>AzatAI</a>",
        },
      });
    </script>
  </body>
</html>

image-20200919170220580

v-on 基础: 元素绑定时间

image-20200919170444794

image-20200919170506616

image-20200919170527464

image-20200919170557319

可以使用 v-on 也可以使用@

Vue 的特点,页面由数据形成,数据改变,页面也会同时改变.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vue v-on 中绑定事件</title>
    <!-- development version, includes helpful console warnings -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  </head>
  <body>
    <div id="app">
      <button v-on:click="doAlert">v-on 绑定事件</button>
      <hr />
      <button @click="doAlert">简化形式 @</button>
      <hr />
      <button @dblclick="doAlert">绑定双击事件</button>
      <h3 @click="changeFood"></h3>
    </div>
    <script>
      var app = new Vue({
        el: "#app",
        data: {
          food: "鸡蛋炒西红柿",
        },
        methods: {
          doAlert: function () {
            alert("我被点击了!");
          },
          changeFood: function () {
            // console.log(this.food);
            this.food += "超好吃!!";
          },
        },
      });
    </script>
  </body>
</html>

2020-09-19 17.42.06

计数器应用

image-20200919174303403

  • 可以添加
  • 可以减少
  • 有最大值
  • 有最小值

image-20200919174435312

image-20200919174524875

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vue 本地应用 : 电商购物车加数器</title>
    <!-- development version, includes helpful console warnings -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  </head>
  <body>
    <div id="app" class="text-center">
      <button @click="add">+</button>
      
      <button @click="sub">-</button>
    </div>
    <script>
      var app = new Vue({
        el: "#app",
        data: {
          num: 0,
        },
        methods: {
          add: function () {
            if (this.num < 5) {
              this.num++;
            } else {
              alert("已经是最大值了!");
            }
          },
          sub: function () {
            if (this.num > 0) {
              this.num--;
            } else {
              alert("已经是最小值了!");
            }
          },
        },
      });
    </script>
  </body>
</html>

2020-09-19 18.09.47

v-show 根据表达式真假切换元素的显示

image-20200919181413229

image-20200919181449888

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>V-Show 实例</title>
    <!-- development version, includes helpful console warnings -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  </head>
  <body>
    <div id="app">
      <h2 class="text-center">本站点禁止未成年人进入!</h2>
      <hr />
      <button @click="addAge">立即成长! (目前年龄:)</button>
      <hr />
      <img v-show="this.age>=18" src="static/pornhub.jpg" alt="" />
    </div>
    <script>
      var app = new Vue({
        el: "#app",
        data: {
          age: 15,
        },
        methods: {
          addAge: function () {
            this.age++;
          },
        },
      });
    </script>
  </body>
</html>

2020-09-19 18.25.18

v-show 会使用 display 的方式来切换元素的显示状态

v-if 根据表达式真假切换元素的显示和隐藏(操纵 DOM)

image-20200919182632433

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vue v-if</title>
    <!-- development version, includes helpful console warnings -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  </head>
  <body>
    <div id="app">
      <button @click="!showContent">Toggle content</button>
      <div v-if="content"><!DOCTYPE html><html lang="en">
  <head><!-- Global site tag (gtag.js) - Google Analytics -->
	<script async src="https://www.googletagmanager.com/gtag/js?id=UA-122841074-3"></script>
	<script>
		window.dataLayer = window.dataLayer || [];
		function gtag(){dataLayer.push(arguments);}
		gtag('js', new Date());

		gtag('config', 'UA-122841074-3');
		
	</script><meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"><title>A flex intro for Quasar - I'm Azat</title>

<meta name="description" content="">
<link rel="canonical" href="http://azat.cc/2020/09/16/flexbox.html"><link rel="alternate" type="application/rss+xml" title="I'm Azat" href="/feed.xml">
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="manifest" href="/site.webmanifest">
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5">
<meta name="apple-mobile-web-app-title" content="I'm Azat">
<meta name="application-name" content="I'm Azat">
<meta name="msapplication-TileColor" content="#ffffff">
<meta name="theme-color" content="#ffffff"><link rel="stylesheet" href="/assets/css/main.css"><link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css" ><!-- start custom head snippets -->

<!-- end custom head snippets -->
<script>(function() {
  window.isArray = function(val) {
    return Object.prototype.toString.call(val) === '[object Array]';
  };
  window.isString = function(val) {
    return typeof val === 'string';
  };

  window.hasEvent = function(event) {
    return 'on'.concat(event) in window.document;
  };

  window.isOverallScroller = function(node) {
    return node === document.documentElement || node === document.body || node === window;
  };

  window.isFormElement = function(node) {
    var tagName = node.tagName;
    return tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA';
  };

  window.pageLoad = (function () {
    var loaded = false, cbs = [];
    window.addEventListener('load', function () {
      var i;
      loaded = true;
      if (cbs.length > 0) {
        for (i = 0; i < cbs.length; i++) {
          cbs[i]();
        }
      }
    });
    return {
      then: function(cb) {
        cb && (loaded ? cb() : (cbs.push(cb)));
      }
    };
  })();
})();
(function() {
  window.throttle = function(func, wait) {
    var args, result, thisArg, timeoutId, lastCalled = 0;

    function trailingCall() {
      lastCalled = new Date;
      timeoutId = null;
      result = func.apply(thisArg, args);
    }
    return function() {
      var now = new Date,
        remaining = wait - (now - lastCalled);

      args = arguments;
      thisArg = this;

      if (remaining <= 0) {
        clearTimeout(timeoutId);
        timeoutId = null;
        lastCalled = now;
        result = func.apply(thisArg, args);
      } else if (!timeoutId) {
        timeoutId = setTimeout(trailingCall, remaining);
      }
      return result;
    };
  };
})();
(function() {
  var Set = (function() {
    var add = function(item) {
      var i, data = this._data;
      for (i = 0; i < data.length; i++) {
        if (data[i] === item) {
          return;
        }
      }
      this.size ++;
      data.push(item);
      return data;
    };

    var Set = function(data) {
      this.size = 0;
      this._data = [];
      var i;
      if (data.length > 0) {
        for (i = 0; i < data.length; i++) {
          add.call(this, data[i]);
        }
      }
    };
    Set.prototype.add = add;
    Set.prototype.get = function(index) { return this._data[index]; };
    Set.prototype.has = function(item) {
      var i, data = this._data;
      for (i = 0; i < data.length; i++) {
        if (this.get(i) === item) {
          return true;
        }
      }
      return false;
    };
    Set.prototype.is = function(map) {
      if (map._data.length !== this._data.length) { return false; }
      var i, j, flag, tData = this._data, mData = map._data;
      for (i = 0; i < tData.length; i++) {
        for (flag = false, j = 0; j < mData.length; j++) {
          if (tData[i] === mData[j]) {
            flag = true;
            break;
          }
        }
        if (!flag) { return false; }
      }
      return true;
    };
    Set.prototype.values = function() {
      return this._data;
    };
    return Set;
  })();

  window.Lazyload = (function(doc) {
    var queue = {js: [], css: []}, sources = {js: {}, css: {}}, context = this;
    var createNode = function(name, attrs) {
      var node = doc.createElement(name), attr;
      for (attr in attrs) {
        if (attrs.hasOwnProperty(attr)) {
          node.setAttribute(attr, attrs[attr]);
        }
      }
      return node;
    };
    var end = function(type, url) {
      var s, q, qi, cbs, i, j, cur, val, flag;
      if (type === 'js' || type ==='css') {
        s = sources[type], q = queue[type];
        s[url] = true;
        for (i = 0; i < q.length; i++) {
          cur = q[i];
          if (cur.urls.has(url)) {
            qi = cur, val = qi.urls.values();
            qi && (cbs = qi.callbacks);
            for (flag = true, j = 0; j < val.length; j++) {
              cur = val[j];
              if (!s[cur]) {
                flag = false;
              }
            }
            if (flag && cbs && cbs.length > 0) {
              for (j = 0; j < cbs.length; j++) {
                cbs[j].call(context);
              }
              qi.load = true;
            }
          }
        }
      }
    };
    var load = function(type, urls, callback) {
      var s, q, qi, node, i, cur,
        _urls = typeof urls === 'string' ? new Set([urls]) : new Set(urls), val, url;
      if (type === 'js' || type ==='css') {
        s = sources[type], q = queue[type];
        for (i = 0; i < q.length; i++) {
          cur = q[i];
          if (_urls.is(cur.urls)) {
            qi = cur;
            break;
          }
        }
        val = _urls.values();
        if (qi) {
          callback && (qi.load || qi.callbacks.push(callback));
          callback && (qi.load && callback());
        } else {
          q.push({
            urls: _urls,
            callbacks: callback ? [callback] : [],
            load: false
          });
          for (i = 0; i < val.length; i++) {
            node = null, url = val[i];
            if (s[url] === undefined) {
              (type === 'js' ) && (node = createNode('script', { src: url }));
              (type === 'css') && (node = createNode('link', { rel: 'stylesheet', href: url }));
              if (node) {
                node.onload = (function(type, url) {
                  return function() {
                    end(type, url);
                  };
                })(type, url);
                (doc.head || doc.body).appendChild(node);
                s[url] = false;
              }
            }
          }
        }
      }
    };
    return {
      js: function(url, callback) {
        load('js', url, callback);
      },
      css: function(url, callback) {
        load('css', url, callback);
      }
    };
  })(this.document);
})();
</script><script>
  (function() {
    var TEXT_VARIABLES = {
      version: '2.2.6',
      sources: {
        font_awesome: 'https://use.fontawesome.com/releases/v5.0.13/css/all.css',
        jquery: 'https://unpkg.com/[email protected]/dist/jquery.min.js',
        leancloud_js_sdk: '//cdn.jsdelivr.net/npm/[email protected]/dist/av-min.js',
        chart: 'https://unpkg.com/[email protected]/dist/Chart.min.js',
        gitalk: {
          js: 'https://unpkg.com/[email protected]/dist/gitalk.min.js',
          css: 'https://unpkg.com/[email protected]/dist/gitalk.css'
        },
        valine: 'https//unpkg.com/valine/dist/Valine.min.js',
        mathjax: 'https://unpkg.com/[email protected]/unpacked/MathJax.js?config=TeX-MML-AM_CHTML',
        mermaid: 'https://unpkg.com/[email protected]/dist/mermaid.min.js'
      },
      site: {
        toc: {
          selectors: 'h1,h2,h3,h4'
        }
      },
      paths: {
        search_js: '/assets/search.js'
      }
    };
    window.TEXT_VARIABLES = TEXT_VARIABLES;
  })();
</script>
</head>
  <body>
    <div class="root" data-is-touch="false">
      <div class="layout--page js-page-root"><div class="page__main js-page-main page__viewport has-aside cell cell--auto">

      <div class="page__main-inner"><div class="page__header d-print-none"><header class="header"><div class="main">
      <div class="header__title">
        <div class="header__brand"><?xml version="1.0" ?><svg id="Layer_1_1_" style="enable-background:new 0 0 64 64;" version="1.1" viewBox="0 0 64 64" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g><g><path d="M25,2c-2.809,0-5.225,1.659-6.34,4.047C18.441,6.026,18.224,6,18,6c-3.866,0-7,3.134-7,7v0.422    c-1.567,0.686-2.695,2.153-2.932,3.907L8,17.29C5.108,18.151,3,20.829,3,24c0,1.347,0.387,2.601,1.047,3.669    C2.778,29.085,2,30.949,2,33c0,2.344,1.012,4.449,2.619,5.912C4.221,39.863,4,40.905,4,42c0,4.08,3.054,7.446,7,7.938l0-0.002V50    h0.378c0.714,2.021,2.457,3.553,4.621,3.917l0.015-0.184C16.011,53.823,16,53.91,16,54c0,4.418,3.582,8,8,8s8-3.582,8-8V9    C32,5.134,28.866,2,25,2z M11,37.955V38C10.99,38.027,10.992,38.005,11,37.955z" style="fill:#FFCB57;"/></g><g><path d="M39,28h-4v-2h4c0.551,0,1-0.449,1-1v-7h2v7C42,26.654,40.654,28,39,28z" style="fill:#E56565;"/></g><g><path d="M41,16c-1.654,0-3-1.346-3-3s1.346-3,3-3s3,1.346,3,3S42.654,16,41,16z M41,12    c-0.551,0-1,0.449-1,1s0.449,1,1,1s1-0.449,1-1S41.551,12,41,12z" style="fill:#E56565;"/></g><g><path d="M42,46h-2v-7c0-0.551-0.449-1-1-1h-4v-2h4c1.654,0,3,1.346,3,3V46z" style="fill:#E56565;"/></g><g><path d="M41,54c-1.654,0-3-1.346-3-3s1.346-3,3-3s3,1.346,3,3S42.654,54,41,54z M41,50    c-0.551,0-1,0.449-1,1s0.449,1,1,1s1-0.449,1-1S41.551,50,41,50z" style="fill:#E56565;"/></g><g><path d="M45,33H35v-2h10c1.654,0,3-1.346,3-3v-3h2v3C50,30.757,47.757,33,45,33z" style="fill:#E56565;"/></g><g><path d="M49,23c-1.654,0-3-1.346-3-3s1.346-3,3-3s3,1.346,3,3S50.654,23,49,23z M49,19    c-0.551,0-1,0.449-1,1s0.449,1,1,1s1-0.449,1-1S49.551,19,49,19z" style="fill:#E56565;"/></g><g><rect height="10" style="fill:#E56565;" width="2" x="48" y="36"/></g><g><rect height="16" style="fill:#E56565;" width="2" x="53" y="22"/></g><g><rect height="2" style="fill:#E56565;" width="2" x="53" y="40"/></g><g><path d="M36.782,1.367c-1.45-0.223-2.92,0.194-4.034,1.148c-0.569,0.487-1.011,1.089-1.309,1.756    C29.98,2.292,27.641,1,25,1c-2.956,0-5.536,1.615-6.921,4.006C18.053,5.005,18.026,5,18,5c-4.346,0-7.886,3.485-7.99,7.806    c-1.387,0.802-2.421,2.14-2.822,3.731C4.114,17.701,2,20.678,2,24c0,1.235,0.29,2.452,0.842,3.559C1.649,29.123,1,31.029,1,33    c0,2.306,0.891,4.511,2.461,6.175C3.166,40.064,3,41.013,3,42c0,4.444,3.26,8.214,7.621,8.886    c0.825,1.833,2.417,3.251,4.415,3.829C15.403,59.344,19.279,63,24,63c2.984,0,5.626-1.466,7.264-3.709    c0.285,0.842,0.792,1.602,1.483,2.194c0.917,0.785,2.074,1.208,3.263,1.208c0.256,0,0.514-0.02,0.771-0.06    C51.974,60.281,63,47.397,63,32S51.974,3.719,36.782,1.367z M24,61c-3.86,0-7-3.14-7-7s3.14-7,7-7v-2    c-4.492,0-8.216,3.313-8.883,7.621C13.265,51.872,12,50.078,12,48c0-2.757,2.243-5,5-5v-2c-3.86,0-7,3.14-7,7    c0,0.242,0.015,0.48,0.039,0.716C7.103,47.861,5,45.148,5,42c0-3.86,3.14-7,7-7v-2c-3.196,0-6.001,1.68-7.598,4.197    C3.501,35.995,3,34.525,3,33c0-1.718,0.636-3.374,1.792-4.664l0.499-0.557l-0.393-0.636C4.311,26.193,4,25.106,4,24    c0-2.179,1.215-4.158,3.058-5.208C7.448,21.727,9.961,24,13,24v-2c-2.206,0-4-1.794-4-4s1.794-4,4-4s4,1.794,4,4h2    c0-3.309-2.691-6-6-6c-0.314,0-0.62,0.032-0.922,0.078c0.408-2.627,2.521-4.693,5.172-5.026C17.093,7.677,17,8.327,17,9    c0,4.411,3.589,8,8,8v-2c-3.309,0-6-2.691-6-6s2.691-6,6-6s6,2.691,6,6v45C31,57.86,27.86,61,24,61z M36.475,60.657    c-0.871,0.138-1.756-0.117-2.426-0.69C33.382,59.395,33,58.564,33,57.688V6.312c0-0.877,0.382-1.708,1.049-2.279    c0.551-0.472,1.248-0.726,1.963-0.726c0.154,0,0.309,0.012,0.464,0.036C50.457,5.508,61,17.828,61,32S50.457,58.492,36.475,60.657    z" style="fill:#3F3A34;"/><rect height="2" style="fill:#3F3A34;" width="2" x="25" y="8"/><rect height="2" style="fill:#3F3A34;" width="2" x="20" y="31"/><rect height="2" style="fill:#3F3A34;" width="2" x="26" y="53"/><rect height="2" style="fill:#3F3A34;" width="2" x="9" y="38"/><rect height="2" style="fill:#3F3A34;" width="2" x="27" y="24"/><rect height="2" style="fill:#3F3A34;" width="2" x="8" y="26"/></g></g></svg><a title="Tech and Finance Plus Education.
" href="/">I'm Azat</a></div><button class="button button--secondary button--circle search-button js-search-toggle"><i class="fas fa-search"></i></button></div><nav class="navigation">
        <ul><li class="navigation__item"><a href="/archive.html">Archive</a></li><li class="navigation__item"><a href="/about.html">About</a></li><li><button class="button button--secondary button--circle search-button js-search-toggle"><i class="fas fa-search"></i></button></li></ul>
      </nav></div>
  </header>
</div><div class="page__content"><div class ="main"><div class="grid grid--reverse">

              <div class="col-aside d-print-none js-col-aside"><aside class="page__aside js-page-aside"><div class="toc-aside js-toc-root"></div>
</aside></div>

              <div class="col-main cell cell--auto"><!-- start custom main top snippet -->

<!-- end custom main top snippet -->
<article itemscope itemtype="http://schema.org/Article"><div class="article__header"><header><h1>A flex intro for Quasar</h1></header><span class="split-space">&nbsp;</span>
          <a class="edit-on-github"
            title="Edit on Github"
            href="https://github.com/azataiot/Blog/tree/master/_posts/2020-09-16-flexbox.md">
            <i class="far fa-edit"></i></a></div><meta itemprop="headline" content="A flex intro for Quasar"><div class="article__info clearfix"><ul class="left-col menu"><li>
              <a class="button button--secondary button--pill button--sm"
                href="/archive.html?tag=Flexbox">Flexbox</a>
            </li><li>
              <a class="button button--secondary button--pill button--sm"
                href="/archive.html?tag=Javascript">Javascript</a>
            </li><li>
              <a class="button button--secondary button--pill button--sm"
                href="/archive.html?tag=Frontend">Frontend</a>
            </li><li>
              <a class="button button--secondary button--pill button--sm"
                href="/archive.html?tag=CSS">CSS</a>
            </li><li>
              <a class="button button--secondary button--pill button--sm"
                href="/archive.html?tag=Quasar">Quasar</a>
            </li></ul><ul class="right-col menu"><li><i class="far fa-calendar-alt"></i> <span>Sep 16, 2020</span>
            </li></ul></div><meta itemprop="author" content="Azat"/><meta itemprop="datePublished" content="2020-09-16T00:00:00+03:00">
    <meta itemprop="keywords" content="Flexbox,Javascript,Frontend,CSS,Quasar"><div class="js-article-content"><div class="layout--article"><!-- start custom article top snippet -->

<!-- end custom article top snippet -->
<div class="article__content" itemprop="articleBody"><p><img src="https://azatai.s3.amazonaws.com/static/2020-09-16-071736.jpg" alt="CSS container box full description" /></p>

<!--more-->

<h2 id="introduction">Introduction</h2>

<p>Flexbox (upon which Quasar Flex CSS classes are based) module aims to provide a more efficient way to lay out, align and distribute space among items in a container, even when their size is unknown and/or dynamic (thus the word “flex”).</p>

<h2 id="key-concept">Key Concept</h2>

<p>Quasar Flex CSS classes apply to either the Container (Parent) or the Container’s items (Children).</p>

<p><img src="https://cdn.quasar.dev/img/flexbox-container.svg" alt="flexbox-container" /></p>

<p><img src="https://cdn.quasar.dev/img/flexbox-items.svg" alt="flexbox-items" /></p>

<h2 id="managing-parents">Managing Parents</h2>

<h3 id="setting-directions">Setting Directions</h3>

<p>One of the following CSS classes is mandatory for the parent in order for ones on the children (described in next sections) to have any effect.</p>

<p><img src="https://cdn.quasar.dev/img/flexbox-direction.svg" alt="flexbox-direction" /></p>

<table>
  <thead>
    <tr>
      <th>Class Name</th>
      <th>Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">row</code></td>
      <td>Flex Row</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">row inline</code></td>
      <td>Inline Flex Row</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">column</code></td>
      <td>Flex Cloumn</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">column inline</code></td>
      <td>Inline Flex Column</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">row reverse</code></td>
      <td>Flex row with <code class="language-plaintext highlighter-rouge">flex-direction</code> set to <code class="language-plaintext highlighter-rouge">row-reverse</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">column reverse</code></td>
      <td>Flex column with <code class="language-plaintext highlighter-rouge">flex-direction</code> se to <code class="language-plaintext highlighter-rouge">column-reverse</code></td>
    </tr>
  </tbody>
</table>

<p><img src="https://azatai.s3.amazonaws.com/static/2020-09-16-073552.gif" alt="img" /></p>

<table>
  <tbody>
    <tr>
      <td>![Como o Flexbox funciona— explicado com gifs grandes e coloridos</td>
      <td>by Lucas  J S</td>
      <td>Medium](https://azatai.s3.amazonaws.com/static/2020-09-16-073507.gif)</td>
    </tr>
  </tbody>
</table>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"row"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;div&gt;</span>First column<span class="nt">&lt;/div&gt;</span>
  <span class="nt">&lt;div&gt;</span>Second column<span class="nt">&lt;/div&gt;</span>
  <span class="nt">&lt;div&gt;</span>Third column<span class="nt">&lt;/div&gt;</span>
<span class="nt">&lt;/div&gt;</span>
</code></pre></div></div>

<p><img src="https://azatai.s3.amazonaws.com/static/2020-09-16-074148.png" alt="image-20200916134147731" /></p>

<h3 id="wrapping-by-default">Wrapping by Default</h3>

<p>By default, all rows and columns wrap their content.</p>

<p><img src="https://cdn.quasar.dev/img/flexbox-wrap.svg" alt="img" /></p>

<p><img src="https://azatai.s3.amazonaws.com/static/2020-09-16-074235.gif" alt="img" /></p>

<p>However if you explicitly do not want to wrap and by so doing you want to fit all content into one line, then add <code class="language-plaintext highlighter-rouge">no-wrap</code> CSS helper class.</p>

<p>Also, if you want to wrap in reverse order, then <code class="language-plaintext highlighter-rouge">reverse-wrap</code> is available.</p>

<table>
  <thead>
    <tr>
      <th>Class Name</th>
      <th>Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">wrap</code></td>
      <td>Wrap if necessary (“on” by default, no need to specify it)</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">o-wrap</code></td>
      <td>Do NOT wrap even if necessary</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">reverse-wrap</code></td>
      <td>Wrap backwards if necessary</td>
    </tr>
  </tbody>
</table>

<h3 id="alignment">Alignment</h3>

<p><img src="https://azatai.s3.amazonaws.com/static/2020-09-16-074440.png" alt="img" /></p>

<p><strong>For alignment along the main axis</strong>, use classes below. It helps distribute left over free space when either all the flex items on a line are inflexible, or are flexible but have reached their maximum size. It also exerts some control over the alignment of items when they overflow the line.</p>

<p><img src="https://cdn.quasar.dev/img/flexbox-main-axis-align---2.svg" alt="flexbox-main-axis-align---2" /></p>

<p><img src="https://azatai.s3.amazonaws.com/static/2020-09-16-074648.gif" alt="img" /></p>

<p><strong>For alignment perpendicular to the main axis</strong>, use classes below. This defines the default behavior for how flex items are laid out along the cross axis on the current line. Think of it as the horizontal-* version for the cross-axis (perpendicular to the main-axis).</p>

<p><img src="https://cdn.quasar.dev/img/flexbox-cross-axis-align.svg" alt="flexbox-cross-axis-align" /></p>

<p><img src="https://azatai.s3.amazonaws.com/static/2020-09-16-074827.gif" alt="img" /></p>

<p>The next classes <strong>align a flex container’s lines</strong> within when there is extra space in the cross-axis, similar to how horizontal-* aligns individual items within the main-axis.</p>

<p><img src="https://cdn.quasar.dev/img/flexbox-content-align.svg" alt="img" /></p>

<h2 id="managing-children">Managing Children</h2>

<h3 id="distribution-of-size">Distribution of Size</h3>

<p>Quasar uses a 12 point column system for distributing the size of row children. Here are some examples of the available CSS helper classes:</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"row"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col-8"</span><span class="nt">&gt;</span>two thirds<span class="nt">&lt;/div&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col-2"</span><span class="nt">&gt;</span>one sixth<span class="nt">&lt;/div&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col-auto"</span><span class="nt">&gt;</span>auto size based on content and available space<span class="nt">&lt;/div&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col"</span><span class="nt">&gt;</span>fills remaining available space<span class="nt">&lt;/div&gt;</span>
<span class="nt">&lt;/div&gt;</span>
</code></pre></div></div>

<p><img src="https://azatai.s3.amazonaws.com/static/2020-09-16-075615.png" alt="image-20200916135615337" /></p>

<p><img src="https://azatai.s3.amazonaws.com/static/2020-09-16-075528.jpg" alt="Foundation 6: The New Flex Grid - SitePoint" /></p>

<p>In the example above, <code class="language-plaintext highlighter-rouge">col-8</code> fills two thirds (2/3) of the row width, because 8/12 = 2/3 = 66%, while <code class="language-plaintext highlighter-rouge">col-2</code> occupies one sixth (2/12 = 1/6 ~ 16.67%).</p>

<p>CSS helper class <code class="language-plaintext highlighter-rouge">col-auto</code> makes the cell fill only the space it needs to be rendered. <code class="language-plaintext highlighter-rouge">col</code>, on the other hand, tries to fill all space available while also shrinking if needed.</p>

<p>CSS helper class <code class="language-plaintext highlighter-rouge">col-grow</code> makes the cell fill at least the space it needs to be rendered, with the possibility to grow when more space is available.</p>

<p>CSS helper class <code class="language-plaintext highlighter-rouge">col-shrink</code> makes the cell fill at most the space it needs to be rendered, with the possibility to shrink when not enough space is available.</p>

<p>Another example with a visual representation below it:</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"row"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col"</span><span class="nt">&gt;</span>1<span class="nt">&lt;/div&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col"</span><span class="nt">&gt;</span>1<span class="nt">&lt;/div&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col"</span><span class="nt">&gt;</span>1<span class="nt">&lt;/div&gt;</span>
  <span class="c">&lt;!--
     we have 3 children, so equivalent
     to above would be to use `col-4`
     on each of the children
  --&gt;</span>
<span class="nt">&lt;/div&gt;</span>

<span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"row"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col-3"</span><span class="nt">&gt;</span>1<span class="nt">&lt;/div&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col-6"</span><span class="nt">&gt;</span>2<span class="nt">&lt;/div&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col-3"</span><span class="nt">&gt;</span>1<span class="nt">&lt;/div&gt;</span>
<span class="nt">&lt;/div&gt;</span>
</code></pre></div></div>

<p><img src="https://cdn.quasar.dev/img/flexbox-grow.svg" alt="flexbox-grow" /></p>

<p>It is also possible to offset a cell. For example: <code class="language-plaintext highlighter-rouge">offset-4</code> offsets a third of space (4/12 = 1/3 = 33%).</p>

<h3 id="wrapping">Wrapping</h3>

<p>Wrapping is a key feature in understanding Flex CSS classes. You are not bound to use exactly 12 points per row. You can use less or even more.</p>

<p>This allows you, among other things, to dynamically stack rows vertically on smaller screens while displaying them on a single line on bigger screens. Read the “Responsive Design” section.</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"row"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col-2"</span><span class="nt">&gt;</span>...<span class="nt">&lt;/div&gt;</span>

  <span class="c">&lt;!-- 2 + 6 &lt; 12, so next element is placed on same line --&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col-6"</span><span class="nt">&gt;</span>...<span class="nt">&lt;/div&gt;</span>

  <span class="c">&lt;!-- 2 + 6 + 10 &gt; 12, so next element wraps to next line --&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col-10"</span><span class="nt">&gt;</span>...<span class="nt">&lt;/div&gt;</span>

  <span class="c">&lt;!--
    10 + 3 &gt; 12, so next element wraps to next line.
    Note that we take into consideration the current line only
    (with col-10 only, since it was wrapped to its own line).
  --&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col-3"</span><span class="nt">&gt;</span>...<span class="nt">&lt;/div&gt;</span>
<span class="nt">&lt;/div&gt;</span>
</code></pre></div></div>

<p>Note that rows are wrappable by default. Should you wish to disable this, use the <code class="language-plaintext highlighter-rouge">no-wrap</code> CSS helper class.</p>

<h3 id="self-alignment">Self Alignment</h3>

<p><strong>An item can override the aligned specified on parent</strong>. This allows alignment to be overridden for individual flex items. Please see the “Alignment” explanation from “Managing Parent” to understand the available values (<code class="language-plaintext highlighter-rouge">self-start</code>, <code class="language-plaintext highlighter-rouge">self-center</code>, <code class="language-plaintext highlighter-rouge">self-baseline</code>, <code class="language-plaintext highlighter-rouge">self-end</code>, <code class="language-plaintext highlighter-rouge">self-stretch</code>).</p>

<p><img src="https://cdn.quasar.dev/img/flexbox-self.svg" alt="img" /></p>

<p><img src="https://azatai.s3.amazonaws.com/static/2020-09-16-081110.gif" alt="img" /></p>

<h3 id="order">Order</h3>

<p><strong>You can set the order</strong> of child elements by using <code class="language-plaintext highlighter-rouge">order-first</code> and <code class="language-plaintext highlighter-rouge">order-last</code> CSS helper classes.</p>

<p>By default, flex items are laid out in source order. However, the order property controls the order in which they appear in the flex container. If you need more granularity, use <code class="language-plaintext highlighter-rouge">order</code> CSS property and assign the desired value.</p>

<p>Example:</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"row"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">style=</span><span class="s">"order: 2"</span><span class="nt">&gt;</span>Second column<span class="nt">&lt;/div&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"order-last"</span><span class="nt">&gt;</span>Third column<span class="nt">&lt;/div&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"order-first"</span><span class="nt">&gt;</span>First column<span class="nt">&lt;/div&gt;</span>
<span class="nt">&lt;/div&gt;</span>
</code></pre></div></div>

<p>Here is how the CSS <code class="language-plaintext highlighter-rouge">order</code> property works:</p>

<p><img src="https://cdn.quasar.dev/img/flexbox-order.svg" alt="img" /></p>

<h2 id="responsive-design">Responsive Design</h2>

<p>Quasar Flex CSS classes can be applied based on the width of the screen, to help you in making a responsive UI. The 12 points grid is inspired by Bootstrap’s, so there are a lot of similarities.</p>

<p>What we’ve learned so far is that, for example, we can size the columns regardless of window width. If we are to create a responsive UI, we need to dynamically change the sizing while taking window width into account. First, let’s learn about some tokens that you can inject in middle of <code class="language-plaintext highlighter-rouge">col-*</code>, <code class="language-plaintext highlighter-rouge">offset-*</code> and <code class="language-plaintext highlighter-rouge">col-auto</code> helper classes (look at table below for tokens).</p>

<table>
  <thead>
    <tr>
      <th>Token</th>
      <th>Max windows width</th>
      <th>Description / When it applies</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">xs</code></td>
      <td>599px</td>
      <td>Extra small sized window</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">sm</code></td>
      <td>1023px</td>
      <td>Small sized window</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">md</code></td>
      <td>1439px</td>
      <td>Medium-sized window</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">lg</code></td>
      <td>1919px</td>
      <td>Large sized window</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">xl</code></td>
      <td>Infinite</td>
      <td>Extra large sized window</td>
    </tr>
  </tbody>
</table>

<p>Example: <code class="language-plaintext highlighter-rouge">col-md-7</code>, <code class="language-plaintext highlighter-rouge">offset-lg-3</code>, <code class="language-plaintext highlighter-rouge">col-xs-auto</code>.</p>

<p>A full example: let’s say we have a row with three children. In extra small windows, we need to stack the children vertically, In small windows we need to display them side by side (each having equal width), and starting with medium windows we should display them all on same line:</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"row"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col-xs-12 col-sm-6 col-md-4"</span><span class="nt">&gt;</span>
    col
  <span class="nt">&lt;/div&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col-xs-12 col-sm-6 col-md-4"</span><span class="nt">&gt;</span>
    col
  <span class="nt">&lt;/div&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col-xs-12 col-sm-6 col-md-4"</span><span class="nt">&gt;</span>
    col
  <span class="nt">&lt;/div&gt;</span>
<span class="nt">&lt;/div&gt;</span>
</code></pre></div></div>

<p>Notice in the above example that we used <code class="language-plaintext highlighter-rouge">col-xs-12</code> (12/12 = 100% of row, so each child will take full width of the container making all children stack vertically, since rows wrap content by default), <code class="language-plaintext highlighter-rouge">col-sm-6</code> (6/12 = 50% of row) and <code class="language-plaintext highlighter-rouge">col-md-4</code> (4/12 = 33% of row).</p>

<p>Like previously mentioned, rows wrap content by default, so when 12 (or more) grid points are used for a row, content is wrapped to the next line. If we have two <code class="language-plaintext highlighter-rouge">&lt;div&gt;</code>s and we use <code class="language-plaintext highlighter-rouge">col-8</code> on both, they will also stack, since 8 + 8 = 16 and we can only display 12 points on a single line.</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"row"</span><span class="nt">&gt;</span>
  <span class="c">&lt;!--
    more than 12 grid points together,
    so second &lt;div&gt; will wrap on next line
  --&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col-8"</span><span class="nt">&gt;</span>col<span class="nt">&lt;/div&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col-8"</span><span class="nt">&gt;</span>col<span class="nt">&lt;/div&gt;</span>
<span class="nt">&lt;/div&gt;</span>
</code></pre></div></div>

<p>Also check <a href="https://quasar.dev/style/visibility#Window-Width-Related">Visibility</a> Style page to see thresholds on window width and these tokens (xs, sm, md, lg, xl) used on their own to hide or show DOM elements.</p>

</div><section class="article__sharing d-print-none"></section><div class="d-print-none"><footer class="article__footer"><span>Last updated
      <time itemprop="dateModified" datetime="2020-09-16T00:00:00+03:00">Sep 16, 2020</time>
    </span><!-- start custom article footer snippet -->

<!-- end custom article footer snippet -->
<div class="article__subscribe"><div class="subscribe"><i class="fas fa-rss"></i> <a type="application/rss+xml" href="/feed.xml">Subscribe</a></div>
</div><div class="article__license"><div class="license">
    <p>This work is licensed under a <a itemprop="license" rel="license" href="https://creativecommons.org/licenses/by-nc/4.0/">Attribution-NonCommercial 4.0 International</a> license.
      <a rel="license" href="https://creativecommons.org/licenses/by-nc/4.0/">
        <img alt="Attribution-NonCommercial 4.0 International" src="https://i.creativecommons.org/l/by-nc/4.0/88x31.png" />
      </a>
    </p>
  </div></div></footer>
<div class="article__section-navigator clearfix"><div class="previous"><span>PREVIOUS</span><a href="/2020/09/11/Codeguru-Quasar-Tuto.html">Codeguru Quasar Tuto</a></div><div class="next"><span>NEXT</span><a href="/2020/09/19/quick-vue.html">Vue Quick 4 Hour</a></div></div></div>

</div>

<script>(function() {
  var SOURCES = window.TEXT_VARIABLES.sources;
  window.Lazyload.js(SOURCES.jquery, function() {
    $(function() {
      var $this ,$scroll;
      var $articleContent = $('.js-article-content');
      var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
      var scroll = hasSidebar ? '.js-page-main' : 'html, body';
      $scroll = $(scroll);

      $articleContent.find('.highlight').each(function() {
        $this = $(this);
        $this.attr('data-lang', $this.find('code').attr('data-lang'));
      });
      $articleContent.find('h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]').each(function() {
        $this = $(this);
        $this.append($('<a class="anchor d-print-none" aria-hidden="true"></a>').html('<i class="fas fa-anchor"></i>'));
      });
      $articleContent.on('click', '.anchor', function() {
        $scroll.scrollToAnchor('#' + $(this).parent().attr('id'), 400);
      });
    });
  });
})();
</script>
</div><section class="page__comments d-print-none"><div id="disqus_thread"></div>
  <script>
  /**
  *  RECOMMENDED CONFIGURATION VARIABLES: EDIT AND UNCOMMENT THE SECTION BELOW TO INSERT DYNAMIC VALUES FROM YOUR PLATFORM OR CMS.
  *  LEARN WHY DEFINING THESE VARIABLES IS IMPORTANT: https://disqus.com/admin/universalcode/#configuration-variables*/
  var disqus_config = function () {
    this.page.url = 'http://azat.cc/2020/09/16/flexbox.html';
    this.page.identifier = 'flex000';
  };
  (function() { // DON'T EDIT BELOW THIS LINE
    var d = document, s = d.createElement('script');
    s.src = 'https://im-azat.disqus.com/embed.js';
    s.setAttribute('data-timestamp', +new Date());
    (d.head || d.body).appendChild(s);
  })();
  </script>
  <noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript></section></article><!-- start custom main bottom snippet -->

<!-- end custom main bottom snippet -->
</div>
            </div></div></div><div class="page__footer d-print-none">
<footer class="footer py-4 js-page-footer">
  <div class="main"><div itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Azat"><meta itemprop="url" content="https://azat.ai"><meta itemprop="description" content="I am Azat. Azat in mind, Azat in heart. (Azat means free or freedom by the way)."><div class="footer__author-links"><div class="author-links">
  <ul class="menu menu--nowrap menu--inline"><link itemprop="url" href="https://azat.ai"><li title="Follow me on Twitter.">
        <a class="button button--circle twitter-button" itemprop="sameAs" href="https://twitter.com/azataiot" target="_blank">
          <div class="icon"><svg fill="#000000" width="24px" height="24px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <path d="M1024.032 194.432c-37.664 16.704-78.176 28-120.672 33.088 43.36-26.016 76.672-67.168 92.384-116.224-40.608 24.064-85.568 41.568-133.408 50.976-38.336-40.832-92.928-66.336-153.344-66.336-116.032 0-210.08 94.048-210.08 210.08 0 16.48 1.856 32.512 5.44 47.872-174.592-8.768-329.408-92.416-433.024-219.52-18.08 31.04-28.448 67.104-28.448 105.632 0 72.896 37.088 137.184 93.472 174.88-34.432-1.088-66.816-10.528-95.168-26.272-0.032 0.864-0.032 1.76-0.032 2.656 0 101.792 72.416 186.688 168.512 205.984-17.632 4.8-36.192 7.36-55.36 7.36-13.536 0-26.688-1.312-39.52-3.776 26.72 83.456 104.32 144.192 196.256 145.888-71.904 56.352-162.496 89.92-260.928 89.92-16.96 0-33.664-0.992-50.112-2.944 92.96 59.616 203.392 94.4 322.048 94.4 386.432 0 597.728-320.128 597.728-597.76 0-9.12-0.192-18.176-0.608-27.168 41.056-29.632 76.672-66.624 104.832-108.736z" />
</svg>
</div>
        </a>
      </li><li title="Follow me on Linkedin.">
        <a class="button button--circle linkedin-button" itemprop="sameAs" href="https://www.linkedin.com/in/azataiot" target="_blank">
          <div class="icon"><svg fill="#000000" width="24px" height="24px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <path d="M260.096 155.648c0 27.307008-9.899008 50.516992-29.696 69.632-19.796992 19.115008-45.396992 28.672-76.8 28.672-30.036992 0-54.612992-9.556992-73.728-28.672-19.115008-19.115008-28.672-42.324992-28.672-69.632 0-28.672 9.556992-52.224 28.672-70.656 19.115008-18.432 44.372992-27.648 75.776-27.648 31.403008 0 56.32 9.216 74.752 27.648 18.432 18.432 28.331008 41.984 29.696 70.656 0 0 0 0 0 0m-202.752 808.96c0 0 0-632.832 0-632.832 0 0 196.608 0 196.608 0 0 0 0 632.832 0 632.832 0 0-196.608 0-196.608 0 0 0 0 0 0 0m313.344-430.08c0-58.708992-1.364992-126.292992-4.096-202.752 0 0 169.984 0 169.984 0 0 0 10.24 88.064 10.24 88.064 0 0 4.096 0 4.096 0 40.96-68.267008 105.812992-102.4 194.56-102.4 68.267008 0 123.220992 22.868992 164.864 68.608 41.643008 45.739008 62.464 113.664 62.464 203.776 0 0 0 374.784 0 374.784 0 0-196.608 0-196.608 0 0 0 0-350.208 0-350.208 0-91.476992-33.451008-137.216-100.352-137.216-47.787008 0-81.236992 24.576-100.352 73.728-4.096 8.192-6.144 24.576-6.144 49.152 0 0 0 364.544 0 364.544 0 0-198.656 0-198.656 0 0 0 0-430.08 0-430.08 0 0 0 0 0 0" />
</svg>
</div>
        </a>
      </li><li title="Follow me on Github.">
        <a class="button button--circle github-button" itemprop="sameAs" href="https://github.com/azataiot" target="_blank">
          <div class="icon"><svg fill="#000000" width="24px" height="24px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <path class="svgpath" data-index="path_0" fill="#272636" d="M0 525.2c0 223.6 143.3 413.7 343 483.5 26.9 6.8 22.8-12.4 22.8-25.4l0-88.7c-155.3 18.2-161.5-84.6-172-101.7-21.1-36-70.8-45.2-56-62.3 35.4-18.2 71.4 4.6 113.1 66.3 30.2 44.7 89.1 37.2 119 29.7 6.5-26.9 20.5-50.9 39.7-69.6C248.8 728.2 181.7 630 181.7 513.2c0-56.6 18.7-108.7 55.3-150.7-23.3-69.3 2.2-128.5 5.6-137.3 66.5-6 135.5 47.6 140.9 51.8 37.8-10.2 80.9-15.6 129.1-15.6 48.5 0 91.8 5.6 129.8 15.9 12.9-9.8 77-55.8 138.8-50.2 3.3 8.8 28.2 66.7 6.3 135 37.1 42.1 56 94.6 56 151.4 0 117-67.5 215.3-228.8 243.7 26.9 26.6 43.6 63.4 43.6 104.2l0 128.8c0.9 10.3 0 20.5 17.2 20.5C878.1 942.4 1024 750.9 1024 525.3c0-282.9-229.3-512-512-512C229.1 13.2 0 242.3 0 525.2L0 525.2z" />
</svg>
</div>
        </a>
      </li></ul>
</div>
</div>
    </div><div class="site-info mt-2">
      <div>© I'm Azat 2024 All rights Reserved.
<!--         Powered by <a title="Jekyll is a simple, blog-aware, static site generator." href="http://jekyllrb.com/">Jekyll</a> & <a -->
<!--         title="TeXt is a super customizable Jekyll theme." href="https://github.com/kitian616/jekyll-TeXt-theme">TeXt Theme</a>. -->
      </div>
    </div>
  </div>
</footer>
</div></div>
    </div><script>(function() {
  var SOURCES = window.TEXT_VARIABLES.sources;
  window.Lazyload.js(SOURCES.jquery, function() {
    var $body = $('body'), $window = $(window);
    var $pageRoot = $('.js-page-root'), $pageMain = $('.js-page-main');
    var activeCount = 0;
    function modal(options) {
      var $root = this, visible, onChange, hideWhenWindowScroll = false;
      var scrollTop;
      function setOptions(options) {
        var _options = options || {};
        visible = _options.initialVisible === undefined ? false : show;
        onChange = _options.onChange;
        hideWhenWindowScroll = _options.hideWhenWindowScroll;
      }
      function init() {
        setState(visible);
      }
      function setState(isShow) {
        if (isShow === visible) {
          return;
        }
        visible = isShow;
        if (visible) {
          activeCount++;
          scrollTop = $(window).scrollTop() || $pageMain.scrollTop();
          $root.addClass('modal--show');
          $pageMain.scrollTop(scrollTop);
          activeCount === 1 && ($pageRoot.addClass('show-modal'), $body.addClass('of-hidden'));
          hideWhenWindowScroll && window.hasEvent('touchstart') && $window.on('scroll', hide);
          $window.on('keyup', handleKeyup);
        } else {
          activeCount > 0 && activeCount--;
          $root.removeClass('modal--show');
          $window.scrollTop(scrollTop);
          activeCount === 0 && ($pageRoot.removeClass('show-modal'), $body.removeClass('of-hidden'));
          hideWhenWindowScroll && window.hasEvent('touchstart') && $window.off('scroll', hide);
          $window.off('keyup', handleKeyup);
        }
        onChange && onChange(visible);
      }
      function show() {
        setState(true);
      }
      function hide() {
        setState(false);
      }
      function handleKeyup(e) {
        // Char Code: 27  ESC
        if (e.which ===  27) {
          hide();
        }
      }
      setOptions(options);
      init();
      return {
        show: show,
        hide: hide,
        $el: $root
      };
    }
    $.fn.modal = modal;
  });
})();
</script><div class="modal modal--overflow page__search-modal d-print-none js-page-search-modal"><script>
(function () {
  var SOURCES = window.TEXT_VARIABLES.sources;
  window.Lazyload.js(SOURCES.jquery, function() {
    // search panel
    var search = (window.search || (window.search = {}));
    var useDefaultSearchBox = window.useDefaultSearchBox === undefined ?
      true : window.useDefaultSearchBox ;

    var $searchModal = $('.js-page-search-modal');
    var $searchToggle = $('.js-search-toggle');
    var searchModal = $searchModal.modal({ onChange: handleModalChange, hideWhenWindowScroll: true });
    var modalVisible = false;
    search.searchModal = searchModal;

    var $searchBox = null;
    var $searchInput = null;
    var $searchClear = null;

    function getModalVisible() {
      return modalVisible;
    }
    search.getModalVisible = getModalVisible;

    function handleModalChange(visible) {
      modalVisible = visible;
      if (visible) {
        search.onShow && search.onShow();
        useDefaultSearchBox && $searchInput[0] && $searchInput[0].focus();
      } else {
        search.onShow && search.onHide();
        useDefaultSearchBox && $searchInput[0] && $searchInput[0].blur();
        setTimeout(function() {
          useDefaultSearchBox && ($searchInput.val(''), $searchBox.removeClass('not-empty'));
          search.clear && search.clear();
          window.pageAsideAffix && window.pageAsideAffix.refresh();
        }, 400);
      }
    }

    $searchToggle.on('click', function() {
      modalVisible ? searchModal.hide() : searchModal.show();
    });
    // Char Code: 83  S, 191 /
    $(window).on('keyup', function(e) {
      if (!modalVisible && !window.isFormElement(e.target || e.srcElement) && (e.which === 83 || e.which === 191)) {
        modalVisible || searchModal.show();
      }
    });

    if (useDefaultSearchBox) {
      $searchBox = $('.js-search-box');
      $searchInput = $searchBox.children('input');
      $searchClear = $searchBox.children('.js-icon-clear');
      search.getSearchInput = function() {
        return $searchInput.get(0);
      };
      search.getVal = function() {
        return $searchInput.val();
      };
      search.setVal = function(val) {
        $searchInput.val(val);
      };

      $searchInput.on('focus', function() {
        $(this).addClass('focus');
      });
      $searchInput.on('blur', function() {
        $(this).removeClass('focus');
      });
      $searchInput.on('input', window.throttle(function() {
        var val = $(this).val();
        if (val === '' || typeof val !== 'string') {
          search.clear && search.clear();
        } else {
          $searchBox.addClass('not-empty');
          search.onInputNotEmpty && search.onInputNotEmpty(val);
        }
      }, 400));
      $searchClear.on('click', function() {
        $searchInput.val(''); $searchBox.removeClass('not-empty');
        search.clear && search.clear();
      });
    }
  });
})();
</script><div class="search search--dark">
  <div class="main">
    <div class="search__header">Search</div>
    <div class="search-bar">
      <div class="search-box js-search-box">
        <div class="search-box__icon-search"><i class="fas fa-search"></i></div>
        <input type="text" />
        <div class="search-box__icon-clear js-icon-clear">
          <a><i class="fas fa-times"></i></a>
        </div>
      </div>
      <button class="button button--theme-dark button--pill search__cancel js-search-toggle">
        Cancel</button>
    </div>
    <div class="search-result js-search-result"></div>
  </div>
</div>
<script>var SOURCES = window.TEXT_VARIABLES.sources;
var PAHTS = window.TEXT_VARIABLES.paths;
window.Lazyload.js([SOURCES.jquery, PAHTS.search_js], function() {
  var search = (window.search || (window.search = {}));
  var searchData = window.TEXT_SEARCH_DATA || {};

  function memorize(f) {
    var cache = {};
    return function () {
      var key = Array.prototype.join.call(arguments, ',');
      if (key in cache) return cache[key];
      else return cache[key] = f.apply(this, arguments);
    };
  }

  /// search
  function searchByQuery(query) {
    var i, j, key, keys, cur, _title, result = {};
    keys = Object.keys(searchData);
    for (i = 0; i < keys.length; i++) {
      key = keys[i];
      for (j = 0; j < searchData[key].length; j++) {
        cur = searchData[key][j], _title = cur.title;
        if ((result[key] === undefined || result[key] && result[key].length < 4 )
          && _title.toLowerCase().indexOf(query.toLowerCase()) >= 0) {
          if (result[key] === undefined) {
            result[key] = [];
          }
          result[key].push(cur);
        }
      }
    }
    return result;
  }

  var renderHeader = memorize(function(header) {
    return $('<p class="search-result__header">' + header + '</p>');
  });

  var renderItem = function(index, title, url) {
    return $('<li class="search-result__item" data-index="' + index + '"><a class="button" href="' + url + '">' + title + '</a></li>');
  };

  function render(data) {
    if (!data) { return null; }
    var $root = $('<ul></ul>'), i, j, key, keys, cur, itemIndex = 0;
    keys = Object.keys(data);
    for (i = 0; i < keys.length; i++) {
      key = keys[i];
      $root.append(renderHeader(key));
      for (j = 0; j < data[key].length; j++) {
        cur = data[key][j];
        $root.append(renderItem(itemIndex++, cur.title, cur.url));
      }
    }
    return $root;
  }

  // search box
  var $result = $('.js-search-result'), $resultItems;
  var lastActiveIndex, activeIndex;

  function clear() {
    $result.html(null);
    $resultItems = $('.search-result__item'); activeIndex = 0;
  }
  function onInputNotEmpty(val) {
    $result.html(render(searchByQuery(val)));
    $resultItems = $('.search-result__item'); activeIndex = 0;
    $resultItems.eq(0).addClass('active');
  }

  search.clear = clear;
  search.onInputNotEmpty = onInputNotEmpty;

  function updateResultItems() {
    lastActiveIndex >= 0 && $resultItems.eq(lastActiveIndex).removeClass('active');
    activeIndex >= 0 && $resultItems.eq(activeIndex).addClass('active');
  }

  function moveActiveIndex(direction) {
    var itemsCount = $resultItems ? $resultItems.length : 0;
    if (itemsCount > 1) {
      lastActiveIndex = activeIndex;
      if (direction === 'up') {
        activeIndex = (activeIndex - 1 + itemsCount) % itemsCount;
      } else if (direction === 'down') {
        activeIndex = (activeIndex + 1 + itemsCount) % itemsCount;
      }
      updateResultItems();
    }
  }

  // Char Code: 13  Enter, 37  ⬅, 38  ⬆, 39  ➡, 40  ⬇
  $(window).on('keyup', function(e) {
    var modalVisible = search.getModalVisible && search.getModalVisible();
    if (modalVisible) {
      if (e.which === 38) {
        modalVisible && moveActiveIndex('up');
      } else if (e.which === 40) {
        modalVisible && moveActiveIndex('down');
      } else if (e.which === 13) {
        modalVisible && $resultItems && activeIndex >= 0 && $resultItems.eq(activeIndex).children('a')[0].click();
      }
    }
  });

  $result.on('mouseover', '.search-result__item > a', function() {
    var itemIndex = $(this).parent().data('index');
    itemIndex >= 0 && (lastActiveIndex = activeIndex, activeIndex = itemIndex, updateResultItems());
  });
});
</script>
</div></div>


<script>(function() {
  var SOURCES = window.TEXT_VARIABLES.sources;
  window.Lazyload.js(SOURCES.jquery, function() {
    function scrollToAnchor(anchor, duration, callback) {
      var $root = this;
      $root.animate({ scrollTop: $(anchor).position().top }, duration, function() {
        window.history.replaceState(null, '', window.location.href.split('#')[0] + anchor);
        callback && callback();
      });
    }
    $.fn.scrollToAnchor = scrollToAnchor;
  });
})();
(function() {
  var SOURCES = window.TEXT_VARIABLES.sources;
  window.Lazyload.js(SOURCES.jquery, function() {
    function affix(options) {
      var $root = this, $window = $(window), $scrollTarget, $scroll,
        offsetBottom = 0, scrollTarget = window, scroll = window.document, disabled = false, isOverallScroller = true,
        rootTop, rootLeft, rootHeight, scrollBottom, rootBottomTop,
        hasInit = false, curState;

      function setOptions(options) {
        var _options = options || {};
        _options.offsetBottom && (offsetBottom = _options.offsetBottom);
        _options.scrollTarget && (scrollTarget = _options.scrollTarget);
        _options.scroll && (scroll = _options.scroll);
        _options.disabled !== undefined && (disabled = _options.disabled);
        $scrollTarget = $(scrollTarget);
        isOverallScroller = window.isOverallScroller($scrollTarget[0]);
        $scroll = $(scroll);
      }
      function preCalc() {
        top();
        rootHeight = $root.outerHeight();
        rootTop = $root.offset().top + (isOverallScroller ? 0 :  $scrollTarget.scrollTop());
        rootLeft = $root.offset().left;
      }
      function calc(needPreCalc) {
        needPreCalc && preCalc();
        scrollBottom = $scroll.outerHeight() - offsetBottom - rootHeight;
        rootBottomTop = scrollBottom - rootTop;
      }
      function top() {
        if (curState !== 'top') {
          $root.removeClass('fixed').css({
            left: 0,
            top: 0
          });
          curState = 'top';
        }
      }
      function fixed() {
        if (curState !== 'fixed') {
          $root.addClass('fixed').css({
            left: rootLeft + 'px',
            top: 0
          });
          curState = 'fixed';
        }
      }
      function bottom() {
        if (curState !== 'bottom') {
          $root.removeClass('fixed').css({
            left: 0,
            top: rootBottomTop + 'px'
          });
          curState = 'bottom';
        }
      }
      function setState() {
        var scrollTop = $scrollTarget.scrollTop();
        if (scrollTop >= rootTop && scrollTop <= scrollBottom) {
          fixed();
        } else if (scrollTop < rootTop) {
          top();
        } else {
          bottom();
        }
      }
      function init() {
        if(!hasInit) {
          var interval, timeout;
          calc(true); setState();
          // run calc every 100 millisecond
          interval = setInterval(function() {
            calc();
          }, 100);
          timeout = setTimeout(function() {
            clearInterval(interval);
          }, 45000);
          window.pageLoad.then(function() {
            setTimeout(function() {
              clearInterval(interval);
              clearTimeout(timeout);
            }, 3000);
          });
          $scrollTarget.on('scroll', function() {
            disabled || setState();
          });
          $window.on('resize', function() {
            disabled || (calc(true), setState());
          });
          hasInit = true;
        }
      }

      setOptions(options);
      if (!disabled) {
        init();
      }
      $window.on('resize', window.throttle(function() {
        init();
      }, 200));
      return {
        setOptions: setOptions,
        refresh: function() {
          calc(true, { animation: false }); setState();
        }
      };
    }
    $.fn.affix = affix;
  });
})();
(function() {
  var SOURCES = window.TEXT_VARIABLES.sources;
  window.Lazyload.js(SOURCES.jquery, function() {
    function toc(options) {
      var $root = this, $window = $(window), $scrollTarget, $scroller, $tocUl = $('<ul class="toc toc--ellipsis"></ul>'), $tocLi, $headings, $activeLast, $activeCur,
        selectors = 'h1,h2,h3', container = 'body', scrollTarget = window, scroller = 'html, body', disabled = false,
        headingsPos, scrolling = false, hasRendered = false, hasInit = false;

      function setOptions(options) {
        var _options = options || {};
        _options.selectors && (selectors = _options.selectors);
        _options.container && (container = _options.container);
        _options.scrollTarget && (scrollTarget = _options.scrollTarget);
        _options.scroller && (scroller = _options.scroller);
        _options.disabled !== undefined && (disabled = _options.disabled);
        $headings = $(container).find(selectors).filter('[id]');
        $scrollTarget = $(scrollTarget);
        $scroller = $(scroller);
      }
      function calc() {
        headingsPos = [];
        $headings.each(function() {
          headingsPos.push(Math.floor($(this).position().top));
        });
      }
      function setState(element, disabled) {
        var scrollTop = $scrollTarget.scrollTop(), i;
        if (disabled || !headingsPos || headingsPos.length < 1) { return; }
        if (element) {
          $activeCur = element;
        } else {
          for (i = 0; i < headingsPos.length; i++) {
            if (scrollTop >= headingsPos[i]) {
              $activeCur = $tocLi.eq(i);
            } else {
              $activeCur || ($activeCur = $tocLi.eq(i));
              break;
            }
          }
        }
        $activeLast && $activeLast.removeClass('active');
        ($activeLast = $activeCur).addClass('active');
      }
      function render() {
        if(!hasRendered) {
          $root.append($tocUl);
          $headings.each(function() {
            var $this = $(this);
            $tocUl.append($('<li></li>').addClass('toc-' + $this.prop('tagName').toLowerCase())
              .append($('<a></a>').text($this.text()).attr('href', '#' + $this.prop('id'))));
          });
          $tocLi = $tocUl.children('li');
          $tocUl.on('click', 'a', function(e) {
            e.preventDefault();
            var $this = $(this);
            scrolling = true;
            setState($this.parent());
            $scroller.scrollToAnchor($this.attr('href'), 400, function() {
              scrolling = false;
            });
          });
        }
        hasRendered = true;
      }
      function init() {
        var interval, timeout;
        if(!hasInit) {
          render(); calc(); setState(null, scrolling);
          // run calc every 100 millisecond
          interval = setInterval(function() {
            calc();
          }, 100);
          timeout = setTimeout(function() {
            clearInterval(interval);
          }, 45000);
          window.pageLoad.then(function() {
            setTimeout(function() {
              clearInterval(interval);
              clearTimeout(timeout);
            }, 3000);
          });
          $scrollTarget.on('scroll', function() {
            disabled || setState(null, scrolling);
          });
          $window.on('resize', window.throttle(function() {
            if (!disabled) {
              render(); calc(); setState(null, scrolling);
            }
          }, 100));
        }
        hasInit = true;
      }

      setOptions(options);
      if (!disabled) {
        init();
      }
      $window.on('resize', window.throttle(function() {
        init();
      }, 200));
      return {
        setOptions: setOptions
      };
    }
    $.fn.toc = toc;
  });
})();
/*(function () {

})();*/
</script><script>
  /* toc must before affix, since affix need to konw toc' height. */(function() {
  var SOURCES = window.TEXT_VARIABLES.sources;
  var TOC_SELECTOR = window.TEXT_VARIABLES.site.toc.selectors;
  window.Lazyload.js(SOURCES.jquery, function() {
    var $window = $(window);
    var $articleContent = $('.js-article-content');
    var $tocRoot = $('.js-toc-root'), $col2 = $('.js-col-aside');
    var toc;
    var tocDisabled = false;
    var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
    var hasToc = $articleContent.find(TOC_SELECTOR).length > 0;

    function disabled() {
      return $col2.css('display') === 'none' || !hasToc;
    }

    tocDisabled = disabled();

    toc = $tocRoot.toc({
      selectors: TOC_SELECTOR,
      container: $articleContent,
      scrollTarget: hasSidebar ? '.js-page-main' : null,
      scroller: hasSidebar ? '.js-page-main' : null,
      disabled: tocDisabled
    });

    $window.on('resize', window.throttle(function() {
      tocDisabled = disabled();
      toc && toc.setOptions({
        disabled: tocDisabled
      });
    }, 100));

  });
})();
(function() {
  var SOURCES = window.TEXT_VARIABLES.sources;
  window.Lazyload.js(SOURCES.jquery, function() {
    var $window = $(window), $pageFooter = $('.js-page-footer');
    var $pageAside = $('.js-page-aside');
    var affix;
    var tocDisabled = false;
    var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');

    affix = $pageAside.affix({
      offsetBottom: $pageFooter.outerHeight(),
      scrollTarget: hasSidebar ? '.js-page-main' : null,
      scroller: hasSidebar ? '.js-page-main' : null,
      scroll: hasSidebar ? $('.js-page-main').children() : null,
      disabled: tocDisabled
    });

    $window.on('resize', window.throttle(function() {
      affix && affix.setOptions({
        disabled: tocDisabled
      });
    }, 100));

    window.pageAsideAffix = affix;
  });
})();
</script><script>
  window.Lazyload.js(['https://unpkg.com/[email protected]/dist/jquery.min.js', 'https://unpkg.com/[email protected]/dist/Chart.min.js'], function() {
    var $canvas = null, $this = null, _ctx = null, _text = '';
    $('.language-chart').each(function(){
      $this = $(this);
      $canvas = $('<canvas></canvas>');
      _text = $this.text();
      $this.text('').append($canvas);
      _ctx = $canvas.get(0).getContext('2d');
      (_ctx && _text) && (new Chart(_ctx, JSON.parse(_text)) && $this.attr('data-processed', true));
    });
  });
</script>
<script type="text/x-mathjax-config">
	var _config = { tex2jax: {
		inlineMath: [['$','$'], ['\\(','\\)']]
	}};_config.TeX = { equationNumbers: { autoNumber: "all" } };MathJax.Hub.Config(_config);
</script>
<script type="text/javascript" src="https://unpkg.com/[email protected]/unpacked/MathJax.js?config=TeX-MML-AM_CHTML" async></script>
<script>
  window.Lazyload.js('https://unpkg.com/[email protected]/dist/mermaid.min.js', function() {
    mermaid.initialize({
      startOnLoad: true
    });
    mermaid.init(undefined, '.language-mermaid');
  });
</script>

    </div>
    <script>(function () {
  var $root = document.getElementsByClassName('root')[0];
  if (window.hasEvent('touchstart')) {
    $root.dataset.isTouch = true;
    document.addEventListener('touchstart', function(){}, false);
  }
})();
</script>
  </body>
</html>
</div>
    </div>
    <script>
      var app = new Vue({
        el: "#app",
        data: {
          showContent: false,
          content: "I am the Content!",
        },
      });
    </script>
  </body>
</html>

v-if 是通过操纵 DOM 元素来切换元素的显示.

v-bind 用来设置元素的属性

image-20200919183412265

image-20200919183421913

image-20200919183437029

image-20200919183454501

image-20200919183517125

image-20200919183537526

image-20200919183553273

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>V-bind</title>
    <!-- development version, includes helpful console warnings -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <style>
      .active {
        border: solid 2px red;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <div
        style="background-color: black; height: 500px; color: aliceblue"
        class="text-center"
      >
        <h1>Teting the v-bind</h1>
        <button @click="toggleActive">Toggle Active</button>
        <br />
        <img
          src="https://azatai.s3.amazonaws.com/static/2020-09-16-AzatAI-Logo_white.png"
          alt=""
          width="500px"
        />
        <br />
        <img :src="imgSrc" alt="" width="500px" />
        <br />
        <img :src="imgSrc" alt="" width="500px" :class="{active:isActive}" />
      </div>
    </div>
    <script>
      var app = new Vue({
        el: "#app",
        data: {
          isActive: true,
          imgSrc:
            "https://azatai.s3.amazonaws.com/static/2020-09-16-AzatAI-Logo_white.png",
        },
        methods: {
          toggleActive: function () {
            this.isActive = !this.isActive;
          },
        },
      });
    </script>
  </body>
</html>

2020-09-19 18.53.33

v-bind 操纵元素的属性.

图片切换

image-20200919185645861

image-20200919185656797

image-20200919185711918

image-20200919185740484

image-20200919185750711

image-20200919185800983

image-20200919185815236

image-20200919185824174

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vue 图片幻灯片制作</title>
    <!-- development version, includes helpful console warnings -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <link rel="stylesheet" href="static/css/slider.css" />
  </head>
  <body>
    <div id="app">
      <div class="container">
        <button v-show="this.index!=0" @click="subIndex">prev</button>
        <div class="album">
          <img :src="imgArr[index]" alt="Some Images" />
        </div>
        <button v-show="this.index<this.imgArr.length-1" @click="addIndex">
          next
        </button>
      </div>
    </div>
    <script>
      var app = new Vue({
        el: "#app",
        data: {
          imgArr: [
            "https://blogs.sitepointstatic.com/images/tech/603-css3-multiple-borders-box.png",
            "https://www.tutorialrepublic.com/lib/images/css-border-style.png",
            "https://media.geeksforgeeks.org/wp-content/uploads/borderbottomwidth.png",
          ],
          index: 0,
        },
        methods: {
          subIndex: function () {
            this.index--;
          },
          addIndex: function () {
            this.index++;
          },
        },
      });
    </script>
  </body>
</html>

2020-09-19 19.17.52

V-for 根据数据生成列表结构

image-20200919194547931

结合的类型很多. 数组,数字,对象,之类的.

image-20200920103936392

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vue v-for</title>
    <!-- development version, includes helpful console warnings -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  </head>
  <body>
    <div id="app">
      <button @click="addElement">添加数据(append)</button>
      <button @click="removeElement">移除数据(最左)</button>
      <div>
        <h3>AzatAI Brand Colors</h3>
        <ul>
          <li v-for="(color,index) in colors" :key="index"></li>
        </ul>
        <ul>
          <li v-for="(branch,index) in branches" :key="index">
            
          </li>
        </ul>
      </div>
    </div>
    <script>
      var app = new Vue({
        el: "#app",
        data: {
          colors: ["Blue", "Red", "Yellow"],
          branches: {
            build: {
              name: "Build",
            },
            design: {
              name: "Design",
            },
            learn: {
              name: "Learn",
            },
          },
        },
        methods: {
          addElement: function () {
            this.colors.push("Green");
          },
          removeElement: function () {
            this.colors.shift();
          },
        },
      });
    </script>
  </body>
</html>

2020-09-20 11.07.06

v-on 传递自定义参数以及事件修饰符

image-20200920110846461

image-20200920110900561

image-20200920110923214

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vue v-on 事件获取参数以及事件修饰符</title>
    <!-- development version, includes helpful console warnings -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  </head>
  <body>
    <div id="app">
      <button @click="clicked">测试点击</button>
      <input type="text" name="" id="" @keyup="sayHi('AzatAI')" />
      <input type="text" name="" id="" @keyup.enter="sayHi('Azat')" />
    </div>
    <script>
      var app = new Vue({
        el: "#app",
        data: {
          pre: "Hi ",
        },
        methods: {
          clicked: function () {
            alert(this.pre + "AzatAI!");
          },
          sayHi: function (name) {
            alert(this.pre + name);
          },
        },
      });
    </script>
  </body>
</html>

2020-09-20 11.18.31

v-model 获取和设置表单元素的值 (双向数据绑定)

image-20200920112006927

表单元素

image-20200920112024414

image-20200920112037518

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>v-model</title>
    <!-- development version, includes helpful console warnings -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  </head>
  <body>
    <div id="app">
      <input type="text" name="" id="" @keyup.enter="doAlert" v-model="msg" />
      <h5></h5>
    </div>
    <script>
      var app = new Vue({
        el: "#app",
        data: {
          msg: "AzatAI",
        },
        methods: {
          doAlert: function () {
            alert(this.msg);
          },
        },
      });
    </script>
  </body>
</html>

2020-09-20 11.29.41

本地应用案例: 记事本

image-20200920113148813

image-20200920113256863

image-20200920113321818

image-20200920113335861

image-20200920113405808

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vue Notebook</title>
    <!-- development version, includes helpful console warnings -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <!-- Font Awesome -->
    <link
      rel="stylesheet"
      href="https://use.fontawesome.com/releases/v5.8.2/css/all.css"
    />
    <!-- Google Fonts -->
    <link
      rel="stylesheet"
      href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"
    />
    <!-- Bootstrap core CSS -->
    <link
      href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.min.css"
      rel="stylesheet"
    />
    <!-- Material Design Bootstrap -->
    <link
      href="https://cdnjs.cloudflare.com/ajax/libs/mdbootstrap/4.19.1/css/mdb.min.css"
      rel="stylesheet"
    />
  </head>
  <body>
    <section id="app">
      <div class="container">
        <h2 class="text-ccenter" text-center>AzatAI Simple Notebook</h2>
        <!-- Card -->
        <div class="md-form">
          <input
            @keyup.enter="add"
            v-model="valueInput"
            type="email"
            id="materialLoginFormEmail"
            class="form-control"
          />
          <label for="materialLoginFormEmail">Please Input a Note:</label>
        </div>
        <div class="card">
          <!-- Card image -->

          <!-- Card content -->
          <ul class="list-group">
            <li
              class="list-group-item d-flex justify-content-between align-items-center"
              v-for="(item,index) in list"
            >
              <span class="badge badge-primary badge-pill"></span>
              
              <i class="fas fa-times-circle" @click="remove(index)"></i>
            </li>
          </ul>
          <div class="card-body">
            <!-- Title -->
            <h6 class="card-title" v-show="!num">
              <a>You don't have any notes, write something?</a>
            </h6>
            <h6 class="card-title" v-show="num">
              <a>You have  notes totally.</a>
            </h6>
            <!-- Text -->
            <!-- Button -->
            <a href="#" class="btn btn-primary" v-show="num" @click="clear"
              >Clear</a
            >
          </div>
        </div>
        <!-- Card -->
      </div>
    </section>
    <script>
      var app = new Vue({
        el: "#app",
        data: {
          list: [],
          // num: 0,
          valueInput: "",
        },
        methods: {
          add: function () {
            this.list.push(this.valueInput);
            this.valueInput = "";
          },
          clear: function () {
            this.list = [];
          },
          remove: function (index) {
            this.list.splice(index, 1);
          },
        },
        computed: {
          num: function () {
            return this.list.length;
          },
        },
      });
    </script>
    <!-- // mdbootstrap javascript -->
    <!-- JQuery -->
    <script
      type="text/javascript"
      src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"
    ></script>
    <!-- Bootstrap tooltips -->
    <script
      type="text/javascript"
      src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.4/umd/popper.min.js"
    ></script>
    <!-- Bootstrap core JavaScript -->
    <script
      type="text/javascript"
      src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/js/bootstrap.min.js"
    ></script>
    <!-- MDB core JavaScript -->
    <script
      type="text/javascript"
      src="https://cdnjs.cloudflare.com/ajax/libs/mdbootstrap/4.19.1/js/mdb.min.js"
    ></script>
  </body>
</html>

2020-09-20 15.04.38

网络应用

内容介绍

image-20200920151917116

axios 基本使用

image-20200920152019319

Get

image-20200920152049426

image-20200920152109756

Post

image-20200920152204273

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vue axios Test</title>
    <!-- development version, includes helpful console warnings -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  </head>
  <body>
    <div id="app">
      <button id="get" @click="get">测试请求</button>
      <button id="post" @click="post">测试发送</button>
      <br />
      <input type="text" name="" id="" v-model="responseContent" />
      <hr />
      <input type="text" name="" id="" v-model="errContent" />
    </div>
    <script>
      // axios
      var app = new Vue({
        el: "#app",
        data: {
          errContent: "",
          responseContent: "",
        },
        methods: {
          get: function () {
            axios.get("https://jsonplaceholder.typicode.com/posts/1").then(
              function (response) {
                console.log(response);
              },
              function (err) {
                console.log(err);
              }
            );
          },
          post: function () {
            axios
              .post("https://jsonplaceholder.typicode.com/posts", {
                title: "foo",
                body: "bar",
                userId: 1,
              })
              .then(
                function (response) {
                  console.log(response);
                },
                function (err) {
                  console.log(err);
                }
              );
          },
        },
      });
    </script>
  </body>
</html>

2020-09-20 15.55.43

axios + Vue

image-20200920155716964

注意 Vue 的 this 的适用范围.在函数内部的嵌套函数当中,this 是另一个 object]!!! this 会变化!!!

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vue + axios</title>
    <!-- development version, includes helpful console warnings -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  </head>
  <body>
    <div id="app">
      <button @click="getContent">获取内容</button>
      <button @click="postContent">发送内容</button>
      <p><!DOCTYPE html><html lang="en">
  <head><!-- Global site tag (gtag.js) - Google Analytics -->
	<script async src="https://www.googletagmanager.com/gtag/js?id=UA-122841074-3"></script>
	<script>
		window.dataLayer = window.dataLayer || [];
		function gtag(){dataLayer.push(arguments);}
		gtag('js', new Date());

		gtag('config', 'UA-122841074-3');
		
	</script><meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"><title>A flex intro for Quasar - I'm Azat</title>

<meta name="description" content="">
<link rel="canonical" href="http://azat.cc/2020/09/16/flexbox.html"><link rel="alternate" type="application/rss+xml" title="I'm Azat" href="/feed.xml">
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="manifest" href="/site.webmanifest">
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5">
<meta name="apple-mobile-web-app-title" content="I'm Azat">
<meta name="application-name" content="I'm Azat">
<meta name="msapplication-TileColor" content="#ffffff">
<meta name="theme-color" content="#ffffff"><link rel="stylesheet" href="/assets/css/main.css"><link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css" ><!-- start custom head snippets -->

<!-- end custom head snippets -->
<script>(function() {
  window.isArray = function(val) {
    return Object.prototype.toString.call(val) === '[object Array]';
  };
  window.isString = function(val) {
    return typeof val === 'string';
  };

  window.hasEvent = function(event) {
    return 'on'.concat(event) in window.document;
  };

  window.isOverallScroller = function(node) {
    return node === document.documentElement || node === document.body || node === window;
  };

  window.isFormElement = function(node) {
    var tagName = node.tagName;
    return tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA';
  };

  window.pageLoad = (function () {
    var loaded = false, cbs = [];
    window.addEventListener('load', function () {
      var i;
      loaded = true;
      if (cbs.length > 0) {
        for (i = 0; i < cbs.length; i++) {
          cbs[i]();
        }
      }
    });
    return {
      then: function(cb) {
        cb && (loaded ? cb() : (cbs.push(cb)));
      }
    };
  })();
})();
(function() {
  window.throttle = function(func, wait) {
    var args, result, thisArg, timeoutId, lastCalled = 0;

    function trailingCall() {
      lastCalled = new Date;
      timeoutId = null;
      result = func.apply(thisArg, args);
    }
    return function() {
      var now = new Date,
        remaining = wait - (now - lastCalled);

      args = arguments;
      thisArg = this;

      if (remaining <= 0) {
        clearTimeout(timeoutId);
        timeoutId = null;
        lastCalled = now;
        result = func.apply(thisArg, args);
      } else if (!timeoutId) {
        timeoutId = setTimeout(trailingCall, remaining);
      }
      return result;
    };
  };
})();
(function() {
  var Set = (function() {
    var add = function(item) {
      var i, data = this._data;
      for (i = 0; i < data.length; i++) {
        if (data[i] === item) {
          return;
        }
      }
      this.size ++;
      data.push(item);
      return data;
    };

    var Set = function(data) {
      this.size = 0;
      this._data = [];
      var i;
      if (data.length > 0) {
        for (i = 0; i < data.length; i++) {
          add.call(this, data[i]);
        }
      }
    };
    Set.prototype.add = add;
    Set.prototype.get = function(index) { return this._data[index]; };
    Set.prototype.has = function(item) {
      var i, data = this._data;
      for (i = 0; i < data.length; i++) {
        if (this.get(i) === item) {
          return true;
        }
      }
      return false;
    };
    Set.prototype.is = function(map) {
      if (map._data.length !== this._data.length) { return false; }
      var i, j, flag, tData = this._data, mData = map._data;
      for (i = 0; i < tData.length; i++) {
        for (flag = false, j = 0; j < mData.length; j++) {
          if (tData[i] === mData[j]) {
            flag = true;
            break;
          }
        }
        if (!flag) { return false; }
      }
      return true;
    };
    Set.prototype.values = function() {
      return this._data;
    };
    return Set;
  })();

  window.Lazyload = (function(doc) {
    var queue = {js: [], css: []}, sources = {js: {}, css: {}}, context = this;
    var createNode = function(name, attrs) {
      var node = doc.createElement(name), attr;
      for (attr in attrs) {
        if (attrs.hasOwnProperty(attr)) {
          node.setAttribute(attr, attrs[attr]);
        }
      }
      return node;
    };
    var end = function(type, url) {
      var s, q, qi, cbs, i, j, cur, val, flag;
      if (type === 'js' || type ==='css') {
        s = sources[type], q = queue[type];
        s[url] = true;
        for (i = 0; i < q.length; i++) {
          cur = q[i];
          if (cur.urls.has(url)) {
            qi = cur, val = qi.urls.values();
            qi && (cbs = qi.callbacks);
            for (flag = true, j = 0; j < val.length; j++) {
              cur = val[j];
              if (!s[cur]) {
                flag = false;
              }
            }
            if (flag && cbs && cbs.length > 0) {
              for (j = 0; j < cbs.length; j++) {
                cbs[j].call(context);
              }
              qi.load = true;
            }
          }
        }
      }
    };
    var load = function(type, urls, callback) {
      var s, q, qi, node, i, cur,
        _urls = typeof urls === 'string' ? new Set([urls]) : new Set(urls), val, url;
      if (type === 'js' || type ==='css') {
        s = sources[type], q = queue[type];
        for (i = 0; i < q.length; i++) {
          cur = q[i];
          if (_urls.is(cur.urls)) {
            qi = cur;
            break;
          }
        }
        val = _urls.values();
        if (qi) {
          callback && (qi.load || qi.callbacks.push(callback));
          callback && (qi.load && callback());
        } else {
          q.push({
            urls: _urls,
            callbacks: callback ? [callback] : [],
            load: false
          });
          for (i = 0; i < val.length; i++) {
            node = null, url = val[i];
            if (s[url] === undefined) {
              (type === 'js' ) && (node = createNode('script', { src: url }));
              (type === 'css') && (node = createNode('link', { rel: 'stylesheet', href: url }));
              if (node) {
                node.onload = (function(type, url) {
                  return function() {
                    end(type, url);
                  };
                })(type, url);
                (doc.head || doc.body).appendChild(node);
                s[url] = false;
              }
            }
          }
        }
      }
    };
    return {
      js: function(url, callback) {
        load('js', url, callback);
      },
      css: function(url, callback) {
        load('css', url, callback);
      }
    };
  })(this.document);
})();
</script><script>
  (function() {
    var TEXT_VARIABLES = {
      version: '2.2.6',
      sources: {
        font_awesome: 'https://use.fontawesome.com/releases/v5.0.13/css/all.css',
        jquery: 'https://unpkg.com/[email protected]/dist/jquery.min.js',
        leancloud_js_sdk: '//cdn.jsdelivr.net/npm/[email protected]/dist/av-min.js',
        chart: 'https://unpkg.com/[email protected]/dist/Chart.min.js',
        gitalk: {
          js: 'https://unpkg.com/[email protected]/dist/gitalk.min.js',
          css: 'https://unpkg.com/[email protected]/dist/gitalk.css'
        },
        valine: 'https//unpkg.com/valine/dist/Valine.min.js',
        mathjax: 'https://unpkg.com/[email protected]/unpacked/MathJax.js?config=TeX-MML-AM_CHTML',
        mermaid: 'https://unpkg.com/[email protected]/dist/mermaid.min.js'
      },
      site: {
        toc: {
          selectors: 'h1,h2,h3,h4'
        }
      },
      paths: {
        search_js: '/assets/search.js'
      }
    };
    window.TEXT_VARIABLES = TEXT_VARIABLES;
  })();
</script>
</head>
  <body>
    <div class="root" data-is-touch="false">
      <div class="layout--page js-page-root"><div class="page__main js-page-main page__viewport has-aside cell cell--auto">

      <div class="page__main-inner"><div class="page__header d-print-none"><header class="header"><div class="main">
      <div class="header__title">
        <div class="header__brand"><?xml version="1.0" ?><svg id="Layer_1_1_" style="enable-background:new 0 0 64 64;" version="1.1" viewBox="0 0 64 64" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g><g><path d="M25,2c-2.809,0-5.225,1.659-6.34,4.047C18.441,6.026,18.224,6,18,6c-3.866,0-7,3.134-7,7v0.422    c-1.567,0.686-2.695,2.153-2.932,3.907L8,17.29C5.108,18.151,3,20.829,3,24c0,1.347,0.387,2.601,1.047,3.669    C2.778,29.085,2,30.949,2,33c0,2.344,1.012,4.449,2.619,5.912C4.221,39.863,4,40.905,4,42c0,4.08,3.054,7.446,7,7.938l0-0.002V50    h0.378c0.714,2.021,2.457,3.553,4.621,3.917l0.015-0.184C16.011,53.823,16,53.91,16,54c0,4.418,3.582,8,8,8s8-3.582,8-8V9    C32,5.134,28.866,2,25,2z M11,37.955V38C10.99,38.027,10.992,38.005,11,37.955z" style="fill:#FFCB57;"/></g><g><path d="M39,28h-4v-2h4c0.551,0,1-0.449,1-1v-7h2v7C42,26.654,40.654,28,39,28z" style="fill:#E56565;"/></g><g><path d="M41,16c-1.654,0-3-1.346-3-3s1.346-3,3-3s3,1.346,3,3S42.654,16,41,16z M41,12    c-0.551,0-1,0.449-1,1s0.449,1,1,1s1-0.449,1-1S41.551,12,41,12z" style="fill:#E56565;"/></g><g><path d="M42,46h-2v-7c0-0.551-0.449-1-1-1h-4v-2h4c1.654,0,3,1.346,3,3V46z" style="fill:#E56565;"/></g><g><path d="M41,54c-1.654,0-3-1.346-3-3s1.346-3,3-3s3,1.346,3,3S42.654,54,41,54z M41,50    c-0.551,0-1,0.449-1,1s0.449,1,1,1s1-0.449,1-1S41.551,50,41,50z" style="fill:#E56565;"/></g><g><path d="M45,33H35v-2h10c1.654,0,3-1.346,3-3v-3h2v3C50,30.757,47.757,33,45,33z" style="fill:#E56565;"/></g><g><path d="M49,23c-1.654,0-3-1.346-3-3s1.346-3,3-3s3,1.346,3,3S50.654,23,49,23z M49,19    c-0.551,0-1,0.449-1,1s0.449,1,1,1s1-0.449,1-1S49.551,19,49,19z" style="fill:#E56565;"/></g><g><rect height="10" style="fill:#E56565;" width="2" x="48" y="36"/></g><g><rect height="16" style="fill:#E56565;" width="2" x="53" y="22"/></g><g><rect height="2" style="fill:#E56565;" width="2" x="53" y="40"/></g><g><path d="M36.782,1.367c-1.45-0.223-2.92,0.194-4.034,1.148c-0.569,0.487-1.011,1.089-1.309,1.756    C29.98,2.292,27.641,1,25,1c-2.956,0-5.536,1.615-6.921,4.006C18.053,5.005,18.026,5,18,5c-4.346,0-7.886,3.485-7.99,7.806    c-1.387,0.802-2.421,2.14-2.822,3.731C4.114,17.701,2,20.678,2,24c0,1.235,0.29,2.452,0.842,3.559C1.649,29.123,1,31.029,1,33    c0,2.306,0.891,4.511,2.461,6.175C3.166,40.064,3,41.013,3,42c0,4.444,3.26,8.214,7.621,8.886    c0.825,1.833,2.417,3.251,4.415,3.829C15.403,59.344,19.279,63,24,63c2.984,0,5.626-1.466,7.264-3.709    c0.285,0.842,0.792,1.602,1.483,2.194c0.917,0.785,2.074,1.208,3.263,1.208c0.256,0,0.514-0.02,0.771-0.06    C51.974,60.281,63,47.397,63,32S51.974,3.719,36.782,1.367z M24,61c-3.86,0-7-3.14-7-7s3.14-7,7-7v-2    c-4.492,0-8.216,3.313-8.883,7.621C13.265,51.872,12,50.078,12,48c0-2.757,2.243-5,5-5v-2c-3.86,0-7,3.14-7,7    c0,0.242,0.015,0.48,0.039,0.716C7.103,47.861,5,45.148,5,42c0-3.86,3.14-7,7-7v-2c-3.196,0-6.001,1.68-7.598,4.197    C3.501,35.995,3,34.525,3,33c0-1.718,0.636-3.374,1.792-4.664l0.499-0.557l-0.393-0.636C4.311,26.193,4,25.106,4,24    c0-2.179,1.215-4.158,3.058-5.208C7.448,21.727,9.961,24,13,24v-2c-2.206,0-4-1.794-4-4s1.794-4,4-4s4,1.794,4,4h2    c0-3.309-2.691-6-6-6c-0.314,0-0.62,0.032-0.922,0.078c0.408-2.627,2.521-4.693,5.172-5.026C17.093,7.677,17,8.327,17,9    c0,4.411,3.589,8,8,8v-2c-3.309,0-6-2.691-6-6s2.691-6,6-6s6,2.691,6,6v45C31,57.86,27.86,61,24,61z M36.475,60.657    c-0.871,0.138-1.756-0.117-2.426-0.69C33.382,59.395,33,58.564,33,57.688V6.312c0-0.877,0.382-1.708,1.049-2.279    c0.551-0.472,1.248-0.726,1.963-0.726c0.154,0,0.309,0.012,0.464,0.036C50.457,5.508,61,17.828,61,32S50.457,58.492,36.475,60.657    z" style="fill:#3F3A34;"/><rect height="2" style="fill:#3F3A34;" width="2" x="25" y="8"/><rect height="2" style="fill:#3F3A34;" width="2" x="20" y="31"/><rect height="2" style="fill:#3F3A34;" width="2" x="26" y="53"/><rect height="2" style="fill:#3F3A34;" width="2" x="9" y="38"/><rect height="2" style="fill:#3F3A34;" width="2" x="27" y="24"/><rect height="2" style="fill:#3F3A34;" width="2" x="8" y="26"/></g></g></svg><a title="Tech and Finance Plus Education.
" href="/">I'm Azat</a></div><button class="button button--secondary button--circle search-button js-search-toggle"><i class="fas fa-search"></i></button></div><nav class="navigation">
        <ul><li class="navigation__item"><a href="/archive.html">Archive</a></li><li class="navigation__item"><a href="/about.html">About</a></li><li><button class="button button--secondary button--circle search-button js-search-toggle"><i class="fas fa-search"></i></button></li></ul>
      </nav></div>
  </header>
</div><div class="page__content"><div class ="main"><div class="grid grid--reverse">

              <div class="col-aside d-print-none js-col-aside"><aside class="page__aside js-page-aside"><div class="toc-aside js-toc-root"></div>
</aside></div>

              <div class="col-main cell cell--auto"><!-- start custom main top snippet -->

<!-- end custom main top snippet -->
<article itemscope itemtype="http://schema.org/Article"><div class="article__header"><header><h1>A flex intro for Quasar</h1></header><span class="split-space">&nbsp;</span>
          <a class="edit-on-github"
            title="Edit on Github"
            href="https://github.com/azataiot/Blog/tree/master/_posts/2020-09-16-flexbox.md">
            <i class="far fa-edit"></i></a></div><meta itemprop="headline" content="A flex intro for Quasar"><div class="article__info clearfix"><ul class="left-col menu"><li>
              <a class="button button--secondary button--pill button--sm"
                href="/archive.html?tag=Flexbox">Flexbox</a>
            </li><li>
              <a class="button button--secondary button--pill button--sm"
                href="/archive.html?tag=Javascript">Javascript</a>
            </li><li>
              <a class="button button--secondary button--pill button--sm"
                href="/archive.html?tag=Frontend">Frontend</a>
            </li><li>
              <a class="button button--secondary button--pill button--sm"
                href="/archive.html?tag=CSS">CSS</a>
            </li><li>
              <a class="button button--secondary button--pill button--sm"
                href="/archive.html?tag=Quasar">Quasar</a>
            </li></ul><ul class="right-col menu"><li><i class="far fa-calendar-alt"></i> <span>Sep 16, 2020</span>
            </li></ul></div><meta itemprop="author" content="Azat"/><meta itemprop="datePublished" content="2020-09-16T00:00:00+03:00">
    <meta itemprop="keywords" content="Flexbox,Javascript,Frontend,CSS,Quasar"><div class="js-article-content"><div class="layout--article"><!-- start custom article top snippet -->

<!-- end custom article top snippet -->
<div class="article__content" itemprop="articleBody"><p><img src="https://azatai.s3.amazonaws.com/static/2020-09-16-071736.jpg" alt="CSS container box full description" /></p>

<!--more-->

<h2 id="introduction">Introduction</h2>

<p>Flexbox (upon which Quasar Flex CSS classes are based) module aims to provide a more efficient way to lay out, align and distribute space among items in a container, even when their size is unknown and/or dynamic (thus the word “flex”).</p>

<h2 id="key-concept">Key Concept</h2>

<p>Quasar Flex CSS classes apply to either the Container (Parent) or the Container’s items (Children).</p>

<p><img src="https://cdn.quasar.dev/img/flexbox-container.svg" alt="flexbox-container" /></p>

<p><img src="https://cdn.quasar.dev/img/flexbox-items.svg" alt="flexbox-items" /></p>

<h2 id="managing-parents">Managing Parents</h2>

<h3 id="setting-directions">Setting Directions</h3>

<p>One of the following CSS classes is mandatory for the parent in order for ones on the children (described in next sections) to have any effect.</p>

<p><img src="https://cdn.quasar.dev/img/flexbox-direction.svg" alt="flexbox-direction" /></p>

<table>
  <thead>
    <tr>
      <th>Class Name</th>
      <th>Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">row</code></td>
      <td>Flex Row</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">row inline</code></td>
      <td>Inline Flex Row</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">column</code></td>
      <td>Flex Cloumn</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">column inline</code></td>
      <td>Inline Flex Column</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">row reverse</code></td>
      <td>Flex row with <code class="language-plaintext highlighter-rouge">flex-direction</code> set to <code class="language-plaintext highlighter-rouge">row-reverse</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">column reverse</code></td>
      <td>Flex column with <code class="language-plaintext highlighter-rouge">flex-direction</code> se to <code class="language-plaintext highlighter-rouge">column-reverse</code></td>
    </tr>
  </tbody>
</table>

<p><img src="https://azatai.s3.amazonaws.com/static/2020-09-16-073552.gif" alt="img" /></p>

<table>
  <tbody>
    <tr>
      <td>![Como o Flexbox funciona— explicado com gifs grandes e coloridos</td>
      <td>by Lucas  J S</td>
      <td>Medium](https://azatai.s3.amazonaws.com/static/2020-09-16-073507.gif)</td>
    </tr>
  </tbody>
</table>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"row"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;div&gt;</span>First column<span class="nt">&lt;/div&gt;</span>
  <span class="nt">&lt;div&gt;</span>Second column<span class="nt">&lt;/div&gt;</span>
  <span class="nt">&lt;div&gt;</span>Third column<span class="nt">&lt;/div&gt;</span>
<span class="nt">&lt;/div&gt;</span>
</code></pre></div></div>

<p><img src="https://azatai.s3.amazonaws.com/static/2020-09-16-074148.png" alt="image-20200916134147731" /></p>

<h3 id="wrapping-by-default">Wrapping by Default</h3>

<p>By default, all rows and columns wrap their content.</p>

<p><img src="https://cdn.quasar.dev/img/flexbox-wrap.svg" alt="img" /></p>

<p><img src="https://azatai.s3.amazonaws.com/static/2020-09-16-074235.gif" alt="img" /></p>

<p>However if you explicitly do not want to wrap and by so doing you want to fit all content into one line, then add <code class="language-plaintext highlighter-rouge">no-wrap</code> CSS helper class.</p>

<p>Also, if you want to wrap in reverse order, then <code class="language-plaintext highlighter-rouge">reverse-wrap</code> is available.</p>

<table>
  <thead>
    <tr>
      <th>Class Name</th>
      <th>Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">wrap</code></td>
      <td>Wrap if necessary (“on” by default, no need to specify it)</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">o-wrap</code></td>
      <td>Do NOT wrap even if necessary</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">reverse-wrap</code></td>
      <td>Wrap backwards if necessary</td>
    </tr>
  </tbody>
</table>

<h3 id="alignment">Alignment</h3>

<p><img src="https://azatai.s3.amazonaws.com/static/2020-09-16-074440.png" alt="img" /></p>

<p><strong>For alignment along the main axis</strong>, use classes below. It helps distribute left over free space when either all the flex items on a line are inflexible, or are flexible but have reached their maximum size. It also exerts some control over the alignment of items when they overflow the line.</p>

<p><img src="https://cdn.quasar.dev/img/flexbox-main-axis-align---2.svg" alt="flexbox-main-axis-align---2" /></p>

<p><img src="https://azatai.s3.amazonaws.com/static/2020-09-16-074648.gif" alt="img" /></p>

<p><strong>For alignment perpendicular to the main axis</strong>, use classes below. This defines the default behavior for how flex items are laid out along the cross axis on the current line. Think of it as the horizontal-* version for the cross-axis (perpendicular to the main-axis).</p>

<p><img src="https://cdn.quasar.dev/img/flexbox-cross-axis-align.svg" alt="flexbox-cross-axis-align" /></p>

<p><img src="https://azatai.s3.amazonaws.com/static/2020-09-16-074827.gif" alt="img" /></p>

<p>The next classes <strong>align a flex container’s lines</strong> within when there is extra space in the cross-axis, similar to how horizontal-* aligns individual items within the main-axis.</p>

<p><img src="https://cdn.quasar.dev/img/flexbox-content-align.svg" alt="img" /></p>

<h2 id="managing-children">Managing Children</h2>

<h3 id="distribution-of-size">Distribution of Size</h3>

<p>Quasar uses a 12 point column system for distributing the size of row children. Here are some examples of the available CSS helper classes:</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"row"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col-8"</span><span class="nt">&gt;</span>two thirds<span class="nt">&lt;/div&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col-2"</span><span class="nt">&gt;</span>one sixth<span class="nt">&lt;/div&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col-auto"</span><span class="nt">&gt;</span>auto size based on content and available space<span class="nt">&lt;/div&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col"</span><span class="nt">&gt;</span>fills remaining available space<span class="nt">&lt;/div&gt;</span>
<span class="nt">&lt;/div&gt;</span>
</code></pre></div></div>

<p><img src="https://azatai.s3.amazonaws.com/static/2020-09-16-075615.png" alt="image-20200916135615337" /></p>

<p><img src="https://azatai.s3.amazonaws.com/static/2020-09-16-075528.jpg" alt="Foundation 6: The New Flex Grid - SitePoint" /></p>

<p>In the example above, <code class="language-plaintext highlighter-rouge">col-8</code> fills two thirds (2/3) of the row width, because 8/12 = 2/3 = 66%, while <code class="language-plaintext highlighter-rouge">col-2</code> occupies one sixth (2/12 = 1/6 ~ 16.67%).</p>

<p>CSS helper class <code class="language-plaintext highlighter-rouge">col-auto</code> makes the cell fill only the space it needs to be rendered. <code class="language-plaintext highlighter-rouge">col</code>, on the other hand, tries to fill all space available while also shrinking if needed.</p>

<p>CSS helper class <code class="language-plaintext highlighter-rouge">col-grow</code> makes the cell fill at least the space it needs to be rendered, with the possibility to grow when more space is available.</p>

<p>CSS helper class <code class="language-plaintext highlighter-rouge">col-shrink</code> makes the cell fill at most the space it needs to be rendered, with the possibility to shrink when not enough space is available.</p>

<p>Another example with a visual representation below it:</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"row"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col"</span><span class="nt">&gt;</span>1<span class="nt">&lt;/div&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col"</span><span class="nt">&gt;</span>1<span class="nt">&lt;/div&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col"</span><span class="nt">&gt;</span>1<span class="nt">&lt;/div&gt;</span>
  <span class="c">&lt;!--
     we have 3 children, so equivalent
     to above would be to use `col-4`
     on each of the children
  --&gt;</span>
<span class="nt">&lt;/div&gt;</span>

<span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"row"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col-3"</span><span class="nt">&gt;</span>1<span class="nt">&lt;/div&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col-6"</span><span class="nt">&gt;</span>2<span class="nt">&lt;/div&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col-3"</span><span class="nt">&gt;</span>1<span class="nt">&lt;/div&gt;</span>
<span class="nt">&lt;/div&gt;</span>
</code></pre></div></div>

<p><img src="https://cdn.quasar.dev/img/flexbox-grow.svg" alt="flexbox-grow" /></p>

<p>It is also possible to offset a cell. For example: <code class="language-plaintext highlighter-rouge">offset-4</code> offsets a third of space (4/12 = 1/3 = 33%).</p>

<h3 id="wrapping">Wrapping</h3>

<p>Wrapping is a key feature in understanding Flex CSS classes. You are not bound to use exactly 12 points per row. You can use less or even more.</p>

<p>This allows you, among other things, to dynamically stack rows vertically on smaller screens while displaying them on a single line on bigger screens. Read the “Responsive Design” section.</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"row"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col-2"</span><span class="nt">&gt;</span>...<span class="nt">&lt;/div&gt;</span>

  <span class="c">&lt;!-- 2 + 6 &lt; 12, so next element is placed on same line --&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col-6"</span><span class="nt">&gt;</span>...<span class="nt">&lt;/div&gt;</span>

  <span class="c">&lt;!-- 2 + 6 + 10 &gt; 12, so next element wraps to next line --&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col-10"</span><span class="nt">&gt;</span>...<span class="nt">&lt;/div&gt;</span>

  <span class="c">&lt;!--
    10 + 3 &gt; 12, so next element wraps to next line.
    Note that we take into consideration the current line only
    (with col-10 only, since it was wrapped to its own line).
  --&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col-3"</span><span class="nt">&gt;</span>...<span class="nt">&lt;/div&gt;</span>
<span class="nt">&lt;/div&gt;</span>
</code></pre></div></div>

<p>Note that rows are wrappable by default. Should you wish to disable this, use the <code class="language-plaintext highlighter-rouge">no-wrap</code> CSS helper class.</p>

<h3 id="self-alignment">Self Alignment</h3>

<p><strong>An item can override the aligned specified on parent</strong>. This allows alignment to be overridden for individual flex items. Please see the “Alignment” explanation from “Managing Parent” to understand the available values (<code class="language-plaintext highlighter-rouge">self-start</code>, <code class="language-plaintext highlighter-rouge">self-center</code>, <code class="language-plaintext highlighter-rouge">self-baseline</code>, <code class="language-plaintext highlighter-rouge">self-end</code>, <code class="language-plaintext highlighter-rouge">self-stretch</code>).</p>

<p><img src="https://cdn.quasar.dev/img/flexbox-self.svg" alt="img" /></p>

<p><img src="https://azatai.s3.amazonaws.com/static/2020-09-16-081110.gif" alt="img" /></p>

<h3 id="order">Order</h3>

<p><strong>You can set the order</strong> of child elements by using <code class="language-plaintext highlighter-rouge">order-first</code> and <code class="language-plaintext highlighter-rouge">order-last</code> CSS helper classes.</p>

<p>By default, flex items are laid out in source order. However, the order property controls the order in which they appear in the flex container. If you need more granularity, use <code class="language-plaintext highlighter-rouge">order</code> CSS property and assign the desired value.</p>

<p>Example:</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"row"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">style=</span><span class="s">"order: 2"</span><span class="nt">&gt;</span>Second column<span class="nt">&lt;/div&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"order-last"</span><span class="nt">&gt;</span>Third column<span class="nt">&lt;/div&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"order-first"</span><span class="nt">&gt;</span>First column<span class="nt">&lt;/div&gt;</span>
<span class="nt">&lt;/div&gt;</span>
</code></pre></div></div>

<p>Here is how the CSS <code class="language-plaintext highlighter-rouge">order</code> property works:</p>

<p><img src="https://cdn.quasar.dev/img/flexbox-order.svg" alt="img" /></p>

<h2 id="responsive-design">Responsive Design</h2>

<p>Quasar Flex CSS classes can be applied based on the width of the screen, to help you in making a responsive UI. The 12 points grid is inspired by Bootstrap’s, so there are a lot of similarities.</p>

<p>What we’ve learned so far is that, for example, we can size the columns regardless of window width. If we are to create a responsive UI, we need to dynamically change the sizing while taking window width into account. First, let’s learn about some tokens that you can inject in middle of <code class="language-plaintext highlighter-rouge">col-*</code>, <code class="language-plaintext highlighter-rouge">offset-*</code> and <code class="language-plaintext highlighter-rouge">col-auto</code> helper classes (look at table below for tokens).</p>

<table>
  <thead>
    <tr>
      <th>Token</th>
      <th>Max windows width</th>
      <th>Description / When it applies</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">xs</code></td>
      <td>599px</td>
      <td>Extra small sized window</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">sm</code></td>
      <td>1023px</td>
      <td>Small sized window</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">md</code></td>
      <td>1439px</td>
      <td>Medium-sized window</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">lg</code></td>
      <td>1919px</td>
      <td>Large sized window</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">xl</code></td>
      <td>Infinite</td>
      <td>Extra large sized window</td>
    </tr>
  </tbody>
</table>

<p>Example: <code class="language-plaintext highlighter-rouge">col-md-7</code>, <code class="language-plaintext highlighter-rouge">offset-lg-3</code>, <code class="language-plaintext highlighter-rouge">col-xs-auto</code>.</p>

<p>A full example: let’s say we have a row with three children. In extra small windows, we need to stack the children vertically, In small windows we need to display them side by side (each having equal width), and starting with medium windows we should display them all on same line:</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"row"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col-xs-12 col-sm-6 col-md-4"</span><span class="nt">&gt;</span>
    col
  <span class="nt">&lt;/div&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col-xs-12 col-sm-6 col-md-4"</span><span class="nt">&gt;</span>
    col
  <span class="nt">&lt;/div&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col-xs-12 col-sm-6 col-md-4"</span><span class="nt">&gt;</span>
    col
  <span class="nt">&lt;/div&gt;</span>
<span class="nt">&lt;/div&gt;</span>
</code></pre></div></div>

<p>Notice in the above example that we used <code class="language-plaintext highlighter-rouge">col-xs-12</code> (12/12 = 100% of row, so each child will take full width of the container making all children stack vertically, since rows wrap content by default), <code class="language-plaintext highlighter-rouge">col-sm-6</code> (6/12 = 50% of row) and <code class="language-plaintext highlighter-rouge">col-md-4</code> (4/12 = 33% of row).</p>

<p>Like previously mentioned, rows wrap content by default, so when 12 (or more) grid points are used for a row, content is wrapped to the next line. If we have two <code class="language-plaintext highlighter-rouge">&lt;div&gt;</code>s and we use <code class="language-plaintext highlighter-rouge">col-8</code> on both, they will also stack, since 8 + 8 = 16 and we can only display 12 points on a single line.</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"row"</span><span class="nt">&gt;</span>
  <span class="c">&lt;!--
    more than 12 grid points together,
    so second &lt;div&gt; will wrap on next line
  --&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col-8"</span><span class="nt">&gt;</span>col<span class="nt">&lt;/div&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"col-8"</span><span class="nt">&gt;</span>col<span class="nt">&lt;/div&gt;</span>
<span class="nt">&lt;/div&gt;</span>
</code></pre></div></div>

<p>Also check <a href="https://quasar.dev/style/visibility#Window-Width-Related">Visibility</a> Style page to see thresholds on window width and these tokens (xs, sm, md, lg, xl) used on their own to hide or show DOM elements.</p>

</div><section class="article__sharing d-print-none"></section><div class="d-print-none"><footer class="article__footer"><span>Last updated
      <time itemprop="dateModified" datetime="2020-09-16T00:00:00+03:00">Sep 16, 2020</time>
    </span><!-- start custom article footer snippet -->

<!-- end custom article footer snippet -->
<div class="article__subscribe"><div class="subscribe"><i class="fas fa-rss"></i> <a type="application/rss+xml" href="/feed.xml">Subscribe</a></div>
</div><div class="article__license"><div class="license">
    <p>This work is licensed under a <a itemprop="license" rel="license" href="https://creativecommons.org/licenses/by-nc/4.0/">Attribution-NonCommercial 4.0 International</a> license.
      <a rel="license" href="https://creativecommons.org/licenses/by-nc/4.0/">
        <img alt="Attribution-NonCommercial 4.0 International" src="https://i.creativecommons.org/l/by-nc/4.0/88x31.png" />
      </a>
    </p>
  </div></div></footer>
<div class="article__section-navigator clearfix"><div class="previous"><span>PREVIOUS</span><a href="/2020/09/11/Codeguru-Quasar-Tuto.html">Codeguru Quasar Tuto</a></div><div class="next"><span>NEXT</span><a href="/2020/09/19/quick-vue.html">Vue Quick 4 Hour</a></div></div></div>

</div>

<script>(function() {
  var SOURCES = window.TEXT_VARIABLES.sources;
  window.Lazyload.js(SOURCES.jquery, function() {
    $(function() {
      var $this ,$scroll;
      var $articleContent = $('.js-article-content');
      var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
      var scroll = hasSidebar ? '.js-page-main' : 'html, body';
      $scroll = $(scroll);

      $articleContent.find('.highlight').each(function() {
        $this = $(this);
        $this.attr('data-lang', $this.find('code').attr('data-lang'));
      });
      $articleContent.find('h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]').each(function() {
        $this = $(this);
        $this.append($('<a class="anchor d-print-none" aria-hidden="true"></a>').html('<i class="fas fa-anchor"></i>'));
      });
      $articleContent.on('click', '.anchor', function() {
        $scroll.scrollToAnchor('#' + $(this).parent().attr('id'), 400);
      });
    });
  });
})();
</script>
</div><section class="page__comments d-print-none"><div id="disqus_thread"></div>
  <script>
  /**
  *  RECOMMENDED CONFIGURATION VARIABLES: EDIT AND UNCOMMENT THE SECTION BELOW TO INSERT DYNAMIC VALUES FROM YOUR PLATFORM OR CMS.
  *  LEARN WHY DEFINING THESE VARIABLES IS IMPORTANT: https://disqus.com/admin/universalcode/#configuration-variables*/
  var disqus_config = function () {
    this.page.url = 'http://azat.cc/2020/09/16/flexbox.html';
    this.page.identifier = 'flex000';
  };
  (function() { // DON'T EDIT BELOW THIS LINE
    var d = document, s = d.createElement('script');
    s.src = 'https://im-azat.disqus.com/embed.js';
    s.setAttribute('data-timestamp', +new Date());
    (d.head || d.body).appendChild(s);
  })();
  </script>
  <noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript></section></article><!-- start custom main bottom snippet -->

<!-- end custom main bottom snippet -->
</div>
            </div></div></div><div class="page__footer d-print-none">
<footer class="footer py-4 js-page-footer">
  <div class="main"><div itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Azat"><meta itemprop="url" content="https://azat.ai"><meta itemprop="description" content="I am Azat. Azat in mind, Azat in heart. (Azat means free or freedom by the way)."><div class="footer__author-links"><div class="author-links">
  <ul class="menu menu--nowrap menu--inline"><link itemprop="url" href="https://azat.ai"><li title="Follow me on Twitter.">
        <a class="button button--circle twitter-button" itemprop="sameAs" href="https://twitter.com/azataiot" target="_blank">
          <div class="icon"><svg fill="#000000" width="24px" height="24px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <path d="M1024.032 194.432c-37.664 16.704-78.176 28-120.672 33.088 43.36-26.016 76.672-67.168 92.384-116.224-40.608 24.064-85.568 41.568-133.408 50.976-38.336-40.832-92.928-66.336-153.344-66.336-116.032 0-210.08 94.048-210.08 210.08 0 16.48 1.856 32.512 5.44 47.872-174.592-8.768-329.408-92.416-433.024-219.52-18.08 31.04-28.448 67.104-28.448 105.632 0 72.896 37.088 137.184 93.472 174.88-34.432-1.088-66.816-10.528-95.168-26.272-0.032 0.864-0.032 1.76-0.032 2.656 0 101.792 72.416 186.688 168.512 205.984-17.632 4.8-36.192 7.36-55.36 7.36-13.536 0-26.688-1.312-39.52-3.776 26.72 83.456 104.32 144.192 196.256 145.888-71.904 56.352-162.496 89.92-260.928 89.92-16.96 0-33.664-0.992-50.112-2.944 92.96 59.616 203.392 94.4 322.048 94.4 386.432 0 597.728-320.128 597.728-597.76 0-9.12-0.192-18.176-0.608-27.168 41.056-29.632 76.672-66.624 104.832-108.736z" />
</svg>
</div>
        </a>
      </li><li title="Follow me on Linkedin.">
        <a class="button button--circle linkedin-button" itemprop="sameAs" href="https://www.linkedin.com/in/azataiot" target="_blank">
          <div class="icon"><svg fill="#000000" width="24px" height="24px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <path d="M260.096 155.648c0 27.307008-9.899008 50.516992-29.696 69.632-19.796992 19.115008-45.396992 28.672-76.8 28.672-30.036992 0-54.612992-9.556992-73.728-28.672-19.115008-19.115008-28.672-42.324992-28.672-69.632 0-28.672 9.556992-52.224 28.672-70.656 19.115008-18.432 44.372992-27.648 75.776-27.648 31.403008 0 56.32 9.216 74.752 27.648 18.432 18.432 28.331008 41.984 29.696 70.656 0 0 0 0 0 0m-202.752 808.96c0 0 0-632.832 0-632.832 0 0 196.608 0 196.608 0 0 0 0 632.832 0 632.832 0 0-196.608 0-196.608 0 0 0 0 0 0 0m313.344-430.08c0-58.708992-1.364992-126.292992-4.096-202.752 0 0 169.984 0 169.984 0 0 0 10.24 88.064 10.24 88.064 0 0 4.096 0 4.096 0 40.96-68.267008 105.812992-102.4 194.56-102.4 68.267008 0 123.220992 22.868992 164.864 68.608 41.643008 45.739008 62.464 113.664 62.464 203.776 0 0 0 374.784 0 374.784 0 0-196.608 0-196.608 0 0 0 0-350.208 0-350.208 0-91.476992-33.451008-137.216-100.352-137.216-47.787008 0-81.236992 24.576-100.352 73.728-4.096 8.192-6.144 24.576-6.144 49.152 0 0 0 364.544 0 364.544 0 0-198.656 0-198.656 0 0 0 0-430.08 0-430.08 0 0 0 0 0 0" />
</svg>
</div>
        </a>
      </li><li title="Follow me on Github.">
        <a class="button button--circle github-button" itemprop="sameAs" href="https://github.com/azataiot" target="_blank">
          <div class="icon"><svg fill="#000000" width="24px" height="24px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <path class="svgpath" data-index="path_0" fill="#272636" d="M0 525.2c0 223.6 143.3 413.7 343 483.5 26.9 6.8 22.8-12.4 22.8-25.4l0-88.7c-155.3 18.2-161.5-84.6-172-101.7-21.1-36-70.8-45.2-56-62.3 35.4-18.2 71.4 4.6 113.1 66.3 30.2 44.7 89.1 37.2 119 29.7 6.5-26.9 20.5-50.9 39.7-69.6C248.8 728.2 181.7 630 181.7 513.2c0-56.6 18.7-108.7 55.3-150.7-23.3-69.3 2.2-128.5 5.6-137.3 66.5-6 135.5 47.6 140.9 51.8 37.8-10.2 80.9-15.6 129.1-15.6 48.5 0 91.8 5.6 129.8 15.9 12.9-9.8 77-55.8 138.8-50.2 3.3 8.8 28.2 66.7 6.3 135 37.1 42.1 56 94.6 56 151.4 0 117-67.5 215.3-228.8 243.7 26.9 26.6 43.6 63.4 43.6 104.2l0 128.8c0.9 10.3 0 20.5 17.2 20.5C878.1 942.4 1024 750.9 1024 525.3c0-282.9-229.3-512-512-512C229.1 13.2 0 242.3 0 525.2L0 525.2z" />
</svg>
</div>
        </a>
      </li></ul>
</div>
</div>
    </div><div class="site-info mt-2">
      <div>© I'm Azat 2024 All rights Reserved.
<!--         Powered by <a title="Jekyll is a simple, blog-aware, static site generator." href="http://jekyllrb.com/">Jekyll</a> & <a -->
<!--         title="TeXt is a super customizable Jekyll theme." href="https://github.com/kitian616/jekyll-TeXt-theme">TeXt Theme</a>. -->
      </div>
    </div>
  </div>
</footer>
</div></div>
    </div><script>(function() {
  var SOURCES = window.TEXT_VARIABLES.sources;
  window.Lazyload.js(SOURCES.jquery, function() {
    var $body = $('body'), $window = $(window);
    var $pageRoot = $('.js-page-root'), $pageMain = $('.js-page-main');
    var activeCount = 0;
    function modal(options) {
      var $root = this, visible, onChange, hideWhenWindowScroll = false;
      var scrollTop;
      function setOptions(options) {
        var _options = options || {};
        visible = _options.initialVisible === undefined ? false : show;
        onChange = _options.onChange;
        hideWhenWindowScroll = _options.hideWhenWindowScroll;
      }
      function init() {
        setState(visible);
      }
      function setState(isShow) {
        if (isShow === visible) {
          return;
        }
        visible = isShow;
        if (visible) {
          activeCount++;
          scrollTop = $(window).scrollTop() || $pageMain.scrollTop();
          $root.addClass('modal--show');
          $pageMain.scrollTop(scrollTop);
          activeCount === 1 && ($pageRoot.addClass('show-modal'), $body.addClass('of-hidden'));
          hideWhenWindowScroll && window.hasEvent('touchstart') && $window.on('scroll', hide);
          $window.on('keyup', handleKeyup);
        } else {
          activeCount > 0 && activeCount--;
          $root.removeClass('modal--show');
          $window.scrollTop(scrollTop);
          activeCount === 0 && ($pageRoot.removeClass('show-modal'), $body.removeClass('of-hidden'));
          hideWhenWindowScroll && window.hasEvent('touchstart') && $window.off('scroll', hide);
          $window.off('keyup', handleKeyup);
        }
        onChange && onChange(visible);
      }
      function show() {
        setState(true);
      }
      function hide() {
        setState(false);
      }
      function handleKeyup(e) {
        // Char Code: 27  ESC
        if (e.which ===  27) {
          hide();
        }
      }
      setOptions(options);
      init();
      return {
        show: show,
        hide: hide,
        $el: $root
      };
    }
    $.fn.modal = modal;
  });
})();
</script><div class="modal modal--overflow page__search-modal d-print-none js-page-search-modal"><script>
(function () {
  var SOURCES = window.TEXT_VARIABLES.sources;
  window.Lazyload.js(SOURCES.jquery, function() {
    // search panel
    var search = (window.search || (window.search = {}));
    var useDefaultSearchBox = window.useDefaultSearchBox === undefined ?
      true : window.useDefaultSearchBox ;

    var $searchModal = $('.js-page-search-modal');
    var $searchToggle = $('.js-search-toggle');
    var searchModal = $searchModal.modal({ onChange: handleModalChange, hideWhenWindowScroll: true });
    var modalVisible = false;
    search.searchModal = searchModal;

    var $searchBox = null;
    var $searchInput = null;
    var $searchClear = null;

    function getModalVisible() {
      return modalVisible;
    }
    search.getModalVisible = getModalVisible;

    function handleModalChange(visible) {
      modalVisible = visible;
      if (visible) {
        search.onShow && search.onShow();
        useDefaultSearchBox && $searchInput[0] && $searchInput[0].focus();
      } else {
        search.onShow && search.onHide();
        useDefaultSearchBox && $searchInput[0] && $searchInput[0].blur();
        setTimeout(function() {
          useDefaultSearchBox && ($searchInput.val(''), $searchBox.removeClass('not-empty'));
          search.clear && search.clear();
          window.pageAsideAffix && window.pageAsideAffix.refresh();
        }, 400);
      }
    }

    $searchToggle.on('click', function() {
      modalVisible ? searchModal.hide() : searchModal.show();
    });
    // Char Code: 83  S, 191 /
    $(window).on('keyup', function(e) {
      if (!modalVisible && !window.isFormElement(e.target || e.srcElement) && (e.which === 83 || e.which === 191)) {
        modalVisible || searchModal.show();
      }
    });

    if (useDefaultSearchBox) {
      $searchBox = $('.js-search-box');
      $searchInput = $searchBox.children('input');
      $searchClear = $searchBox.children('.js-icon-clear');
      search.getSearchInput = function() {
        return $searchInput.get(0);
      };
      search.getVal = function() {
        return $searchInput.val();
      };
      search.setVal = function(val) {
        $searchInput.val(val);
      };

      $searchInput.on('focus', function() {
        $(this).addClass('focus');
      });
      $searchInput.on('blur', function() {
        $(this).removeClass('focus');
      });
      $searchInput.on('input', window.throttle(function() {
        var val = $(this).val();
        if (val === '' || typeof val !== 'string') {
          search.clear && search.clear();
        } else {
          $searchBox.addClass('not-empty');
          search.onInputNotEmpty && search.onInputNotEmpty(val);
        }
      }, 400));
      $searchClear.on('click', function() {
        $searchInput.val(''); $searchBox.removeClass('not-empty');
        search.clear && search.clear();
      });
    }
  });
})();
</script><div class="search search--dark">
  <div class="main">
    <div class="search__header">Search</div>
    <div class="search-bar">
      <div class="search-box js-search-box">
        <div class="search-box__icon-search"><i class="fas fa-search"></i></div>
        <input type="text" />
        <div class="search-box__icon-clear js-icon-clear">
          <a><i class="fas fa-times"></i></a>
        </div>
      </div>
      <button class="button button--theme-dark button--pill search__cancel js-search-toggle">
        Cancel</button>
    </div>
    <div class="search-result js-search-result"></div>
  </div>
</div>
<script>var SOURCES = window.TEXT_VARIABLES.sources;
var PAHTS = window.TEXT_VARIABLES.paths;
window.Lazyload.js([SOURCES.jquery, PAHTS.search_js], function() {
  var search = (window.search || (window.search = {}));
  var searchData = window.TEXT_SEARCH_DATA || {};

  function memorize(f) {
    var cache = {};
    return function () {
      var key = Array.prototype.join.call(arguments, ',');
      if (key in cache) return cache[key];
      else return cache[key] = f.apply(this, arguments);
    };
  }

  /// search
  function searchByQuery(query) {
    var i, j, key, keys, cur, _title, result = {};
    keys = Object.keys(searchData);
    for (i = 0; i < keys.length; i++) {
      key = keys[i];
      for (j = 0; j < searchData[key].length; j++) {
        cur = searchData[key][j], _title = cur.title;
        if ((result[key] === undefined || result[key] && result[key].length < 4 )
          && _title.toLowerCase().indexOf(query.toLowerCase()) >= 0) {
          if (result[key] === undefined) {
            result[key] = [];
          }
          result[key].push(cur);
        }
      }
    }
    return result;
  }

  var renderHeader = memorize(function(header) {
    return $('<p class="search-result__header">' + header + '</p>');
  });

  var renderItem = function(index, title, url) {
    return $('<li class="search-result__item" data-index="' + index + '"><a class="button" href="' + url + '">' + title + '</a></li>');
  };

  function render(data) {
    if (!data) { return null; }
    var $root = $('<ul></ul>'), i, j, key, keys, cur, itemIndex = 0;
    keys = Object.keys(data);
    for (i = 0; i < keys.length; i++) {
      key = keys[i];
      $root.append(renderHeader(key));
      for (j = 0; j < data[key].length; j++) {
        cur = data[key][j];
        $root.append(renderItem(itemIndex++, cur.title, cur.url));
      }
    }
    return $root;
  }

  // search box
  var $result = $('.js-search-result'), $resultItems;
  var lastActiveIndex, activeIndex;

  function clear() {
    $result.html(null);
    $resultItems = $('.search-result__item'); activeIndex = 0;
  }
  function onInputNotEmpty(val) {
    $result.html(render(searchByQuery(val)));
    $resultItems = $('.search-result__item'); activeIndex = 0;
    $resultItems.eq(0).addClass('active');
  }

  search.clear = clear;
  search.onInputNotEmpty = onInputNotEmpty;

  function updateResultItems() {
    lastActiveIndex >= 0 && $resultItems.eq(lastActiveIndex).removeClass('active');
    activeIndex >= 0 && $resultItems.eq(activeIndex).addClass('active');
  }

  function moveActiveIndex(direction) {
    var itemsCount = $resultItems ? $resultItems.length : 0;
    if (itemsCount > 1) {
      lastActiveIndex = activeIndex;
      if (direction === 'up') {
        activeIndex = (activeIndex - 1 + itemsCount) % itemsCount;
      } else if (direction === 'down') {
        activeIndex = (activeIndex + 1 + itemsCount) % itemsCount;
      }
      updateResultItems();
    }
  }

  // Char Code: 13  Enter, 37  ⬅, 38  ⬆, 39  ➡, 40  ⬇
  $(window).on('keyup', function(e) {
    var modalVisible = search.getModalVisible && search.getModalVisible();
    if (modalVisible) {
      if (e.which === 38) {
        modalVisible && moveActiveIndex('up');
      } else if (e.which === 40) {
        modalVisible && moveActiveIndex('down');
      } else if (e.which === 13) {
        modalVisible && $resultItems && activeIndex >= 0 && $resultItems.eq(activeIndex).children('a')[0].click();
      }
    }
  });

  $result.on('mouseover', '.search-result__item > a', function() {
    var itemIndex = $(this).parent().data('index');
    itemIndex >= 0 && (lastActiveIndex = activeIndex, activeIndex = itemIndex, updateResultItems());
  });
});
</script>
</div></div>


<script>(function() {
  var SOURCES = window.TEXT_VARIABLES.sources;
  window.Lazyload.js(SOURCES.jquery, function() {
    function scrollToAnchor(anchor, duration, callback) {
      var $root = this;
      $root.animate({ scrollTop: $(anchor).position().top }, duration, function() {
        window.history.replaceState(null, '', window.location.href.split('#')[0] + anchor);
        callback && callback();
      });
    }
    $.fn.scrollToAnchor = scrollToAnchor;
  });
})();
(function() {
  var SOURCES = window.TEXT_VARIABLES.sources;
  window.Lazyload.js(SOURCES.jquery, function() {
    function affix(options) {
      var $root = this, $window = $(window), $scrollTarget, $scroll,
        offsetBottom = 0, scrollTarget = window, scroll = window.document, disabled = false, isOverallScroller = true,
        rootTop, rootLeft, rootHeight, scrollBottom, rootBottomTop,
        hasInit = false, curState;

      function setOptions(options) {
        var _options = options || {};
        _options.offsetBottom && (offsetBottom = _options.offsetBottom);
        _options.scrollTarget && (scrollTarget = _options.scrollTarget);
        _options.scroll && (scroll = _options.scroll);
        _options.disabled !== undefined && (disabled = _options.disabled);
        $scrollTarget = $(scrollTarget);
        isOverallScroller = window.isOverallScroller($scrollTarget[0]);
        $scroll = $(scroll);
      }
      function preCalc() {
        top();
        rootHeight = $root.outerHeight();
        rootTop = $root.offset().top + (isOverallScroller ? 0 :  $scrollTarget.scrollTop());
        rootLeft = $root.offset().left;
      }
      function calc(needPreCalc) {
        needPreCalc && preCalc();
        scrollBottom = $scroll.outerHeight() - offsetBottom - rootHeight;
        rootBottomTop = scrollBottom - rootTop;
      }
      function top() {
        if (curState !== 'top') {
          $root.removeClass('fixed').css({
            left: 0,
            top: 0
          });
          curState = 'top';
        }
      }
      function fixed() {
        if (curState !== 'fixed') {
          $root.addClass('fixed').css({
            left: rootLeft + 'px',
            top: 0
          });
          curState = 'fixed';
        }
      }
      function bottom() {
        if (curState !== 'bottom') {
          $root.removeClass('fixed').css({
            left: 0,
            top: rootBottomTop + 'px'
          });
          curState = 'bottom';
        }
      }
      function setState() {
        var scrollTop = $scrollTarget.scrollTop();
        if (scrollTop >= rootTop && scrollTop <= scrollBottom) {
          fixed();
        } else if (scrollTop < rootTop) {
          top();
        } else {
          bottom();
        }
      }
      function init() {
        if(!hasInit) {
          var interval, timeout;
          calc(true); setState();
          // run calc every 100 millisecond
          interval = setInterval(function() {
            calc();
          }, 100);
          timeout = setTimeout(function() {
            clearInterval(interval);
          }, 45000);
          window.pageLoad.then(function() {
            setTimeout(function() {
              clearInterval(interval);
              clearTimeout(timeout);
            }, 3000);
          });
          $scrollTarget.on('scroll', function() {
            disabled || setState();
          });
          $window.on('resize', function() {
            disabled || (calc(true), setState());
          });
          hasInit = true;
        }
      }

      setOptions(options);
      if (!disabled) {
        init();
      }
      $window.on('resize', window.throttle(function() {
        init();
      }, 200));
      return {
        setOptions: setOptions,
        refresh: function() {
          calc(true, { animation: false }); setState();
        }
      };
    }
    $.fn.affix = affix;
  });
})();
(function() {
  var SOURCES = window.TEXT_VARIABLES.sources;
  window.Lazyload.js(SOURCES.jquery, function() {
    function toc(options) {
      var $root = this, $window = $(window), $scrollTarget, $scroller, $tocUl = $('<ul class="toc toc--ellipsis"></ul>'), $tocLi, $headings, $activeLast, $activeCur,
        selectors = 'h1,h2,h3', container = 'body', scrollTarget = window, scroller = 'html, body', disabled = false,
        headingsPos, scrolling = false, hasRendered = false, hasInit = false;

      function setOptions(options) {
        var _options = options || {};
        _options.selectors && (selectors = _options.selectors);
        _options.container && (container = _options.container);
        _options.scrollTarget && (scrollTarget = _options.scrollTarget);
        _options.scroller && (scroller = _options.scroller);
        _options.disabled !== undefined && (disabled = _options.disabled);
        $headings = $(container).find(selectors).filter('[id]');
        $scrollTarget = $(scrollTarget);
        $scroller = $(scroller);
      }
      function calc() {
        headingsPos = [];
        $headings.each(function() {
          headingsPos.push(Math.floor($(this).position().top));
        });
      }
      function setState(element, disabled) {
        var scrollTop = $scrollTarget.scrollTop(), i;
        if (disabled || !headingsPos || headingsPos.length < 1) { return; }
        if (element) {
          $activeCur = element;
        } else {
          for (i = 0; i < headingsPos.length; i++) {
            if (scrollTop >= headingsPos[i]) {
              $activeCur = $tocLi.eq(i);
            } else {
              $activeCur || ($activeCur = $tocLi.eq(i));
              break;
            }
          }
        }
        $activeLast && $activeLast.removeClass('active');
        ($activeLast = $activeCur).addClass('active');
      }
      function render() {
        if(!hasRendered) {
          $root.append($tocUl);
          $headings.each(function() {
            var $this = $(this);
            $tocUl.append($('<li></li>').addClass('toc-' + $this.prop('tagName').toLowerCase())
              .append($('<a></a>').text($this.text()).attr('href', '#' + $this.prop('id'))));
          });
          $tocLi = $tocUl.children('li');
          $tocUl.on('click', 'a', function(e) {
            e.preventDefault();
            var $this = $(this);
            scrolling = true;
            setState($this.parent());
            $scroller.scrollToAnchor($this.attr('href'), 400, function() {
              scrolling = false;
            });
          });
        }
        hasRendered = true;
      }
      function init() {
        var interval, timeout;
        if(!hasInit) {
          render(); calc(); setState(null, scrolling);
          // run calc every 100 millisecond
          interval = setInterval(function() {
            calc();
          }, 100);
          timeout = setTimeout(function() {
            clearInterval(interval);
          }, 45000);
          window.pageLoad.then(function() {
            setTimeout(function() {
              clearInterval(interval);
              clearTimeout(timeout);
            }, 3000);
          });
          $scrollTarget.on('scroll', function() {
            disabled || setState(null, scrolling);
          });
          $window.on('resize', window.throttle(function() {
            if (!disabled) {
              render(); calc(); setState(null, scrolling);
            }
          }, 100));
        }
        hasInit = true;
      }

      setOptions(options);
      if (!disabled) {
        init();
      }
      $window.on('resize', window.throttle(function() {
        init();
      }, 200));
      return {
        setOptions: setOptions
      };
    }
    $.fn.toc = toc;
  });
})();
/*(function () {

})();*/
</script><script>
  /* toc must before affix, since affix need to konw toc' height. */(function() {
  var SOURCES = window.TEXT_VARIABLES.sources;
  var TOC_SELECTOR = window.TEXT_VARIABLES.site.toc.selectors;
  window.Lazyload.js(SOURCES.jquery, function() {
    var $window = $(window);
    var $articleContent = $('.js-article-content');
    var $tocRoot = $('.js-toc-root'), $col2 = $('.js-col-aside');
    var toc;
    var tocDisabled = false;
    var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
    var hasToc = $articleContent.find(TOC_SELECTOR).length > 0;

    function disabled() {
      return $col2.css('display') === 'none' || !hasToc;
    }

    tocDisabled = disabled();

    toc = $tocRoot.toc({
      selectors: TOC_SELECTOR,
      container: $articleContent,
      scrollTarget: hasSidebar ? '.js-page-main' : null,
      scroller: hasSidebar ? '.js-page-main' : null,
      disabled: tocDisabled
    });

    $window.on('resize', window.throttle(function() {
      tocDisabled = disabled();
      toc && toc.setOptions({
        disabled: tocDisabled
      });
    }, 100));

  });
})();
(function() {
  var SOURCES = window.TEXT_VARIABLES.sources;
  window.Lazyload.js(SOURCES.jquery, function() {
    var $window = $(window), $pageFooter = $('.js-page-footer');
    var $pageAside = $('.js-page-aside');
    var affix;
    var tocDisabled = false;
    var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');

    affix = $pageAside.affix({
      offsetBottom: $pageFooter.outerHeight(),
      scrollTarget: hasSidebar ? '.js-page-main' : null,
      scroller: hasSidebar ? '.js-page-main' : null,
      scroll: hasSidebar ? $('.js-page-main').children() : null,
      disabled: tocDisabled
    });

    $window.on('resize', window.throttle(function() {
      affix && affix.setOptions({
        disabled: tocDisabled
      });
    }, 100));

    window.pageAsideAffix = affix;
  });
})();
</script><script>
  window.Lazyload.js(['https://unpkg.com/[email protected]/dist/jquery.min.js', 'https://unpkg.com/[email protected]/dist/Chart.min.js'], function() {
    var $canvas = null, $this = null, _ctx = null, _text = '';
    $('.language-chart').each(function(){
      $this = $(this);
      $canvas = $('<canvas></canvas>');
      _text = $this.text();
      $this.text('').append($canvas);
      _ctx = $canvas.get(0).getContext('2d');
      (_ctx && _text) && (new Chart(_ctx, JSON.parse(_text)) && $this.attr('data-processed', true));
    });
  });
</script>
<script type="text/x-mathjax-config">
	var _config = { tex2jax: {
		inlineMath: [['$','$'], ['\\(','\\)']]
	}};_config.TeX = { equationNumbers: { autoNumber: "all" } };MathJax.Hub.Config(_config);
</script>
<script type="text/javascript" src="https://unpkg.com/[email protected]/unpacked/MathJax.js?config=TeX-MML-AM_CHTML" async></script>
<script>
  window.Lazyload.js('https://unpkg.com/[email protected]/dist/mermaid.min.js', function() {
    mermaid.initialize({
      startOnLoad: true
    });
    mermaid.init(undefined, '.language-mermaid');
  });
</script>

    </div>
    <script>(function () {
  var $root = document.getElementsByClassName('root')[0];
  if (window.hasEvent('touchstart')) {
    $root.dataset.isTouch = true;
    document.addEventListener('touchstart', function(){}, false);
  }
})();
</script>
  </body>
</html>
</p>
      <li v-for="(obj,key) in content"> : </li>
    </div>
    <script>
      var app = new Vue({
        el: "#app",
        data: {
          content: "",
        },
        methods: {
          getContent: function () {
            console.log(this); // 这里的 this 指向的是 Vue 实例
            that = this;
            axios
              .get("https://jsonplaceholder.typicode.com/posts/1")
              .then(function (response) {
                that.content = response.data;
              });
            this.content = "";
          },
          postContent: function () {
            that = this;
            axios
              .post("https://jsonplaceholder.typicode.com/posts", {
                title: "foo",
                body: "bar",
                userId: 1,
              })
              .then(
                function (response) {
                  console.log(response.data);
                  that.content = response.data;
                },
                function (err) {
                  console.log(err);
                }
              );
            this.content = "";
          },
        },
      });
    </script>
  </body>
</html>

2020-09-20 16.19.32

Vue 结合网络数据开发应用

image-20200920162139472

image-20200920162314992

image-20200920162333411

image-20200920163010268

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vue Weather App</title>
    <link
      rel="stylesheet"
      href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"
      integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z"
      crossorigin="anonymous"
    />
    <!-- development version, includes helpful console warnings -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  </head>
  <body>
    <div class="container top" id="app">
      <!-- Content here -->
      <div class="card text-center">
        <h3>.</h3>
        <div class="card-header"></div>
        <div class="card-body">
          <h5 class="card-title">Vue.js Weather App Demo</h5>
          <div class="input-group mb-3">
            <input
              @keyup.enter="searchByName(currentCity)"
              v-model="currentCity"
              type="text"
              class="form-control"
              placeholder="Please input a city name and press enter"
              aria-label="Please input a city name and press enter"
              aria-describedby="button-addon2"
            />
            <div class="input-group-append">
              <button
                class="btn btn-outline-secondary"
                type="button"
                id="button-addon2"
                @click="searchByName(currentCity)"
              >
                Search
              </button>
            </div>
          </div>
          <div class="input-group mb-3">
            <div class="input-group-append">
              <button
                v-for="(city,index) in citiesChangYong"
                class="btn btn-outline-secondary"
                type="button"
                id="button-addon2"
                @click="searchById(index)"
              >
                
              </button>
            </div>
          </div>
          <a href="#" class="btn btn-primary">Go somewhere</a>
        </div>
      </div>
      <div v-if="rData">:</div>
    </div>

    <footer>
      <script
        src="https://code.jquery.com/jquery-3.5.1.slim.min.js"
        integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj"
        crossorigin="anonymous"
      ></script>
      <script
        src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js"
        integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN"
        crossorigin="anonymous"
      ></script>
      <script
        src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"
        integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV"
        crossorigin="anonymous"
      ></script>
      <script src="js/main.js"></script>
    </footer>
  </body>
</html>
.top {
  padding-top: 20px;
  margin-top: 20px;
}

var app = new Vue({
  el: "#app",
  data() {
    return {
      currentCity: "",
      citiesChangYong: ["Almaty", "London", "Beijing"],
      rData: "",
    };
  },
  methods: {
    searchById: function (id) {
      //   console.log(id);
      city = this.citiesChangYong[id];
      //   console.log(city);
      this.searchByName(city);
    },
    searchByName: function (city) {
      var api = "c85205db2bd74ae8c7958b4865a006b2";
      const url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${api}`;
      console.log(url);
      var that = this;
      axios.get(url).then(function (response) {
        console.log(response.data);
        that.rData = response.data;
      });
    },
  },
});

2020-09-20 17.31.11

综合应用

介绍

image-20200920173408678

image-20200920173527189本应用由于 API 的关系暂停更新.