VUE的简陋实现(Simple implementation of Vue)

按:记录一下VUE学习初期的简陋实现,除编译器外,无需额外安装任何内容;另外简陋的实现与后台的交互。
参考了这篇博客。
0. 文件准备
从官网下载(点击“开发版本”可下载)和、(./dist/文件夹下;若无法访问,可从其余途径下载)文件。

vue.js
axios.js
axios.map
  • VUE项目的结构
vue-demo
|-- index.html
|-- vue.js
|-- axios.js
|-- axios.map
|-- style.css
  • style.css
    此文件内容来自vue官网的示例。本随笔采用的是网格组件。
  • index.html
    此文件的主要内容也是来自网格组件的官方示例。添加的内容实现的是与后台交互。
    完整的内容如下:
<!DOCTYPE html>
<html>
  <head>
    <title>Grid Component</title>
    <script src="./vue.js"></script> <!--改动点-->
    <script src="./axios.js"></script> <!--改动点-->
    <link rel="stylesheet" type="text/css" href="/style.css" />

    <!-- component template -->
    <script type="text/x-template" id="grid-template">
      <table>
        <thead>
          <tr>
            <th v-for="key in columns"
              @click="sortBy(key)"
              :class="{ active: sortKey == key }">
              {{ key | capitalize }}
              <span class="arrow" :class="sortOrders[key] > 0 ? 'asc' : 'dsc'">
              </span>
            </th>
          </tr>
        </thead>
        <tbody>
          <tr v-for="entry in filteredHeroes">
            <td v-for="key in columns">
              {{entry[key]}}
            </td>
          </tr>
        </tbody>
      </table>
    </script>
    <!-- 改动点 -->
    <script type="text/x-template" id="call-template">
      <table>
        <tbody>
          <tr @click='callLink()'">
            <td >
              answer is: {{answer}}
            </td>
          </tr>
        </tbody>
      </table>
    </script>
  </head>
  <body>
    <!-- demo root element -->
    <div id="demo">
      <form id="search">
        Search <input name="query" v-model="searchQuery" />
      </form>
      <demo-grid
        :heroes="gridData"
        :columns="gridColumns"
        :filter-key="searchQuery"
      >
      </demo-grid>

      <call-demo></call-demo> <!--改动点-->
    </div>

    <script>
      // register the grid component
      Vue.component("demo-grid", {
        template: "#grid-template",
        props: {
          heroes: Array,
          columns: Array,
          filterKey: String
        },
        data: function() {
          var sortOrders = {};
          this.columns.forEach(function(key) {
            sortOrders[key] = 1;
          });
          return {
            sortKey: "",
            sortOrders: sortOrders
          };
        },
        computed: {
          filteredHeroes: function() {
            var sortKey = this.sortKey;
            var filterKey = this.filterKey && this.filterKey.toLowerCase();
            var order = this.sortOrders[sortKey] || 1;
            var heroes = this.heroes;
            if (filterKey) {
              heroes = heroes.filter(function(row) {
                return Object.keys(row).some(function(key) {
                  return (
                    String(row[key])
                      .toLowerCase()
                      .indexOf(filterKey) > -1
                  );
                });
              });
            }
            if (sortKey) {
              heroes = heroes.slice().sort(function(a, b) {
                a = a[sortKey];
                b = b[sortKey];
                return (a === b ? 0 : a > b ? 1 : -1) * order;
              });
            }
            return heroes;
          }
        },
        filters: {
          capitalize: function(str) {
            return str.charAt(0).toUpperCase() + str.slice(1);
          }
        },
        methods: {
          sortBy: function(key) {
            this.sortKey = key;
            this.sortOrders[key] = this.sortOrders[key] * -1;
          }
        }
      });

      <!--改动点-->
      Vue.component("call-demo", {
        data: function(){
            return {answer: 'this is answer.'}
        },
        template: '#call-template',
        methods: {
            callLink: function(){
                var vm = this;
                vm.answer = 'calling ...';
                <!--访问后台-->
                axios.get('http://localhost:8888/demo-system/a?param=123')
                    .then(function(response){
                        vm.answer = response.data;
                  }).catch(function(error){
                        vm.answer = 'Error! '+error;
                });
            }
      }
      });

      // bootstrap the demo
      var demo = new Vue({
        el: "#demo",
        data: {
          searchQuery: "",
          gridColumns: ["name", "power"],
          gridData: [
            { name: "Chuck Norris", power: Infinity },
            { name: "Bruce Lee", power: 9000 },
            { name: "Jackie Chan", power: 7000 },
            { name: "Jet Li", power: 8000 }
          ]
        }
      });
    </script>
  </body>
</html>

  • 运行
    1)启动后台,确保浏览器访问目的网址可得到json格式的数据(本随笔中的目的网址为: http://localhost:8888/demo-system/a?param=123 );
    2)从浏览器打开index.html或者从编译器启动,点击单元格answer即可。

Tips:

  • 通常,前后端分离后会发生跨域访问错误,需要在前端或者后端进行一些额外的配置,此随笔选择利用注解@CrossOrigin(origins = “*”)在后端进行配置,主要参考了这篇文章。
  • vue.component的编写参考了这篇文章。
