Vue — 第二天(v-model和过滤器)

VUE-02-v-model和过滤器

昨日反馈与回顾

代码仓库的问题

不要修改你克隆下来的仓库中任意代码,否则,下次pull时,可能会报错,从而得到不到最新的代码。

在这里插入图片描述

如果已经遇到了这个冲突:

  • 解决冲突(git 中解决冲突)
  • 把关键代码拷出来,放弃这个仓库,重新再次clone(后续git pull)

处理样式

样式由两个部分决定:

  • class
  • style

v-bind绑定class

目标:知道通过vue怎么去操作类,也就是class属性的值。

动态绑定class属性,有三种方式:

  • 三元运算符
  • 绑定对象:如果属性值为true,则添加属性名给class
  • 绑定数组

代码:

<style>

        #app{width:500px;margin:50px auto;border:3px solid red;}
        .box{
           border:3px solid black;
           margin:5px;
        }
        .bg-blue{
            background-color: blue;
        }
        .bg-green{
            background-color: green;
        }
        .fs20{font-size:20px;}
        .tr{text-align: right;}
    </style>
</head>
<body>
  
    <div id="app">
        <h3 class="title">v-bind-绑定class</h3>
        <!-- 元素自有class和v-bind绑定的class会协同工作,一起生效 -->
        <div class="box" v-bind:class="cla ? 'bg-blue': 'bg-green'">
            1. 三元表达式
        </div>

        <!-- 如果对象中的属性值是true,
            则把对象中的属性名添加到类名中 -->
        <div class="box" :class="claObj">
            2. 绑定对象
        </div>

        <!-- 数组中元素是字符串,
            它会把所有的元素全添加到class中 -->
        <div class="box" :class="claArr">
            3. 绑定数组
        </div>
        <button @click="hAddClass">补充一个class</button>
    </div>
    <script>
        // v-bind 是用来动态绑定元素的属性,而class也是元素的属性
        // 目标: 可以通过动绑定class来控制样式 。

        // 方式:
        // 1. 三元表达式
        // 2. 绑定对象
        // 3. 绑定数组

        const vm = new Vue({
            el: "#app",
            // el: document.getElementById("app"),
            data: {
                cla: false,
                claObj: {
                    fs20: true,
                    tr: true
                },
                claArr:['fs20','tr', 'abc']
            },
            methods: {
                hAddClass () {
                    // 向数组中添加一个类 'c-red'
                    this.claArr.push('c-red')
                }
            }
        })
    </script>

:class 动态绑定类名 class 原生属性,可以同时存在,他们包含的所有类会合并在一起生效。

v-bind绑定style

目标:知道通过vue怎么去操作行内样式,也就是style属性的值。

动态绑定style属性有两种方式:

  • 对象形式
  • 数组形式

v-bind绑定style使用对象:

<div id="app">
        <h3 class="title">v-bind-绑定style</h3>
    
       <!-- 把对象的属性名和属性值直接设置到style中 -->
        <div class="box" :style="styleObj">
            1. 绑定对象
        </div>

        <!-- 把数组中的每一个元素(对象),取出来,组成style -->
        <div class="box" :style="styleArr">
            2. 绑定数组
        </div>
        <button @click="hBlack">改成黑色的字</button>
    </div>
    <script>
        // v-bind 是用来动态绑定元素的属性,而style也是元素的属性
        // 目标: 可以通过动绑定style来控制样式 。

        // 方式:
        // 1. 绑定对象
        // 2. 绑定数组

        const vm = new Vue({
            el: "#app",
            // el: document.getElementById("app"),
            data: {
                styleObj: {
                    color:'red',
                    // 如果属性名有-,则要加''
                    'background-color':'blue'
                },
                // 数组中的每一项都是一个对象,其中以键值对的格式设置了style
                styleArr:[ {color:'red','font-weight':'bold'}, {'font-size':'50px'} ]
            },
            methods: {
                hBlack () {
                    // 直接把styleObj中的color设置成black
                    this.styleObj.color = "black"
                   
                }
            }
        })
    </script>

如果同时存在 :style 和 style vue操作的样式会覆盖默认样式。

总结:

  • :style 使用对象 {css属性名:css属性值}
  • :style 使用数组 [{css属性名:css属性值}]

v-model

目标

知道如何绑定多种类型的表单元素

基本使用

