Vue(监测数据改变、收集表单数据、过滤器)

一、监测数据改变原理

1. 监测对象数据改变原理

当数据发生改变之后:直接会显示数据改变(一种强硬写法)

  let data = { name: "北京大学", address: "北京" };
    // 以下通过temp进行监视:还得还原temp值(硬写)
    let temp = "北京大学";
    setInterval(() => {
      if (data.name !== temp) {
        console.log("name被改了");
        temp = data.name;
      }
    }, 100);

 当对象数据发生变化之后就会调用观察构造函数

  • 通过构造观察构造函数
  • 将传入数据转为数组并进行遍历
  • 遍历加入回调函数(箭头函数),通过defineProperty添加或者获取数据
  • 然后进行实例化并吧实例化得数据给vm实例和data
let data = { name: "北京大学", address: "北京" };
const obs = new Observer(data);
    // 准备vm实例
    let vm = {};
    //三连等就可以通过data获取实例对象
    vm._data = data = obs;
    // 创建观察构造函数
    function Observer(obj) {
      // 汇总对象的多所有属性形成数组
      const keys = Object.keys(obj);
        //遍历当前数组
      keys.forEach((k) => {
        // 当前this指的是实例对象(相当于给实例对象中添加属性)当前this是实例对象
        Object.defineProperty(this, k, {
          get() {
            // 返回传入对象的值
            return obj[k];
          },
          set(val) {
            // 只要对象内容发生修改,就会调用set进行修改然后解析模板
            console.log(`此处修改${k},需要重解析`);
            obj[k] = vla;
          },
        });
      });
    } 

2. 监测对象数据改变中的v-set使用

添加一个初始没有在data中定义一个性别属性值(没有响应式)

  • 在初始定义得值模板解析之后都会存在getter和setter,但是通过直接添加是没有响应式

   <div id="root">
      <h2>学校名称:{{school.name}}</h2>
      <h2>学校地址:{{school.address}}</h2>
      <h2>校长名字:{{school.leader}}</h2>
      <hr />
      <!-- ---------------------------------- -->
      <h2>学生信息</h2>
      <button @click="addSex">添加一个性别属性,默认值是男</button>
      <h2>学生姓名:{{students.name}}</h2>
      <!-- 添加 -->
      <h2 v-if="students.sex">学生性别:{{students.sex}}</h2>
      <h2>
        学生年龄:真实年龄{{students.age.rAge}},对外年龄{{students.age.rAge}}
      </h2>
      <ul>
        <li v-for="(f,index) in students.friends" :key="index">
          {{f.name}}--{{f.age}}
        </li>
      </ul>
    </div>
  </body>
  <script>
    Vue.config.production = false;
    const vm = new Vue({
      el: "#root",
      data: {
        school: { name: "北京大学", address: "北京" },
        students: {
          name: "tom",
          age: { rAge: 40, sAge: 20 },
          friends: [
            {
              name: "toy",
              age: 15,
            },
            {
              name: "boom",
              age: 20,
            },
          ],
        },
      },
      methods: {
        //添加一个属性得api
        addSex() {
          // Vue.set(this.students, "sex", "男");
          this.$set(this.students, "sex", "男");
        },
      },
    });
  </script>

 

 解决:

  • 通过Vue.set(target,name,value) 进行响应式添加

  • 通过vm.$set(target,name,value)进行响应式添加

 

 

 

 

 

3. 监测数组数据改变 

监测对象数据时候是通过getter和setter进行监测和响应式获取数据

 

但是在监测数组数据变化时候就不奏效:数组在vue中没有getter和setter方法

 说明数组下标修改数据不会被vue监视

 

解决: 数组对于元素得增删改查通过数组方法(非arr数组方法)

  • push : 末尾添加(返回index)

 

  • pop :末尾删除

  • shift :第一个删除(返回删除数组元素)

 

  • unshift :第一个添加

  • splice(a,b,item) :指定位置删除:标识从a开始删除b个插入item

 这里补充上一章改变马老师响应式的解决方法:

 this.persons.splice(0, 1, {
            id: "001",
            name: "马老师",
            age: 50,
            sex: "男",
          });
  • sort :排列

  • reverse : 反转

  <div id="root">    
  <h2>爱好</h2>
      <ul>
        <!-- 遍历对象或者数组都是v-for指令 -->
        <li v-for="(h,index) in students.hobby" :key="index">{{h}}</li>
      </ul>
    </div>
 data: {
        school: {
          name: "北京大学",
          address: "北京",
        },
        students: {
          name: "tom",
          age: {
            rAge: 40,
            sAge: 20,
          },
          hobby: ["抽烟", "喝酒", "烫头"],
          friends: [
            {
              name: "toy",
              age: 15,
            },
            {
              name: "boom",
              age: 20,
            },
          ],
        },
      },