————————

< strong > Press: < / strong > record the simple implementation of Vue in the early stage of learning. There is no need to install any additional content except the compiler; In addition, the simple implementation of the interaction with the background.
Refer to this blog.
0. Document preparation
Download files from the official website (click “development version” to download) and (. / dist / folder; if you can’t access them, you can download them from other ways).

vue.js
axios.js
axios.map
  • Structure of Vue project
vue-demo
|-- index.html
|-- vue.js
|-- axios.js
|-- axios.map
|-- style.css
  • style. css
    The content of this file is from the example of Vue official website. This essay uses grid components.
  • index. html
    The main content of this file is also an official example from grid components. The added content realizes the interaction with the background.
    The complete contents are as follows:
<!DOCTYPE html>
<html>
  <head>
    <title>Grid Component</title>
    <script src="./vue.js"></script> <!--改动点-->
    <script src="./axios.js"></script> <!--改动点-->
    <link rel="stylesheet" type="text/css" href="/style.css" />

    <!-- component template -->
    <script type="text/x-template" id="grid-template">
      <table>
        <thead>
          <tr>
            <th v-for="key in columns"
              @click="sortBy(key)"
              :class="{ active: sortKey == key }">
              {{ key | capitalize }}
              <span class="arrow" :class="sortOrders[key] > 0 ? 'asc' : 'dsc'">
              </span>
            </th>
          </tr>
        </thead>
        <tbody>
          <tr v-for="entry in filteredHeroes">
            <td v-for="key in columns">
              {{entry[key]}}
            </td>
          </tr>
        </tbody>
      </table>
    </script>
    <!-- 改动点 -->
    <script type="text/x-template" id="call-template">
      <table>
        <tbody>
          <tr @click='callLink()'">
            <td >
              answer is: {{answer}}
            </td>
          </tr>
        </tbody>
      </table>
    </script>
  </head>
  <body>
    <!-- demo root element -->
    <div id="demo">
      <form id="search">
        Search <input name="query" v-model="searchQuery" />
      </form>
      <demo-grid
        :heroes="gridData"
        :columns="gridColumns"
        :filter-key="searchQuery"
      >
      </demo-grid>

      <call-demo></call-demo> <!--改动点-->
    </div>

    <script>
      // register the grid component
      Vue.component("demo-grid", {
        template: "#grid-template",
        props: {
          heroes: Array,
          columns: Array,
          filterKey: String
        },
        data: function() {
          var sortOrders = {};
          this.columns.forEach(function(key) {
            sortOrders[key] = 1;
          });
          return {
            sortKey: "",
            sortOrders: sortOrders
          };
        },
        computed: {
          filteredHeroes: function() {
            var sortKey = this.sortKey;
            var filterKey = this.filterKey && this.filterKey.toLowerCase();
            var order = this.sortOrders[sortKey] || 1;
            var heroes = this.heroes;
            if (filterKey) {
              heroes = heroes.filter(function(row) {
                return Object.keys(row).some(function(key) {
                  return (
                    String(row[key])
                      .toLowerCase()
                      .indexOf(filterKey) > -1
                  );
                });
              });
            }
            if (sortKey) {
              heroes = heroes.slice().sort(function(a, b) {
                a = a[sortKey];
                b = b[sortKey];
                return (a === b ? 0 : a > b ? 1 : -1) * order;
              });
            }
            return heroes;
          }
        },
        filters: {
          capitalize: function(str) {
            return str.charAt(0).toUpperCase() + str.slice(1);
          }
        },
        methods: {
          sortBy: function(key) {
            this.sortKey = key;
            this.sortOrders[key] = this.sortOrders[key] * -1;
          }
        }
      });

      <!--改动点-->
      Vue.component("call-demo", {
        data: function(){
            return {answer: 'this is answer.'}
        },
        template: '#call-template',
        methods: {
            callLink: function(){
                var vm = this;
                vm.answer = 'calling ...';
                <!--访问后台-->
                axios.get('http://localhost:8888/demo-system/a?param=123')
                    .then(function(response){
                        vm.answer = response.data;
                  }).catch(function(error){
                        vm.answer = 'Error! '+error;
                });
            }
      }
      });

      // bootstrap the demo
      var demo = new Vue({
        el: "#demo",
        data: {
          searchQuery: "",
          gridColumns: ["name", "power"],
          gridData: [
            { name: "Chuck Norris", power: Infinity },
            { name: "Bruce Lee", power: 9000 },
            { name: "Jackie Chan", power: 7000 },
            { name: "Jet Li", power: 8000 }
          ]
        }
      });
    </script>
  </body>
</html>

  • function
    1) Start the background to ensure that the browser can access the target website to get data in JSON format (the target website in this essay is: http://localhost:8888/demo -system/a? param=123 );
    2) Open index. From the browser HTML or start from the compiler and click cell answer.

Tips:

  • Generally, cross domain access errors will occur after the front and back ends are separated, and some additional configuration needs to be made on the front end or back end. This essay chooses to use the annotation @ crossorigin (origins = “*”) to configure on the back end. I mainly refer to this article.
  • vue. The preparation of component refers to this article.