<div id="app">
        <h3 class="title">v-model</h3>
        用户名:<input v-model="userName" >
        <br>
         <!-- 
             不是表单元素不能用
             <div v-model="userName" ></div> 
        -->
        <button @click="userName=123">123</button>
        <button @click="hPrint">打出userName</button>
    </div>
    <script>
        // v-model 
        // 是用来对表单元素进行双向绑定的。
        //   表单元素: 用户可以进行交互的元素,textarea,select,input,checkbox...
        //   双向绑定: 
        //      -1. 用户在input中的修改,会影响到数据
        //      -2. 数据的修改会影响input

        // 格式:<表单元素 v-model="数据项">

        const vm = new Vue({
            el: "#app",
            data: {
                userName: '小王'
            },
            methods: {
                hPrint () {
                    console.log( this.userName )
                }
            }
            
        })
    </script>

表单元素

  • 文本域
  • 复选框
  • 单选框
  • 下拉框
<div id="app">
        <h3 class="title">v-model</h3>
        <div class="box">
            <!-- 1. 普通文本框  -->
            用户名:<input v-model="userName" >
        </div>

        <div class="box">
            <!-- 2. 单选  
            由value来决定用户选中的值 -->
            性别:
            <input type="radio" value="" v-model="gender">帅哥
            <input type="radio" value="" v-model="gender">美女
        </div>

        <div class="box">
            <!-- 3. 复选  
            由value来决定用户选中的值,结果放在一个数组中 -->
            爱好:
            <input type="checkbox" value="读书" v-model="hobby">读书
            <input type="checkbox" value="sport" v-model="hobby">运动
            <input type="checkbox" value="k歌" v-model="hobby">k歌
        </div>

        <div class="box">
            <!-- 4. 文本域  
            注: 不能把内容写在元素中: 
            <textarea v-model="info">abc</textarea>
        -->
            个人说明:<textarea v-model="info"></textarea>
        </div>

        <div class="box">
        <!-- 5. 下拉
           选中的值是以value为准
        -->
            位置: 
            <select  v-model="city">
                <option value="1">北京</option>
                <option value="2">上海</option>
                <option value="3">潜江</option>
            </select>
        </div>

        <div class="box">
            <!-- 6. 单个复选框(是否同意)
                如果为true,则选中,false,不选中
            -->
            愿意吗?<input type="checkbox" v-model="isChecked">
        </div>
        <button @click="hPrint">打印结果</button>
    </div>
    <script>
        // v-model 
        // 是用来对表单元素进行双向绑定的。
                // 1. 普通文本框 
                // 2. 单选
                // 3. 复选
                // 4. 文本域
                // 5. 下拉
                // 6. 单个复选框(是否同意)
        const vm = new Vue({
            el: "#app",
            data: {
                userName: '小王子',
                gender:'男',  // 单选
                hobby:['读书'], // 多选
                info: '自我介绍,如下:白玉谁家郎',
                city: 1,
                isChecked: false
            },
            methods: {
                hPrint () {
                    console.log( this.userName )
                    console.log( this.gender )
                    console.log( this.hobby )
                    console.log( this.info )
                    console.log( this.city )
                    console.log( this.isChecked )
                }
            }
            
        })
    </script>

修饰符

lazy

在默认情况下,v-model 在每次 input 事件触发后将输入框的值与数据进行同步。你可以添加 lazy 修饰符,从而转为在 change 事件_之后_进行同步:

<!-- 在“change”时而非“input”时更新 -->
<input v-model.lazy="msg">

number

如果想自动将用户的输入值转为数值类型,可以给 v-model 添加 number 修饰符:

<input v-model.number="age" type="number">

这通常很有用,因为即使在 type="number" 时,HTML 输入元素的值也总会返回字符串。如果这个值无法被 parseFloat() 解析,则会返回原始的值。

trim

如果要自动过滤用户输入的首尾空白字符,可以给 v-model 添加 trim 修饰符:

<input v-model.trim="msg">
<div id="app">
        <h3 class="title">v-model</h3>
        <div class="box">
            <!-- 1. lazy  -->
            <!-- 不加lazy:<input v-model="userName" >
            {{userName}} -->
            <br>
            加lazy:<input v-model.lazy="userName" >
            {{userName}}

        </div>

        <div class="box">
            <!-- 2. number  
            不加number,就是一个普通的字符串
            加了number,会尽量帮你转成数值,转不成,也不会报错
            -->
           
            <br>
            加number:<input v-model.number="age" >
            {{age}}

        </div>


        <div class="box">
            <!-- 3. trim  
                自动把内容中的前后空格去掉
            -->
        
            <br>
            <input v-model.trim="email" >
            内容的长度:{{email.length}}
        </div>
    </div>
    <script>
        // v-model 
        //     v-model的三个修饰符
        // 1. lazy    -->   v-model.lazy="userName"
        //    默认情况,v-model只要用户修改了input中的内容(在每次input事件之后)就会与数据进行同步
        //    如果加了lazy之后,则在用户完成了输入,鼠标失焦之后(相当于change),才会与数据同步。

        // 2. number
        //    自动转成数值的格式
        
        // 3. trim
        //    把内容中的前后空格去掉

        const vm = new Vue({
            el: "#app",
            data: {
                userName: '小王',
                age:18,
                email:''

            },
            methods: {
                hPrint () {
                    console.log( this.userName )
                }
            }
            
        })
    </script>

