zoukankan      html  css  js  c++  java
  • Vue对象提供的属性功能

     

    Vue对象提供的属性功能

     

    一. 过滤器

      过滤器,就是vue允许开发者自定义的文本格式化函数,可以使用在两个地方:输出内容和操作数据中。

      定义过滤器的方式有两种:

    1. 使用Vue.filter()进行全局定义

      示例:

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>过滤器</title>
      <script src="js/vue.js"></script>
    </head>
    <body>

    <div id="app">
      {{price}}
      <p>{{price|RMB}}</p>
    </div>
    <script>
      // 通过Vue.filter() 进行全局声明,是在vm对象创建之前声明好的。
      // 语法:Vue.filter("过滤器名称", func);
      Vue.filter('RMB', function (data) {
          return "¥" + data;
      });
      var vm = new Vue({
          el: "#app",
          data: {
              price: 10.3333333,
          }
      })
    </script>
    </body>
    </html>

      效果:

    2. 在Vue对象中通过filters属性来定义

      示例:

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>过滤器</title>
      <script src="js/vue.js"></script>
    </head>
    <body>

    <div id="app">
      {{price}}
      <p>{{price|RMB}}</p>
      <p>{{price|p_format(2)}}</p>
      <!--这里会报错,因为过滤器后的数据,已经不是数值了。为了避免报错,只需将过滤器换个位置即可。-->
      <!--<p>{{price|RMB|p_format(2)}}</p>-->
      <p>{{price|p_format(2)|RMB}}</p>
    </div>
    <script>
      // 用法一:
      // 通过Vue.filter() 进行全局声明,是在vm对象创建之前声明好的。
      // 语法:Vue.filter("过滤器名称", func);
      Vue.filter('RMB', function (data) {
          return "¥" + data;
      });
      var vm = new Vue({
          el: "#app",
          data: {
              price: 10.3333333,
          },
          // 用法二:
          // 通过vm对象内部的filters属性进行局部声明,过滤器只能用于当前vm实例对象。
          filters: {
              // "过滤器名称": function(){
              //     // 过滤器执行的代码
              // }
              // p_format: function (data, num) {
              //     return data.toFixed(num);
              // }
              // 可以简写为
              p_format(data, num){
                  return data.toFixed(num);
              }
          }
      })
    </script>
    </body>
    </html>

      效果:

      总结:

    1. 一个数据可以调用多个过滤器,每个过滤器之间使用 "|"竖杠隔开,但是过滤器之间的执行顺序是从左往右执行,所以有可能产生冲突问题.这时候可以尝试调整调用过滤器之间的顺序

    2. 过滤器本质上就是一个函数,所有我们必须有返回值,否则数据调用了过滤器以后,无法得到处理后的数据结果
    3. vue1.x版本时,有内置过滤器的,但是官方认为,过多的封装工具给开发者使用,会容易造成框架本身的臃肿,所以在vue2.x版本以后又废除了.
    4. 过滤器本质上来说就是函数,所以函数不仅只有一个参数的.我们过滤器也支持多个参数的写法.

    二. 计算属性

      我们之前学习过字符串反转,如果直接把反转的代码写在元素中,则会使得其他同事在开发时时不易发现数据被调整了,所以vue提供了一个计算属性(computed),可以让我们把调整data数据的代码存在在该属性中。

      示例:

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>计算属性</title>
      <script src="js/vue.js"></script>
    </head>
    <body>

    <div id="app">
      <p>{{price}}</p>
      <p>{{new_price}}</p>
      <p>{{href}}</p>
    </div>
    <script>
      // 计算属性,这里的属性指代的就是data里面的内容,官方建议,针对数字的计算和调整,放在计算属性
      var vm = new Vue({
          el: "#app",
          data: {
              price: 10.3333333,
          },
          // 计算属性,重新产生一个新的变量值
          computed: {
              /*
              新的变量名: function(){
                  // 内部必须有返回值,如果要对原有的data里面的属性计算调用,则通过this.变量名来调用
              },
              */
              new_price: function () {
                  return this.price.toFixed(2);
              },
              href: function () {
                  return location.href;
              }
          }
      })
    </script>
    </body>
    </html>

      效果:

    三. 监听属性

      侦听属性,可以帮助我们侦听data某个数据的变化,从而做相应的自定义操作。

      侦听属性是一个对象,它的键是要监听的对象或者变量,值一般是函数,当侦听的data数据发生变化时,会执行的对应函数,这个函数在被调用时,vue会传入两个实参,第一个是变化前的数据值,第二个是变化后的数据值。

      示例:

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>监听属性(侦听属性)</title>
      <script src="js/vue.js"></script>
    </head>
    <body>
    <div id="app">
      <p>{{num}}</p>
      <button @click="num++">投票</button>
    </div>
    <script>
      var vm = new Vue({
          el: "#app",
          data: {
              num: 0,
          },
          // 监听属性,监控data属性的变化,一旦指定的属性发生值的变化时,则vue会自动调用watch里面的同名属性对应的函数,并且把修改后的值和修改前的值作为参数传递进去。
          watch: {
              num: function (new_data, old_data) {
                  console.log(new_data, old_data);
                  if (this.num > 3){
                      this.num = 3;
                  }
              }
          }
      })
    </script>
    </body>
    </html>

      效果:

      案例(实现省市区的三级联动):

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>省市区的三级联动</title>
      <script src="js/vue.js"></script>
    </head>
    <body>

    <div id="app">
      地址:
      <select name="" v-model="province_id">
          <option value="0">请选择省份</option>
          <option v-for="province in province_list" :value="province.id">{{province.name}}</option>
      </select>
      <select name="" v-model="city_id">
          <option value="0">请选择城市</option>
          <option v-if="city.parent_id == province_id" v-for="city in city_list" :value="city.id">{{city.name}}</option>
      </select>
      <select name="" v-model="area_id">
          <option value="0">请选择地区</option>
          <option v-if="area.parent_id == city_id" v-for="area in area_list" :value="area.id">{{area.name}}</option>
      </select>
    </div>
    <script>
      var vm = new Vue({
          el: "#app",
          data: {
              province_id: 0,
              city_id: 0,
              area_id: 0,
              province_list: [
                  {"id":1,"name":"北京市"},
                  {"id":2,"name":"广东省"},
              ],
              city_list: [],
              area_list: [],
          },
          // 侦听属性
          watch: {
              province_id (){
                  // 假设ajax从后端获取的城市列表数据
                  this.city_list = [
                      {"parent_id":1,"id":1,"name":"海淀区"},
                      {"parent_id":1,"id":2,"name":"昌平区"},
                      {"parent_id":2,"id":3,"name":"广州市"},
                      {"parent_id":2,"id":4,"name":"深圳市"},
                  ],
                  this.city_id = 0,
                  this.area_id = 0
              },
              city_id(){
                  this.area_list = [
                      {"parent_id":1,"id":1,"name":"中关村"},
                      {"parent_id":1,"id":2,"name":"清华园"},
                      {"parent_id":2,"id":3,"name":"沙河"},
                      {"parent_id":2,"id":4,"name":"回龙观"},
                      {"parent_id":3,"id":5,"name":"天河区"},
                      {"parent_id":3,"id":6,"name":"番禺区"},
                      {"parent_id":4,"id":7,"name":"南山区"},
                      {"parent_id":4,"id":8,"name":"宝安区"},
                  ]
              }
          }
      })
    </script>
    </body>
    </html>

      效果:

    四. vue对象的生命周期

      每个Vue对象在创建时都要经过一系列的初始化过程。在这个过程中Vue.js会自动运行一些叫做生命周期的的钩子函数,我们可以使用这些函数,在对象创建的不同阶段加上我们需要的代码,实现特定的功能。

      示例:

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>vue对象的生命周期</title>
      <script src="js/vue.js"></script>
    </head>
    <body>
    <div id="app">
      <p>{{num}}</p>
      <button @click="num++">投票</button>
    </div>
    <script>
      var vm = new Vue({
          el: "#app",
          data: {
              num: 10,
          },
          // 8个钩子函数,常用的有6个下面列举出来的。还有2个不常用分别是:destroy和bdforeDestroy

          // bdforeCreate会在vm对象创建实例化以后,初始化vm内部数据之前调用
          beforeCreate(){
              console.log("----------beforeCreate start---------");
              console.log(this);
              console.log(this.$el); // 还没有对视图模板进行初始化
              console.log(this.num); // 还没有对数据进行初始化
              console.log("##########beforeCreate end#########");
          },
          // created 在vm对象实例化并初始化数据以后,视图模板加载之前调用
          // 一般情况下,会在这里编写ajax代码,从服务器端获取数据并赋值给data里面的数据
          created(){
              console.log("----------created start---------");
              console.log(this);
              console.log(this.$el); // 还没有对视图模板进行初始化
              console.log(this.num); // 此时已经可以拿到数据了
              console.log("##########created end#########");
          },
          // beforeMount 在加载视图以后,给数据赋值之前调用
          beforeMount(){
              console.log("----------beforeMount start---------");
              console.log(this);
              console.log(this.$el); // 还没有对视图模板进行初始化
              console.log(this.num); // 此时已经可以拿到数据了
              console.log("##########beforeMount end#########");
          },
          // 加载视图并进行数据赋值以后调用
          // 一般情况下,会在这里编写操作界面的代码,调整样式,制作初始化的js特效
          mounted(){
              console.log("----------mounted start---------");
              console.log(this);
              console.log(this.$el);
              console.log(this.num);
              console.log("##########mounted end#########");
          },
          // 更新数据时,修改data数据以后,对模板的数据赋值之前调用
          beforeUpdate(){
              console.log("----------beforeUpdate start---------");
              console.log(this);
              console.log(this.$el.innerHTML);
              console.log(this.num);
              console.log("##########beforeUpdate end#########");
          },
          // 更新数据完成以后调用
          updated(){
              console.log("----------updated start---------");
              console.log(this);
              console.log(this.$el.innerHTML);
              console.log(this.num);
              console.log("##########updated end#########");
          }

      })
    </script>
    </body>
    </html>

    五. 阻止事件冒泡和阻止元素的默认行为

    1.阻止事件冒泡

      什么是事件冒泡?  

        事件绑定时,如果同时给父子元素绑定同名事件,则在子元素触发事件以后,父元素的同名事件也会触发到,这种现象就是事件冒泡.

      好处:一个触发,多次执行

        利用事件冒泡的好处,可以实现事件委托.

      坏处:形成事件的联动反应.

      下面我们先一起来回顾一下js原生阻止的事件冒泡

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title></title>
      <style>
          .father{
              300px;
              height: 300px;
              background: green;
          }
          .son{
              100px;
              height: 100px;
              background: red;
          }
      </style>
    </head>
    <body>

    <div class="father">
      <div class="son"></div>
    </div>
    <ul id="content_list">
      <li>子元素1</li>
      <li>子元素2</li>
      <li>子元素3</li>
      <li>子元素4</li>
      <li>子元素5</li>
      <li>子元素6</li>
      <li>子元素7</li>
      <li>子元素8</li>
    </ul>

    <script>
      var fa_div = document.getElementsByClassName("father")[0];
      var son_div = document.getElementsByClassName("son")[0];
      fa_div.onclick = function () {
          alert("父元素");
      };
      son_div.onclick = function (e) {
          alert("子元素");
          e.stopPropagation(); // 原生的js阻止事件冒泡
      };

      // 批量添加事件
      // var li_list = document.getElementsByTagName("li");
      // for (let i = 0; i < li_list.length; i++){
      //     console.log(li_list[i]);
      //     li_list[i].onclick = function () { // 批量绑定事件,当数据量非常大时,会出现页面加载慢。
      //         console.log(this.innerHTML);
      //     }
      // }
      // 为了解决上的问题,我们可以利用事件委托来完成。
      // 事件委托:利用事件冒泡的特性,把子元素要执行的代码,委托给父元素来执行
      var fa_ul = document.getElementById("content_list");
      fa_ul.onclick = function (e) {
          console.log(e); // 事件对象:浏览器会把本次事件相关的内容和属性,封装成一个对象作为参数提供给我们
          console.log(e.target); // 事件触发对象
          let _this = e.target;
          console.log(_this.innerHTML);
      }

    </script>

    </body>
    </html>

      下面我们看一下vue的事件冒泡和阻止事件冒泡:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>vue的事件冒泡和阻止事件冒泡</title>
        <script src="js/vue.js"></script>
        <style>
            .father{
                300px;
                height: 300px;
                color: white;
                background: green;
            }
            .son{
                 100px;
                height: 100px;
                background: red;
            }
        </style>
    </head>
    <body>
    
    <div id="app">
        <div class="father" @click="add">
            <h3>{{num}}</h3>
            <!--使用 事件名称.stop 即可阻止事件冒泡-->
            <div class="son" @click.stop="add">
                点击子盒子
            </div>
        </div>
    </div>
    
    <script>
        var vm = new Vue({
            el: "#app",
            data: {
                num: 0,
            },
            methods: {
                add(){
                    this.num++;
                }
            }
        })
    
    </script>
    
    </body>
    </html>
    

      效果:

    2. 阻止元素的默认行为

      先看没有阻止的一个效果:

      代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>阻止元素的默认行为</title>
        <script src="js/vue.js"></script>
    </head>
    <body>
    <div id="app">
        <a href="" @click="add">a标签</a>
    </div>
    <script>
        var vm = new Vue({
            el: "#app",
            data: {
    
            },
            methods: {
                add(){
                    alert("点击了a标签!");
                }
            }
        })
    </script>
    </body>
    </html>
    

      效果:(注意看刷新按钮)

      下面来看一下vue阻止元素的默认行为。

      代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>阻止元素的默认行为</title>
        <script src="js/vue.js"></script>
    </head>
    <body>
    <div id="app">
        <a href="" @click.prevent="add">a标签</a>
    </div>
    <script>
        var vm = new Vue({
            el: "#app",
            data: {
    
            },
            methods: {
                add(){
                    alert("点击了a标签!");
                }
            }
        })
    </script>
    </body>
    </html>
    

      效果:(注意看刷新按钮)

    六. 综合案例-计划列表

      首先我们看下初识页面代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>ToDoList案例</title>
        <style>
            .list_con {
                 600px;
                margin: 50px auto 0;
            }
    
            .inputtxt {
                 550px;
                height: 30px;
                border: 1px solid #ccc;
                padding: 0;
                text-indent: 10px;
            }
    
            .inputbtn {
                 40px;
                height: 32px;
                padding: 0;
                border: 1px solid #ccc;
            }
    
            .list {
                padding: 0;
                list-style: none;
                margin-top: 20px;
            }
    
            .list li {
                height: 40px;
                line-height: 40px;
                border-bottom: 1px solid #ccc;
            }
    
            .list li span {
                float: left;
            }
    
            .list li a {
                float: right;
                text-decoration: none;
                margin: 0 10px;
            }
        </style>
    </head>
    <body>
    <div id="ToDoList" class="list_con">
        <h2>To do list</h2>
        <input type="text" name="" id="txt1" class="inputtxt">
        <input type="button" name="" value="增加" id="btn1" class="inputbtn">
    
        <ul id="list" class="list">
            <!-- javascript:void(0); # 阻止a标签跳转 -->
            <li>
                <span>学习html</span>
                <a href="javascript:void(0);" class="up"> ↑ </a>
                <a href="javascript:void(0);" class="down"> ↓ </a>
                <a href="javascript:void(0);" class="del">删除</a>
            </li>
            <li>
                <span>学习css</span>
                <a href="javascript:void(0);" class="up"> ↑ </a>
                <a href="javascript:void(0);" class="down"> ↓ </a>
                <a href="javascript:void(0);" class="del">删除</a>
            </li>
            <li>
                <span>学习javascript</span>
                <a href="javascript:void(0);" class="up"> ↑ </a>
                <a href="javascript:void(0);" class="down"> ↓ </a>
                <a href="javascript:void(0);" class="del">删除</a>
            </li>
        </ul>
    </div>
    </body>
    </html>
    

      效果:

      下面我们通过vue来实现页面的列表计划管理。

      首先进行需求分析:

    1. 把计划数据展示到页面中

      1. 当用户填写计划以后,点击"增加"按钮时,把数据添加到计划列表中,展示出来

        1. 当用户点击"删除"按钮,把当前一行的计划数据移除掉

          1. 当用户点击"↑",则需要把当前一行和上一行数据之间的位置,进行互换

            1. 当用户点击"↓",则需要把当前一行和下一行数据之间的位置,进行互换

      然后,开始一项一项的完成需求:

      代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>vue完成ToDoList需求</title>
        <script src="js/vue.js"></script>
        <style>
            .list_con {
                 600px;
                margin: 50px auto 0;
            }
    
            .inputtxt {
                 550px;
                height: 30px;
                border: 1px solid #ccc;
                padding: 0;
                text-indent: 10px;
            }
    
            .inputbtn {
                 40px;
                height: 32px;
                padding: 0;
                border: 1px solid #ccc;
            }
    
            .list {
                padding: 0;
                list-style: none;
                margin-top: 20px;
            }
    
            .list li {
                height: 40px;
                line-height: 40px;
                border-bottom: 1px solid #ccc;
            }
    
            .list li span {
                float: left;
            }
    
            .list li a {
                float: right;
                text-decoration: none;
                margin: 0 10px;
            }
        </style>
    </head>
    <body>
    <div id="ToDoList" class="list_con">
        <h2>To do list</h2>
        <input type="text" name="" v-model="plan" id="txt1" class="inputtxt">
        <input type="button" name="" @click="add_data" value="增加" id="btn1" class="inputbtn">
    
        <ul id="list" class="list">
            <!-- javascript:void(0); # 阻止a标签跳转 -->
            <li v-for="item,index in data_list">
                <span>{{item.title}}</span>
                <a href="javascript:void(0);" @click="move_up(index)" class="up"> ↑ </a>
                <a href="javascript:void(0);" @click="move_down(index)" class="down"> ↓ </a>
                <a href="javascript:void(0);" @click="del_data(index)" class="del">删除</a>
            </li>
    
        </ul>
    </div>
    <script>
        var vm = new Vue({
            el: "#ToDoList",
            data: {
                plan: "",
                data_list: [
                    {"title":"学习html"},
                    {"title":"学习css"},
                    {"title":"学习javascript"},
                ]
            },
            methods: {
                // 添加计划
                add_data(){
                    if (this.plan.length > 0){
                        // this.data_list.push({"title": this.plan});  // 追加
                        // this.data_list.unshift({"title": this.plan});  // 前置插入
                        // 或者使用数组的splice方法
                        // 尾部追加 data_list.splice(data_list.length + 1, 0, "添加元素")
                        // this.data_list.splice(this.data_list.length + 1, 0, {"title": this.plan});
                        // 头部添加 data_list.splice(0, 0, "添加元素")
                        this.data_list.splice(0, 0, {"title": this.plan});
                    }
                },
                // 删除计划
                del_data(index){
                    console.log(index);  // 获取当前删除元素的index
                    // 数组的splice删除的语法:data_list.splice(index, 1)
                    this.data_list.splice(index, 1);
                },
                // 向上移动计划
                move_up(index){
                    if (index > 0){
                        // 1. 先把当前要移动的元素提取出来
                        // let current = this.data_list[index];
                        let current = this.data_list.splice(index, 1)[0];
                        // console.log(current);
                        // 2. 再把提取出来的元素放到index - 1的位置
                        this.data_list.splice(index - 1, 0, current);
                    }
                },
                // 向下移动计划
                move_down(index){
                    // 1. 先把当前要移动的元素提取出来
                    let current = this.data_list.splice(index, 1)[0];
                    // 2. 再把提取出来的元素放在index + 1 的位置
                    this.data_list.splice(index + 1, 0, current);
                }
            }
        })
    </script>
    </body>
    </html>
    

      效果:

     

  • 相关阅读:
    .Net学习难点讨论系列2 – 细说C#中new关键字与多态
    [翻译]搜索关键字 – 管道与过滤器模式(PipesandFilters)与装饰模式(Decorator)之间的关系
    .Net学习难点讨论系列1 – 委托与事件之事件
    [翻译]Popfly系列课程1 Popfly课程计划概览
    常用桌面虚拟化软件横向对比
    各种算法的C#实现系列1 合并排序的原理及代码分析
    博客园安家
    疑:Microsoft® Silverlight™ Tools for Visual Studio 2008 SP1的版本让人困惑
    stream_socket_client
    stream_socket_client2
  • 原文地址:https://www.cnblogs.com/zengxiaowen/p/11838820.html
Copyright © 2011-2022 走看看