Vue2(五):收集表单数据、过滤器、自定义指令、Vue的生命周期

一、收集表单数据

复制代码
爱好:
         学习<input type="checkbox" value="study" v-model="hobby">
         打游戏<input type="checkbox" value="games" v-model="hobby">
         吃饭<input type="checkbox" value="eat" v-model="hobby">

这种写法为啥一勾三个全勾呢?

(1)不配置value的话,默认收集的是checkbox,然后hobby被选为true,其他两个一看hobby是true也就选上了,但是我写了value还是不对

(2)hobby默认值不能是' '

多选框要设置type、value、v-model对应的设置为数组

复制代码
<body>
    <div id="root">
     <form @submit.prevent="demo">
         <!-- 填完信息把信息提交整个表单,而且防止button提交之后跳转页面 -->
         <label for="demo" >账号:</label>
         <!-- 这样写一个label,点击账号两个字就能在input框里获取焦点了 -->
         <input type="text" id="demo" v-model.trim="userInfo.account">
         <!-- .trim可以忽略   ab c  (获得ab  c) -->
         <br><br/>
         密码:<input type="password" v-model="userInfo.password">
         <br><br/>
         <!-- 账号和密码输入什么值value就是啥,但是单/多选框没法输入 -->
         年龄:<input type="number" v-model.number="userInfo.age">
         <!-- 设成type:number可以忽略用户输入的文字 v-model.number是vue提供的,输入到后台就是数字18不是字符串18-->
         <br><br/>
         性别:
         男<input type="radio" name="sex" value="man" v-model="userInfo.sex">
         女<input type="radio" name="sex" value="woman" v-model="userInfo.sex">
         <br><br/>
         爱好:
         学习<input type="checkbox" value="study" v-model="userInfo.hobby">
         打游戏<input type="checkbox" value="games" v-model="userInfo.hobby">
         吃饭<input type="checkbox" value="eat" v-model="userInfo.hobby">
         <br><br/>
         所属校区
         <select v-model="userInfo.city">
             <option value="" >请选择校区</option>
             <option value="beijing">北京</option>
             <option value="shenzhen">深圳</option>
             <option value="shanghai">上海</option>
             <option value="guangdong">广东</option>
         </select>
         <br><br/>
         其他信息:<textarea v-model.lazy="userInfo.other"></textarea>
         <!-- 加上.lazy就会失去焦点的时候再去读入写的啥,不会实时获取 -->
         <br><br/>
         <input type="checkbox" v-model="userInfo.agree">
         阅读并接受<a href="#">《用户协议》</a> 
         <button>提交</button>
     </form>
    </div>
    <script type="text/javascript">
    
    const vm=new Vue({
        el:'#root',
        data:{
            userInfo:{
                password:'',
                account:'',
                age:'',
                sex:'woman',//默认选择女
                hobby:[],
                city:'beijing',//默认值
                agree:'',
          //这样单选框就不用设置value,就一个点了就是true否则几句诗false
      
            }
            },
       methods: {
           demo(){
               console.log(JSON.stringify(this.userInfo))
               //交给后端的方法,但是直接提交data不太好
           }
       },
     
    })

v-model.lazy:实现不用实时收集,输入框失去焦点再收集
v-model.number:输入的字符串收集为数字(Vue内部做了数据转换),经常和type="number"一起用
v-model.trim:收集时去掉输入的首尾空格

二、过滤器

1.过滤器定义

定义:对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理比如价格1999改成1,999等需求,复杂的用计算属性或方法)。

语法:

1、注册过滤器:Vue.filter(name,callback) 或 new Vue{filters:{}}

2、使用过滤器:{{ xxx | 过滤器名}} 或 v-bind:属性 = "xxx | 过滤器名"(用的少)

备注:

1、过滤器也可以接收额外参数、多个过滤器也可以串联

2、并没有改变原本的数据, 是产生新的对应的数据

过滤器两种用法:插值语法、v-bind

2.案例:过滤器格式化时间戳:

复制代码
<body>
    <div id="root">
     <h2>显示格式化之后的时间</h2>
     <!-- 计算属性实现 -->
     <h3>现在是:{{fmtTime}}</h3>
     <!-- methods实现 -->
     <h3>现在是:{{getFmtTime()}}</h3>
     <!-- 是方法就得加()调用 -->
     <!-- 过滤器实现 要改谁就直接写它名儿-->
     <h3>现在是:{{time | timeFormaters}}</h3>
     <h3>现在是:{{time | timeFormaters('YYYY-MM-DD')}}</h3>
     <!-- 拿着time传给timeFormaters返回值直接到{{}}里面,也就是time是个参数 -->
     <!-- 过滤器可以不加(),会给你把|左边的传进去,如果加了(),第一个还是time,第二个参数是格式 -->
     <h3>现在是:{{time | timeFormaters('YYYY-MM-DD') | mySlice}}</h3>
     <!-- 拿着time传给timeFormaters,timeFormaters拿着传入的结果继续往下 -->
     <h3 :x="msg | mySlice">hhh</h3>
     <!-- 过滤器不仅可以用在插值里面 -->
    </div>
    <div id="root2">
        <h2>{{mes | mySlice}}</h2>
    </div>

    <script type="text/javascript">
    Vue.filter('mySlice',function(value){
        return value.slice(0,4)
    })
//    全局过滤器得写在new Vue之前,而且是filter不加s
    const vm=new Vue({
        el:'#root',
        data:{
            time:1710744301627,
            msg:"你好哇哇哇哇"
            },
       computed:{
           fmtTime(){
               return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')
            //    如果dayjs后面不加参数就默认是当前时间
           }
       },
       methods:{
           getFmtTime(){
              return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')
           }
       },
       filters:{
        timeFormaters(value,str='YYYY-MM-DD HH:mm:ss'){
            // 过滤器本质是函数
            return dayjs(value).format(str)
            // 没有格式就默认是'YYYY-MM-DD HH:mm:ss',有的话用传入的格式
        },
        
       }
    })
        // 我写的这些过滤器只能在root vue中可以用
        new Vue({
        el:'#root2',
        data:{
            mes:'hello',
        }
        })
    </script>
</body>

三、自定义指令

1.内置指令

v-bind : 单向绑定解析表达式, 可简写为 :xxx

v-model : 双向数据绑定

v-for : 遍历数组/对象/字符串

v-on : 绑定事件监听, 可简写为@

v-if : 条件渲染(动态控制节点是否存存在)

v-else : 条件渲染(动态控制节点是否存存在)

v-show : 条件渲染 (动态控制节点是否展示)

**v-text:**向其所在的节点中渲染文本内容。

复制代码
<div>{{name}}</div>
<div v-text="name"></div>

当data中name='尚硅谷'的时候,这两段显示出来没有什么区别

但是插值用的更多,因为可以这样写:

复制代码
<div>你好哇{{name}}</div>

而v-text把所有内容当文本会替换掉整个div 的内容,div里面写东西没用,''内容里的写标签它也不识别

v-html :向指定节点中渲染包含html结构的内容。

复制代码
 data:{
            name:'尚硅谷',
            str:'<h3>hhh</h3>'
        },

与插值语法的区别:

(1)v-html会替换掉节点中所有的内容,{{xx}}则不会,这点和v-text一样。

(2)v-html可以识别html结构,这点和v-text区别,v-text不能渲染标签。

严重注意:v-html有安全性问题!!!!

(1)在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击。

(2)一定要在可信的内容上使用v-html,永不要用在用户提交的内容上!

v-cloak (没有值):不让未经解析的模版跑到页面上去

script链接的js如果延迟五秒的话,body内的内容就不会展示在界面上,vue也不会工作

如果script链接的js写在body里面的最下方,那么body上面的内容会出现在页面上但是不被解析

(1)本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性。

(2)使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题,先隐藏标签,然后Vue渲染完了之后删除v-cloak,那么就能显示渲染完之后的页面了。