案例-资产列表

在这里插入图片描述

渲染列表

目标:完成表格列表渲染。

需求:

  • 根据data中的数据,进行tr的渲染。
  • 当没有数据的时候,显示暂无数据。

静态页面:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <link rel="stylesheet" href="./bootstrap.min.css">
</head>
<body>
  <div id="app">
    <div class="container">
      <table class="table table-bordered table-hover">
        <thead>
          <tr>
            <th>编号</th>
            <th>资产名称</th>
            <th>创建时间</th>
            <th>操作</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>1</td>
            <td>宝马</td>
            <td>20000</td>
            <td><a href="#">删除</a></td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>
</body>
</html>

准备数据:

list: [
    { id: 1, name: '外套', price: 99 },
    { id: 2, name: '裤子', price: 34 },
    { id: 3, name: '鞋', price: 25.4 },
    { id: 4, name: '头发', price: 19900 }
]

完整的功能实现:

  <div id="app">
    <div class="container">
      <table class="table table-bordered table-hover">
        <thead>
          <tr>
            <th>编号</th>
            <th>资产名称</th>
            <th>创建时间</th>
            <th>操作</th>
          </tr>
        </thead>
        <tbody>
          <!-- <tr v-for="(循环变量,索引变量) in 数据"> -->
          <tr v-for="(item, idx) in list">
            <td>{{item.id}}</td>
            <td>{{item.name}}</td>
            <!-- 如果价格超过100,就有red这个类 -->
            <!-- <td class="red">{{item.price}}</td> -->

            <!-- 三元
            -->
            <!-- <td :class='item.price > 100 ? "red" : ""'>{{item.price}}</td> -->
            
            <!-- 放一个对象
               如果对象中的属性值是true,
               则把对象中的属性名添加到类名中
            -->
            <td :class="{red:item.price>100}">{{item.price}}</td>
           
            <td><a href="#" @click.prevent="hDel(idx)">删除</a></td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>
  <script src="./vue.js"></script>
  <script>
    const vm = new Vue({
      el: '#app',
      data: {
        list: [
            { id: 1, name: '外套', price: 99 },
            { id: 2, name: '裤子', price: 34 },
            { id: 3, name: '鞋', price: 25.4 },
            { id: 4, name: '头发', price: 19900 }
        ]
      }
    })
  </script>

删除功能

目标:完成表格一行删除。

需求:

  • 点击删除按钮,确认框提示
  • 点击确认后,再进行删除
  • 绑定事件,指定处理函数的时候,传入ID
  • 在处理函数中,根据ID进行删除(id===>index====>根据索引删除)

实现:

<td><a @click.prevent="hDel(idx)" href="#">删除</a></td>
methods: {
    hDel (index) {
            console.log('要删除的下标是',index)
            // 删除数组中指定位置的元素
            this.list.splice(index, 1)
          }
}

添加资产

目标:完成表格添加资产。

大致的实现步骤:

  1. 准备一个表单,包含一个输入框,包含一个提交按钮。
  2. 监听提交事件,提取输入框中的内容
  3. 根据输入的内容来组织 资产信息对象 追加到数组中即可
    1. 数据会驱动视图的更新
  4. 清空输入框中的内容

在案例中的代码:

html结构

<!-- 添加资产 -->
<form class="form-inline">
    <div class="form-group">
        <div class="input-group">
            <input type="text" class="form-control" placeholder="资产名称">
        </div>
    </div>
    &nbsp;&nbsp;&nbsp;&nbsp;
    <button class="btn btn-primary">添加资产</button>
</form>

双向绑定输入框

<input v-model.trim="brandName" type="text" class="form-control" placeholder="资产名称">
  • 监听提交事件,且阻止默认提交行为