判断数组方法得区别:

  • 数组方法等于数组原型对象上的方法

  •  vue上的数组方法对模板进行解析

 当然也可以直接通过$set-api进行添加响应式:

 

 

 4. Vue监视数据原理总结

vue会监视data中所有层次的数据

如何监视对象中的数据?

  • 通过setter实现监视,并且new Vue时候就要传入检测数据
    (1)对象中后追加的属性,Vue默认不做响应处理
    (2)如果需要给后追加的属性做响应式,请使用如下API:
    Vue.set(target,propertyName/index,value)或者
    vm.$set(target,propertyName/index,value)

如何检测数组中的数据?

  • 通过包裹数组更新元素的方法实现,本质就是做了两件事:
    (1)调用原生对应的方法对数组进行更新
    (2)重新解析模板,进而更新页面

在Vue修改数组中的某个元素要用如下方法

  1. 使用这些API:push(),pop(),shift(),unshift(),splice(),sort(),reverse()

  2. Vue.set(),vm.$set()

    >>> 特别注意:Vue.set()和vm.$set()不能给vm或vm的根数据对象添加属性

二、收集表单数据 通过v-model

1. 表单数据通过vue管理

  • 账号、密码直接使用v-model进行双向绑定

  • 单选框通过双向绑定之后还需要给每个单选添加一个value值:需要默认值直接在vue的data中添加value值

  • 多选框 

    • 通过双向绑定之后,给每个选项添加一个value值

    • 没有配置input的value属性,那么收集的就是checked(勾选or 未勾选:都是布尔值)

  • select选项框

    • 也是双向绑定和数据的value值,然后通过设置选项初始值进行设置默认选项

  • 最后通过json数据处理再通过form进行数据传输或者btn进行传输上传

备注:v-model的三个修饰符:
                    lazy:失去焦点再收集数据(而不是实时收集)
                    number:输入字符串转为有效的数字
                    trim:输入首位空格过滤

 <div id="root">
      <!-- 原本使用action通过ajax页面不刷新发送数据 -->
       <!--这里通过表单绑定一个提交事件,并阻止默认事件-->
      <form @submit.prevent="demo">
        账号:<input type="text" v-model.trim="useInfo.account" />
        <br />
        <br />
        密码:<input type="text" v-model="useInfo.passward" />
        <br />
        年龄:<input type="number" v-model.number="useInfo.age" />
        <br />
        <br />
        性别:
        <!-- 区分性别单选使用name:并且没有value值 -->
        男<input type="radio" name="sex" v-model="useInfo.sex" value="male" />
        女<input type="radio" name="sex" v-model="useInfo.sex" value="fmale" />
        <br />
        <br />
        爱好:
        <!-- 多选框 :数组-->
        学习<input type="checkbox" v-model="useInfo.hobby" value="learn" />
        <!--  -->
        打游戏<input type="checkbox" v-model="useInfo.hobby" value="game" />
        <!--  -->
        吃饭<input type="checkbox" v-model="useInfo.hobby" value="eat" />
        <br />
        <br />
        所选地区:<select v-model="useInfo.city">
          <option value="">请选择校区</option>
          <option value="beijing">北京</option>
          <option value="shanghai">上海</option>
          <option value="shenzhen">深圳</option>
        </select>
        <br />
        <br />
        其他信息
        <textarea v-model.lazy="useInfo.other"></textarea>
        <br />
        <br />
        //这里的checkboc的只接受布尔值
        <input type="checkbox" v-model="useInfo.aggree" />阅读并接收信息:<a
          href="www.baidu.com"
          >请详细阅读</a
        >

        <button>注册</button>
      </form>
    </div>
    <script>
      Vue.config.production = false;
      const vm = new Vue({
        el: "#root",
        data: {
          useInfo: {
            account: "",
            passward: "",
            sex: "male",
            hobby: [],
            city: "beijing",
            other: "",
            aggree: "",
            age: 18,
          },
        },
        methods: {
          demo() {
            console.log(JSON.stringify(this.useInfo));
          },
        },
      });
    </script>