复制代码
<style>
    [v-colak]{
        /* 选中所有标签属性里面有v-colak的 */
        display: none;
    }
</style>

<body>
   
   <div id="root">
       <div v-cloak>{{name}}</div>
   </div>

    <script type="text/javascript">
    const vm=new Vue({
        el:'#root',
        data:{
            name:'尚硅谷',
          
        },
  
    })

v-once指令:(没有值)

(1)v-once所在节点在初次动态渲染后,就视为静态内容了,也就是只读一次。

(2)以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能。

复制代码
<div id="root">
       <div v-once>{{n}}</div>
       <button @click="n++">点我n+1</button>
       <div>{{n}}</div>
   </div>

v-pre指令:(没有值)

(1)跳过其所在节点的编译过程。

(2)可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译。

也就是程序员写的什么样它就呈现出来什么样,vue不去解析了

2.自定义指令

(1)函数式

big函数何时调用?

1、指令与元素成功绑定时(一上来,没放入页面之前)

2、指令所在的模板被重新解析时

点击按钮使n++,输出n*10

复制代码
<div id="root">
       <h2>当前的n值是:
           <span v-text="n"></span>
       </h2>
       <h2>放大10倍的n值是:
           <span v-big="n"></span>
       </h2>
       <button @click="n++">点我n++</button>
   </div>

    <script type="text/javascript">
    const vm=new Vue({
        el:'#root',
        data:{
            n:1,
          
        },
        directives:{
            big(element,binding){//这里就不加v-了
                // 这里的binding是说v-big和span的绑定关系,不是v-bind
                // return this.n*10这么写不对!!
                // 不是靠返回值,是靠big这个函数返回的参数
              console.log(element,binding)
                // 第一个参数是说跟什么标签绑定的span(真实dom)
                // 第二个参数是一个存着指令值的对象
              element.innerText=binding.value*10
            }
        }

(2)对象式

配置对象中常用的3个回调:
bind:指令与元素成功绑定时(一上来,没放入页面之前)
inserted:指令所在元素被插入页面时调用(放入页面后)
update:指令所在模板结构被重新解析时调用(有任意data中的东西被改了)。

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

复制代码
 <div id="root">
       <h2>当前的n值是:
           <span v-text="n"></span>
       </h2>
       <h2>放大10倍的n值是:
           <span v-big="n"></span>
       </h2>
       <button @click="n++">点我n++</button>
    </br>
    <input type="text" v-fbind:value="n">
   </div>

const vm=new Vue({
        el:'#root',
        data:{
            n:1,
          
        },
        directives:{
            // 函数调用的时候:一上来;指令所在模版被重新解析
            big(element,binding){//这里就不加v-了
                // 这里的binding是说v-big和span的绑定关系,不是v-bind
                // return this.n*10这么写不对!!
                // 不是靠返回值,是靠big这个函数返回的参数
                console.log(element,binding)
                // 第一个参数是说跟什么标签绑定的span(真实dom)
                // 第二个参数是一个存着指令值的对象
                element.innerText=binding.value*10
            },
            // fbind(element,binding){
            //     element.value=binding.value
            //     element.focus()
//这个放在这里刷新之后并没有自动获取焦点,所以不能写成函数得弄成对象,因为:
//fbind第一次调用就在他俩成功绑定也就是一上来的时候,那会input还没被解析到页面上,所以出不来焦点
//如果这时候点了button发现input自动获取焦点了,因为n值改变fbind再次被调用了,这时候input框已经出来了
            // }    
            fbind:{
                //指令与元素成功绑定时(一上来)
                bind(element,binding){
                    element.value=binding.value
                },
                //指令所在元素被插入到页面时调用
                inserted(element,binding){
                    element.focus()
                },
                //指令所在的模版被重新调用时
                update(element,binding){
                    element.value=binding.value
                }
                // bind和updata往往都一样,所以人家设置了函数
            }   
         }
    })
    </script>

(3)注意点

1.多个单词用-分割,v-big-number,而且在vue中写函数的时候不能简写了,得:

复制代码
'big-number'(element,binding){}

2.指令里面相关的this都是window

(4)写全局指令:

复制代码
Vue.directive(指令名,配置对象) 或 Vue.directive(指令名,回调函数)

Vue.directive('fbind',{
        bind、、
        update、、、
    })

和filter一样不加s

写全局函数:

复制代码
Vue.directive('big',function(element,binding){
        element.innerText=binding.value*10
    })

四、Vue的生命周期!!

1.什么是生命周期?

一个小笔记:{{}}如果返回值为undefined的话不显示在页面上

生命周期

1.又名:生命周期回调函数、生命周期函数、生命周期钩子。

2.是什么:Vue在关键时刻帮我们调用的一些特殊名称的函数。

3.生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的。

4.生命周期函数中的this指向是vm 或 组件实例对象。

mounted之前有一些函数,之后有一些函数,这三种加一块就组成生命周期

2.生命周期中的8个钩子

整个root div都是模版template

把内容写在template里和直接写在body里有区别:写在template里root的div就不被解析了,而且template里边只能有一个根元素,template标签不能作为根元素出现在vue中的template(它不显示在页面上)

重要的生命周期钩子

1.mounted: 发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】。

2.beforeDestroy: 清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】。

关于销毁Vue实例

1.销毁后借助Vue开发者工具看不到任何信息。

2.销毁后自定义事件会失效,但原生DOM事件依然有效,销毁后所有的监视也没了

3.一般不会在beforeDestroy操作数据,因为即便操作数据,也不会再触发更新流程了。

复制代码
beforeCreate() {
                console.log('beforeCreate');
                console.log(this);
                // debugger;
            },
            created() {
                console.log('created');
                // create的是数据代理和数据监测
            },
            beforeMount() {
                console.log('beforeMount');
                // 挂载之前对dom的操作最终都无效所以不要操作
            },
            mounted() {
                console.log('mounted');
                // 避免对dom操作,让vue来
            },
            beforeUpdate() {
                console.log('beforeUpdate');
            },
            updated() {
                console.log('updated');
            },
            beforeDestroy() {
                console.log('beforeDestroy');
                // 如果这个时候调函数让n++,这个操作不会让数据更新了
                // 可以访问数据和调用函数,但是不更新
            },
            destryed() {
                console.log('destryed');
                // 销毁了但是它之前的成果还会留着
            }

3.图解生命周期

4.案例:字体闪烁,点击停止(销毁vm)

复制代码
<body>
   
   <div id="root">
    <h1 :style="{opacity}">欢迎学习Vue</h1>
    <!-- opacity本来就是透明度,正好变量设置的也是opacity,可以简略写成opacity -->
    <button @click="stop">停止变换</button>
    <button @click="opacity=1">透明度设置为1</button>
    <!-- destory很少用vm.$destory(紫砂)得v-if或v-for -->
</div>

    <script type="text/javascript">
    
    const vm=new Vue({
        el:'#root',
        data:{
            opacity:1,
        },
        methods: {
            stop(){
                // clearInterval(this.timer)
                // 我想拿到mounred里的东西不能直接给下面const为id,这儿是找不着id的
                // 加上this,但是清理定时器以后还能打开,我想要销毁
                this.$destory(timer)
                // 这样是页面停了但是定时器还一直在变化
            },

        },
       mounted() {
           this.timer=setInterval(()=>{
               this.opacity-=0.01
               if(this.opacity<=0) this.opacity=1
           },16)
       },
       beforeDestroy() {
        clearInterval(this.timer)
        // 这句话写在stop也行但是是紫砂的时候才调用,但是写在这里就是不管紫砂还是他砂都停止定时器
       },

    })
    
    </script>
</body>
相关推荐
腾讯TNTWeb前端团队4 小时前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
范文杰8 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪8 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪8 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy9 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom9 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom10 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom10 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom10 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom10 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试