<form @submit.prevent="addBrand()" class="form-inline">
  • 在处理函数中实现逻辑
        // 添加资产
        addBrand() {
          // 通过v-model绑定输入框,可以实时的获取输入的内容
          // console.log(this.brandName)
          // 严谨判断,未输入内容,提示 + 阻止程序运行
          // trim()是去除字符串左右两侧的空格,然后去判断会更加严谨
          if (!this.brandName.trim()) {
            return alert('请输入资产名称')
          }
          // 组织一个对象:id brandName createTime
          // 正常逻辑:去除数组中最后一项数据的ID累加1即可
          // 极端情况:数组中已经没有数据,此时ID为1即可
          const obj = {
            id: this.list.length ? this.list[this.list.length - 1].id + 1 : 1,
            brandName: this.brandName,
            createTime: new Date()
          }
          // 追加到数组中即可
          this.list.push(obj)
          // 清空输入框
          this.brandName = ''
        }

梳理其它功能

目标:确定还有哪些功能需要完成。

在这里插入图片描述

输入框结构:

      <!-- 搜索 -->
      <form class="form-inline" style="padding: 20px 0">
        <input type="text" class="form-control" placeholder="输入关键字进行搜索">
      </form>
      <!-- 表格 -->

过滤器

目标:

  • 理解过滤器的作用和使用场景
  • 掌握定义和使用过滤器。

理解过滤器

过滤器的作用:转换格式。

生活中的过滤器:

如:把水中的杂质过滤掉。输入过滤器的是脏水,输出的是纯净水。

vue中的过滤器:

- 如:把字符串用0补足6位。输入的是不足6位的字符串,输出的是用0补全之后的字符串。
- 如:把单词首字母转成大写。输入的是普通单词,输出的是首字母大写的单词。

本质就是一个函数

格式x ---过滤器---->  格式y

格式

定义过滤器的格式

new Vue({
      // 过滤器的定义
      filters: {
        // 属性名称(过滤器名称):属性的值(过滤器处理函数)
        myFilter:function(value,其它参数){
        
        }
      }
    })

使用过滤器的格式

// 不带参数
{{ msg | 过滤器}}
// 带参数
{{ msg | 过滤器(参数)}}

示例1:不带参数的过滤器

<div id="app">
    <h3>{{msg}}</h3>

    <!-- 使用过滤器 -->
    <h3>{{msg | f1}}</h3>

    <!-- 使用过滤器 -->
    <h3>{{msg | padding6}}</h3>

</div>

<script>
    // vue中的过滤器
    // 作用: 在显示数据之前,做一次格式转化

    // 定义格式
    // filters: {
    //     过滤器名: function (value,其它参数) {

    //     }
    // }

    // 使用格式 
    // {{ msg | 过滤器}}


    // {{msg}}       =====> console.log(msg)
    // {{msg | f1}}  =====> console.log(   f1(msg)  )

    const vm = new Vue({
        el: "#app",
        data: {
            msg: 'vue'
        },
        // 过滤器列表
        filters: {
            // {{msg | f1}}
            // 会去:
            // 1. 调用f1这个函数,并自动把msg传进来给value
            // 2. 把f1函数的返回值显示出来
            f1 (value) {
                console.log(value)
                return 'hahaha'
            },
            padding6 (str) {
                // 对于字符串,不足6位,
                // 左侧补0
                // String(str) 类型转换
                // padStart: 在左侧补足字符串
                //字符串.padStart(总长度,填充的字符)
                return String(str).padStart(6, "*")
            }
        }
    })
</script>

注意:

  • 它的工作过程就是函数的调用执行过程。

  • 过滤器本质是一个函数:它的接收的参数是格式化之前的数据及格式化的参数,它的返回值是格式化之间的值

示例2:带参数过滤器

定义:

filters: {
            // {{msg | f1}}
            // 会去:
            // 1. 调用f1这个函数,并自动把msg传进来给value
            // 2. 把f1函数的返回值显示出来
            f1 (value) {
                console.log(value)
                return 'hahaha'
            },
            paddingN (str,n) {
                // 对于字符串,不足n位,左侧补0
                // String(str) 类型转换
                // padStart: 在左侧补足字符串
                //字符串.padStart(总长度,填充的字符)
                return String(str).padStart(n, "*")
            }
        }

使用:

{{ "ab" | padding6}}
{{ name | padding(5)}}

注意:

  • 它会自动传入第一个参数。

在这里插入图片描述

过滤器的分类

  • 全局过滤器(在vue实例外部定义,在随后的每个vue实例中均可使用)

    Vue.filter('过滤器名称',function(value){ 
       //管道符前js表达式执行结果 
       // 返回处理好的数据即可 
    })
    
  • 局部过滤器(在vue实例中定义,仅能给当前vue实例管理的视图使用)