三、过滤器 (非必要)

需求:页面中显示格式化后的时间:时间戳

 Date.now()生成的数据转为年月日-时分秒

解决:第三方库moment(重量级)/day(轻量级)是第三方的库两个库api同步引入到文件中

https://github.com/iamkun/dayjs/blob/dev/docs/zh-cn/README.zh-CN.mdicon-default.png?t=N3I4https://github.com/iamkun/dayjs/blob/dev/docs/zh-cn/README.zh-CN.mdapi

  1. 计算属性:

 computed: {
        fameTime() {
          return dayjs(this.time).format("YYYY-MM-DD HH-mm-ss");
        },
      },

2. 方法:

 methods: {
        getFumTime() {
          return dayjs(this.time).format("YYYY-MM-DD HH-mm-ss");
        },
      },

3. 过滤器实现:

    filters: {
        timeFormater(value) {      
          return dayjs(value).format("YYYY-MM-DD HH-mm-ss");
        },
      
      }

   filters: {
        //这里可以给过滤函数添加第二个参数作为默认参数进行转换格式
        timeFormater(value,str='YYYY-MM-DD HH-mm-ss') {      
          return dayjs(value).format(str);
        },
      
      }

过滤器:数据 | 过滤

过滤过程:将数据传给过滤器函数然后使用通用api-format返回一个格式化值

过滤器还可以使用串联过滤方式进行过滤:查看下方的串联过滤器使用方式

还有过滤器可以声名全局过滤器

  Vue.filter("mySilice", function (value) {
      return value.slice(0, 4);
    });

    <div id="root">
      <h2>显示格式化后的时间</h2>
      <!-- 计算属性实现:时间戳变为可以看懂的时间 -->
      <h3>现在的时间是:{{fameTime}}</h3>
      <!-- 方法实现:时间戳变为可以看懂的时间:方法再插值语法中需要使用() -->
      <h3>现在的时间是:{{getFumTime()}}</h3>
      <!-- 过滤器属性实现:时间戳变为可以看懂的时间(过滤器本质就是函数) -->
      <h3>现在的时间是:{{time | timeFormater}}</h3>
      <!-- 多个过滤器可以串联 -->
      <h3>
        现在的时间是:{{time | timeFormater("YYYY-MM-DD HH-mm-ss") | mySilice}}
      </h3>
      <!-- 除了插值语法可以使用过滤器:数据绑定也可以:查看控制台结构,但是不允许使用双向绑定 -->
      <h2 :bind="msg | mySilice">这里是数据绑定过滤器用法</h2>
    </div>
    <!-- 使用全局过滤器:每一个过滤器都是单一包裹的 -->
    <div id="root2">
      <h2>{{msg | mySilice}}</h2>
    </div>
  </body>
  <script>
    Vue.config.production = false;
    // 全局过滤器
    Vue.filter("mySilice", function (value) {
      return value.slice(0, 4);
    });
    const vm = new Vue({
      el: "#root",
      data: {
        time: 1681109185734,
        msg: "nihaoya",
      },
      // 通过方法直接使用库api进行数据转换
      computed: {
        fameTime() {
          return dayjs(this.time).format("YYYY-MM-DD HH-mm-ss");
        },
      },
      methods: {
        getFumTime() {
          return dayjs(this.time).format("YYYY-MM-DD HH-mm-ss");
        },
      },
      // 局部过滤器
      filters: {
        //使用es6中形参默认值:将传入的参数值转为以下格式
        timeFormater(value, str = "YYYY-MM-DD") {
          // console.log("@", value);
          // 这里的模板字符可以使用字符串格式(作为第二个参数)
          // return dayjs(value).format("YYYY-MM-DD HH-mm-ss");
          return dayjs(value).format(str);
        },
        mySilice(value) {
          return value.slice(0, 4);
        },
      },
    });
    // 第二个实例
    const vm2 = new Vue({
      el: "#root2",
      data: {
        msg: "xlf-nihao",
      },
    });
  </script>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值