总结:

  • 全局 Vue.filter('过滤器名称',(value)=>{ //管道符前js表达式执行结果 // 返回处理好的数据即可 })
  • 局部 new Vue({filters:{'过滤器名称':(value)=>{ //管道符前js表达式执行结果 // 返回处理好的数据即可 }}})

自定义指令

目标:知道如何定义自定义指令,使用自定义指令。

指令(directive)vue提供了v-开头的特殊属性,称之为指令。它提供的指令是有限,如果遇见内置指令无法给你实现的功能,自己封装一个指令(自定义指令)。

定义一个v-focus的指令,作用让input自动获取焦点

全局自定义指令,局部自定义指令

  <div id="app">
    <input type="text" v-focus>
    <input type="text" v-myfocus>
  </div>
  <script src="./vue.js"></script>
  <script>
    // 全局自定义指令
    // Vue.directive('指令的名称','指令配置对象')
    // 参数1:指令的名称,不包含v-,但是在使用指令的时候需要加上v-
    // 参数2:指令配置对象,固定属性 inserted 指定的一个函数,
    //      1. 该函数会在通过指令标记的元素,创建完毕之后执行
    //      2. 该函数有一个默认参数 el 指的是使用这个指令的元素
    Vue.directive('focus',{
      inserted (el) {
        // 获取焦点
        el.focus()
      }
    })


    const vm = new Vue({
      el: '#app',
      // 局部自定义指令
      // vue配置对象提供了一个选项:directives 对应 对象
      directives: {
        // 属性名称(指令的名称):属性的值(指令的配置对象)
        myfocus: {
          inserted (el) {
            el.style.height = '50px'
            el.focus()
          }
        }
      }
    })
  </script>

补充:

  • dom元素提供了focus函数,dom.focus()触发获取焦点事件,自然元素可以获取焦点。

案例-资产列表(续)

用过滤器完成货币格式化显示

filters: {
    $:function(value, _currency) {
        // 全局匹配: 三位连续,且之后也是数值 的数值
        var digitsRE = /(\d{3})(?=\d)/g;
        value = parseFloat(value);
        if (!isFinite(value) || !value && value !== 0) return '';
        _currency = _currency != null ? _currency : '¥';
        // 保留两位小数,并整体转成字符串
        var stringified = Math.abs(value).toFixed(2);

        // 获取整数部分。-3表示倒数3位的位置
        var _int = stringified.slice(0, -3);

        // 整数部分以3为基准长度划分,剩下几位
        var i = _int.length % 3;
        // 取出头部。
        // 如:12345 ----> 12,
        var head = i > 0 ? _int.slice(0, i) + (_int.length > 3 ? ',' : '') : '';
        // 取出小数点部分
        // 如:12345.67 ----> .67

        var _float = stringified.slice(-3);
        var sign = value < 0 ? '-' : '';
        return _currency + sign + head + _int.slice(i).replace(digitsRE, '$1,') + _float;
    }
}

用自定义指令来完成搜索框自动获取焦点

directives: {
    // 属性名称(指令的名称):属性的值(指令的配置对象)
    myfocus: {
        inserted (el) {
            el.focus()
        }
    }
}

用过滤器完成货币格式化显示。

注意:下面的代码来自vue1中的源码。在vue1中提供了货币金额显示格式化的过滤器currency,请在这里https://cdn.bootcdn.net/ajax/libs/vue/1.0.11/vue.js搜索currency关键字。

在这里插入图片描述

filters: {
    $:function(value, _currency) {
        // 全局匹配: 三位连续,且之后也是数值 的数值
        var digitsRE = /(\d{3})(?=\d)/g;
        value = parseFloat(value);
        if (!isFinite(value) || !value && value !== 0) return '';
        _currency = _currency != null ? _currency : '¥';
        // 保留两位小数,并整体转成字符串
        var stringified = Math.abs(value).toFixed(2);

        // 获取整数部分。-3表示倒数3位的位置
        var _int = stringified.slice(0, -3);

        // 整数部分以3为基准长度划分,剩下几位
        var i = _int.length % 3;
        // 取出头部。
        // 如:12345 ----> 12,
        var head = i > 0 ? _int.slice(0, i) + (_int.length > 3 ? ',' : '') : '';
        // 取出小数点部分
        // 如:12345.67 ----> .67

        var _float = stringified.slice(-3);
        var sign = value < 0 ? '-' : '';
        return _currency + sign + head + _int.slice(i).replace(digitsRE, '$1,') + _float;
    }
}

用自定义指令来完成搜索框自动获取焦点

directives: {
    // 属性名称(指令的名称):属性的值(指令的配置对象)
    myfocus: {
        inserted (el) {
            el.focus()
        }
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_44694682/article/details/106059366
今日推荐