vue笔记(二)

7、事件处理

7.1、事件的基本处理

  • 事件的使用
    • 使用v-on:xxx或者用@xxx绑定事件,其中XXX是事件名
    • 事件的回调需要配置在methods对象中,最终出现在VM上
    • methods配置的函数,不需要箭头函数
vue 复制代码
    <div id="root">
        <h1>{{hi}}</h1>
        <!-- 绑定事件 v-on:click 当被点击的时候 -->
        <button v-on:click="click">点我</button>
        <!-- 两种写法都可以,下面是上面的缩写 -->
        <button @click="click">点我</button>
    </div>
    <script>
        new Vue({
            el:'#root',
            data:{
                hi:'hi'
            },
            
            
            
            
            
            //方法体
            methods:{
                click(){
                    alert("hellword")
                }
            }
        })
    </script>

7.2、事件修饰符

在js中提供的事件修饰符,vue也给我们提供了

常见的有 .prevent、.stop、.once

  • .prevent 阻止默认事件
  • .stop 阻止事件冒泡
  • .once 事件只触发一次
  • .capture 使用事件的捕获模式
  • .self 只有event.target是当前元素时才触发
  • .passive 事件的默认行为立即执行,无需等回调
  • 修饰符key连续写 如 @click.prevent.stop
vue 复制代码
    <div id="root">
        <!-- 阻止默认事件 -->
        <a href="http://www.baidu.com" @click.prevent="show">跳转</a>
        <!-- 阻止冒泡 -->
        <div @click="show">
            <button @click.stop="show">阻止冒泡</button>
        </div>
         <!-- 只触发一次事件 -->
        <button @click.once="show">Once</button>
    </div>
    <script>
        new Vue({
            el:'#root',
            methods:{
                show(e){
                    alert('hello')
                }
            }
        })
    </script>

7.3、键盘事件

  • vue中的键盘事件 @keydown.xxx 或者@keyup.xxx
  • vue中提供的常用的键盘别名:
    • enter(回车键)
    • delete(删除键指删除和退格俩个键)
    • esc(退出键)
    • space(空格)
    • tab(换行 必须配合keydown去使用)
    • up (上)
    • down(下)
    • left(左)
    • right(右)
  • 未提供的别名按键,也可以通过原始的key值去绑定,但要注意像CapsLock(转换大小写键)要写成 caps-lock(全小写加短横线)
  • 系统特殊的键位 ctrl、alt、shift、win键等
    • 如果配合keyup使用 必须按下修饰键的同时加上一个键位 如 同时按下ctrl+A键位才会触发
    • 也可以 @keyup.crtl.y 这样 只有按下ctrl+y 键位才会触发
    • 配合keydown键可正常使用
  • 自定义按键:Vue.config.keyCodes.自定义的键位 = 键码
vue 复制代码
C:\Users\Administrator\Desktop\vueB\vue2\08_计算属性\1、插值语法实现.htmlx     <div id="root">           <!-- 通过enter键触发事件拿值 -->        <input type="text" placeholder="提示" @keyup.enter = 'show'>    </div>    <script>        new Vue({            el:'#root',            methods:{                show(e){                    //拿当前触发元素的值                    console.log(e.target.value);                }            }        })    </script>

8、计算属性

效果:

8.1、使用插值语法实现

vue 复制代码
    <div id="root">
        姓:<input type="text" v-model="lastName"><br>
        名:<input type="text" v-model="firstName"><br>
         <!-- 通过拼接的方式 -->
        全名:<span>{{lastName}}{{firstName}}</span>
    </div>
    <script>
        new Vue({
            el:'#root',
            data:{
                lastName:'z',
                firstName:'y',
            }
        })
    </script>

只能进行简单的计算,不能太复杂

8.2、methods方法实现

vue 复制代码
    <div id="root">
        姓:<input type="text" v-model="lastName"><br>
        名:<input type="text" v-model="firstName"><br>
        <!-- 通过methods方法的方式 -->
        <!-- 这里必须加() 否则会不会有值,只会打印整个方法 -->
        全名:<span>{{fullName()}}</span><br>
        全名:<span>{{fullName()}}</span><br>
        全名:<span>{{fullName()}}</span><br>
        全名:<span>{{fullName()}}</span>
    </div>
    <script>
        new Vue({
            el:'#root',
            data:{
                lastName:'z',
                firstName:'y',
            },
            methods:{
                fullName(){
                    console.log("调用了");
                    return this.lastName+this.firstName
                }
            }
        })
    </script>

8.3、computed计算属性实现

  • 计算属性
    • 定义:要用的属性都是通过已经有的属性计算得来。
    • 原理:底层借助了Object.defineProperty方法提供getter和setter
    • 优势:与methods实现相比,内部有缓存机制,效率更高
    • 注意事项
      • 如果计算属性要被修改,那必须用set去响应修改,并要引起被计算属性的值发生变化
vue 复制代码
    <div id="root">
        姓:<input type="text" v-model="lastName"><br>
        名:<input type="text" v-model="firstName"><br>
        全名:<span>{{fullName}}</span><br>
        全名:<span>{{fullName}}</span><br>
        全名:<span>{{fullName}}</span><br>
        全名:<span>{{fullName}}</span><br>
    </div>
    <script>
        new Vue({
            el:'#root',
            data:{
                lastName:'z',
                firstName:'y',
            },
            computed:{
                fullName:{
                    get(){
                        // 这里为了set方法方便使用空格连接
                        console.log("被调用");
                        return this.lastName+' '+this.firstName
                    },
                    set(){
                        const arr = value.split(' ')
                        this.lastName = arr[0]
                        this.firstName = arr[1]
                    }
                }
            }
        })
    </script>

9、监视属性

9.1、基础监视

  • 监视属性watch:
    • 用法:当监视的属性发生变化时,自动调用进行相关参数
    • 可以监听 计算属性
    • 注意事项
      • 监视属性必须存在,才能监视。不存在控制台不会提示
    • 两种写法
      • 通过new Vue时传入watch配置,用于已经知道需要监听的属性
      • 通过vm.$watch监视,用于开始并不知道需要监视时
vue 复制代码
    <div id="root">
        <h1>数字为{{info}}</h1>
        <button @click="change">改变数字</button>
    </div>
    <script>
       const vm = new Vue({
            el:'#root',
            data:{
                value:true
            },
            computed:{
                info(){
                    return this.value ? '1':'2'
                }
            },
            methods:{
                //取相反
                change(){
                   this.value = !this.value
                }
            },
            // 第一种写法
            // watch:{
            //     value:{
            //         //初始化时handler被调用一次
            //         immediate:true,
            //         //当监听到value值被改变时 handler被调用
            //         handler(newValue,oldValue){
            //             console.log("value被修改了"+newValue+" "+oldValue);
            //         }
            //     }
            // }
        })
        //第二种写法
        vm.$watch('value',{
            immediate:true,
            handler(newValue,oldValue){
             console.log("value被修改了"+newValue+" "+oldValue);
            }
        })
 </script>

9.2、深度监视

在vue中watch方法默认不会监视多层级的值

  • vue中给我们提供了方法deep
    • vue自身可以监控到内部值的改变,但是vue提供的watch默认不可以
    • 需要根据数据具体结构来决定是否开启deep
vue 复制代码
    <div id="root">
        <h1>数字为{{value.a}}</h1>
        <button @click="value.a++">add</button>
    </div>
    <script>
       const vm = new Vue({
            el:'#root',
            data:{
                value:{
                    a:1,
                    b:2,
                }
            },
            watch:{
                value:{
                    //开启深度监测
                    deep:true,
                    immediate:true,
                    handler(){
                        console.log("value被修改了");
                    }
                }
            }
        })
    </script>

9.3、watch与computed区别

我们拿一个小案例来举例

computed版本

watch版本

  • 从代码层面来看两者对比,conputed的代码更精简
  • 但如果涉及到异步操作时,只有watch能够实现
    • 如:让它延迟一秒后再显示修改的全名
  • 这里涉及到两个小原则
    • 只要是被Vue管理的函数,最好都写成普通函数,这样this指向的才是组件实例对象
    • 不被vue所管理的函数(定时器回调函数、ajax回调函数),最好写成箭头函数这样this才能指向组件实例对象

10、绑定样式

10.1、绑定class样式

  • 绑定class样式
    • 字符串写法
      • 用于样式类名不确定,需要动态指定
    • 数组写法
      • 用于要绑定的样式个数不确定、名字也不确定
    • 对象写法
      • 用于要绑定的样式个数确定、名字也确定,但要动态决定用不用
  • 字符串写法

通过改变mood的值来实现切换

  • 数组的写法

方便以后管理样式,如果不需要有些样式,可通过数组形式删除

  • 对象写法

动态的决定样式是否开启

10.2、内联style样式写法

  • 内联样式写法
    • :style="{fontSize:xxx}"其中xxx是动态值
    • 也可以写成对象形式

以对象的形式存储,方便修改

11、条件渲染

  • 条件渲染

  • v-if( 与JavaScript中的if作用相同)

    • 写法:v-if="表达式"

    • v-else-if="表达式"

    • v-else="表达式"

    • 适用于:用于切换频率较低的场景

    • 特点:不展示的Dom元素直接被删除

    • 三个表达式可以连用,但是结构必须在一起,不能拆分

  • v-show

    • 写法:v-show="表达式"
      • 适用于:切换频率较高的 场景
      • 特点:不展示的Dom元素只会被display隐藏
  • 注意事项

    • v-if被触发时,会导致元素直接被删除,获取不到元素

11.1、v-if的使用

vue 复制代码
    <div id="root">
        <!-- v-if条件渲染 -->
        <h2 v-if="n===1">1</h2> 
        <h2 v-else-if="n===2">2</h2> 
        <h2 v-else="n===3">3</h2> 
        <button @click="n++">v-if测试</button>
    </div>
    <script>
        new Vue({
            el:'#root',
            data:{
                n:0
            }
        })
    </script>

可以看到以前的Dom元素随着切换会被移除

11.2、v-show的使用

vue 复制代码
    <div id="root">
        <!-- v-if条件渲染 -->
        <h1 v-show="false">1</h1>
        <h2 v-show="1===1">2</h2> 
    </div>
    <script>
        new Vue({
            el:'#root'
        })
    </script>

这里可以看到v-show等于false时元素没有被移除

12、列表渲染

12.1、v-for指令

  • v-for指令
    • 用于展示列表数据
    • 语法:v-for="(p,index) of persons" :key="index"
    • 可遍历:数组、对象、字符串、指定次数
  • :key的作用
    • 虚拟Dom中的key作用
      • 作为虚拟Dom中的对象标识,当数据发生变化,会生成一个新的虚拟Dom,随后新旧Dom进行一个比对
    • 新旧Dom比对规则
      • 若旧Dom找到与新Dom相同的Key
      • 虚拟Dom中内容没变,直接使用前面的真实Dom
      • 若发生变化则生成新的真实Dom,替换旧的
vue 复制代码
    <div id="root">
        <!-- 遍历数组 -->
        <h2>数组</h2>
        <ul>
            <!-- 这里必须直接列表的Key 否则vue会把整个Li当成一个 会报错 -->
          	
            <li v-for="(p,index) in persons" :key="index">
                {{p.name}}-{{p.age}}
            </li>
        </ul>
         <!-- 遍历数组 -->
        <h2>数组</h2>
        <ul>
            <li v-for="(p,index) in student" :key="index">
                {{p}}--{{index}}
            </li>
        </ul>
    </div>
    <script>
        new Vue({
            el:'#root',
            data:{
            persons:[
                    {id:'01',name:'zy',age:'18'},
                    {id:'02',name:'zy2',age:'19'},
                    {id:'03',name:'zy3',age:'20'},
            ],
            student:{name:'zy',age:'18'}
        }
        })
    </script>

这里如果用index(索引)作为key,我们在最前面追加一个数据的时候,会导致vue 复用前面的input 会出现下面的结果

推荐使用 p.id作为key

12.2、列表模糊查找过滤案例

先看效果

  1. watch监听实现
vue 复制代码
 <div id="root">
        <h2>模糊查找案例</h2>
        <!-- 建立一个输入框 取值用于模糊查找 -->
        <input type="text" placeholder="输入要查找的名字" v-model="likeName">
        <ul>
            <li v-for="(p,index) in newPersons" :key="p.id">
                {{p.name}}-{{p.age}}
            </li>
        </ul>
    </div>
    <script>
        new Vue({
            el: '#root',
            data: {
                persons: [
                    { id: '01', name: '周冬雨', age: '18', sex: 'woman' },
                    { id: '02', name: '马冬梅', age: '19', sex: 'woman' },
                    { id: '03', name: '周杰伦', age: '21', sex: 'man' },
                    { id: '04', name: '马东伦', age: '20', sex: 'man' },
                ],
                likeName:'',
                //不对原数组进行操作
                newPersons: []
            },
            //监听事件
            watch: {
                likeName:{
                    //初始化调用一次 使indexOf比较为空刷新所有数据
                    immediate:true,
                    handler(val){
                        //过滤数据
                        this.newPersons = this.persons.filter((p)=>{
                            //通过indexOf判断搜索的值是否与列表匹配,如果不匹配等于-1
                            return p.name.indexOf(val) !== -1
                        })
                    }
                }
            }
     })
    </script>

2、computed计算实现

vue 复制代码
<div id="root">
        <h2>模糊查找案例</h2>
        <!-- 建立一个输入框 取值用于模糊查找 -->
        <input type="text" placeholder="输入要查找的名字" v-model="likeName">
        <ul>
            <li v-for="(p,index) in newPersons" :key="p.id">
                {{p.name}}-{{p.age}}
            </li>
        </ul>
</div>
<script>
        new Vue({
            el: '#root',
            data: {
                persons: [
                    { id: '01', name: '周冬雨', age: '18', sex: 'woman' },
                    { id: '02', name: '马冬梅', age: '19', sex: 'woman' },
                    { id: '03', name: '周杰伦', age: '21', sex: 'man' },
                    { id: '04', name: '马东伦', age: '20', sex: 'man' },
                ],
                likeName:'',
            },
            computed:{
                newPersons(){
                    return this.persons.filter((p)=>{
               //通过indexOf判断搜索的值是否与列表匹配,如果不匹配等于-1
                        return p.name.indexOf(this.likeName) !== -1
                    })
                }
            }
     })
</script>

12.3、排序列表案例

效果:

代码实现

vue 复制代码
    <div id="root">
        <h2>模糊查找案例+升降序</h2>
        <!-- 建立一个输入框 取值用于模糊查找 -->
        <input type="text" placeholder="输入要查找的名字" v-model="likeName">
        <button  @click="isup=1">升序</button>
        <button  @click="isup=2">降序</button>
        <button  @click="isup=0">原顺序</button>
        <ul>
            <li v-for="(p,index) in newPersons" :key="p.id">
                {{p.name}}-{{p.age}}
            </li>
        </ul>
    </div>
    <script>
        new Vue({
            el: '#root',
            data: {
                persons: [
                    { id: '01', name: '周冬雨', age: '20', sex: 'woman' },
                    { id: '02', name: '马冬梅', age: '30', sex: 'woman' },
                    { id: '03', name: '周杰伦', age: '21', sex: 'man' },
                    { id: '04', name: '马东伦', age: '40', sex: 'man' },
                ],
                likeName: '',
                //判断为升序还是降序 1为升 2为降 0为与原来的顺序
                isup: 0
            },
            computed: {
                newPersons() {
                    const arr = this.persons.filter((p) => {
                        //通过indexOf判断搜索的值是否与列表匹配,如果不匹配等于-1
                        return p.name.indexOf(this.likeName) !== -1
                    })
                    //判断升降序
                    if (this.isup ==0) {
                        return arr
                    }else{
                        //如果要升降序利用三元表达式进行操作
                        arr.sort((a, b) => {
                            return this.isup === 1 ? a.age-b.age : b.age-a.age
                        })
                    }
                    return arr
                }
            }
        })
    </script>

13、vue监测数据的原理

  • 原理

    • vue会监视data中所有层次的数据

    • 如何监测对象中的数据?

      • 通过setter事件监视,且要在newVue时就传入要监测的数据

      • 在对象后追加的属性,Vue默认不做响应式处理

      • 如需给后添加的属性做响应式,需要使用以下API:

        Vue.set(target,propertyName/index,value)

        vm.$ser(target,propertyName/index,value)

    • 如何监测数组中的数据?

      • 通过包裹数组更新元素的方法实现,本质就是做了两件事:
      • 调用原生对应的方法对数组进行更新
      • 重新解析模板,进而更新页面
    • 在Vue修改数组中的某个元素需要用到以下方法:

      • 使用这些API:push(),pop(),shift(),unshift(),splice(),sort(),erverse()
      • Vue.set()或vm.$set
    • 注意Vue.set:

      • 不允许修改vue的根数据或者vue实例
      • 只能给data里面的对象追加属性

13.1、例子 更新一个人的信息

html 复制代码
        <!-- html -->
<div id="root">
        <h1>更新信息的一个问题</h1>
        <ul>
            <li v-for="(p,index) in persons" :key="p.id">
                {{p.name}}-{{p.age}}
            </li>
        </ul>
            <!-- 只能更新第一条的信息 -->
        <button @click="upData">点我更新一条信息</button>
</div>
vue 复制代码
<!-- vue -->
<script>
        const vm = new Vue({
            el:'#root',
            data:{
                persons: [
                    { id: '01', name: '周冬雨', age: '20', sex: 'woman' },
                    { id: '02', name: '马冬梅', age: '30', sex: 'woman' },
                    { id: '03', name: '周杰伦', age: '21', sex: 'man' },
                    { id: '04', name: '马东伦', age: '40', sex: 'man' },
                ],
            },
            methods:{
                //更新第一条信息
                upData(){
                    this.persons[0]= { id: '01', name: 'zy', age: '30', sex: 'man' }
                }
            }
        })
</script>

​ 当我触发点击事件时,可以发现前后的对比

​ 虽然我们修改了数据,但是vue并没有监测到,就不会渲染到页面上。同时我们发现,通过我们直接赋值的这种方式,将第一个的对象属性的get和set方法没有了。

​ 那我们通过下面这种方式操作对象的属性在进行一次数据的修改

​ 我们可以看到数据成功的渲染到了页面上,同时我们可以看到对象的方法并没有被删除,其背后的原理就是Vue底层利用了Object.defineProperty 做数据代理,通过get和set函数进行修改和解析,封装成Observer方法遍历data的属性,并对属性添加getter和setter。

​ 而我们用的persons[0].name是对象中的属性,所以会触发监听重新渲染页面。

13.2、简单实现一个vue监测数据的原理

js 复制代码
    <script>
        let data = {
            name:'zy',
            age:18
        }
        const obs = new Observer(data)
        console.log(obs);
        
        //new 一个vm实例对象
        let vm ={}
        vm._data = data = obs

        function Observer(obj) {
            //汇总对象中的所有属性,形成一个数组
            const keys = Object.keys(obj)
            console.log(keys);
            //遍历
            keys.forEach((item)=>{
                //这里this指向的是Observer的实例对象
                Object.defineProperty(this,item,{
                    get(){
                        //返回对应属性身上的值
                        return obj[item]
                    },
                    set(val){
                        //修改对应属性身上的值
                        obj[item]=val
                    }
                })
            })
        }
    </script>

13.3、vue.set方法

​ 当我们的data已经写好,但后续需要添加一个对象时,vue给我们提供了一个set方法,给我们使用。达到重新渲染的效果。

  • 例子:Vue.set(this.student,'sex','男') 或者 this.$Vue(this.student,'sex','男')
    • 注意事项
      • 不允许修改vue的根数据或者vue实例
      • 只能给data里面的对象追加属性

​ 如图所示,我们需要向红色框添加一个性别属性

vue 复制代码
    <div id="root">
        <button @click="addSex">添加一个性别:默认值为男</button>
        <h2>姓名:{{student.name}}</h2>
        <h2>年龄:{{student.age}}</h2>
      <!-- 这里要注意 如果值为undefind vue不会渲染,也就是开始data.student中没有sex这个属性 -->
        <h2>性别:{{student.sex}}</h2>
    </div>
    <script>
        new Vue({
            el:'#root',
            data:{
                student:{
                    name:'zy',
                    age:'1'
                }

            },
            methods:{
                addSex(){
                    Vue.set(this.student,'sex','男')
                }
            }
        })
    </script>

13.4、利用vue提供的方法做例1 -更新一个人的信息

​ 在开头我们直接利用

vue 复制代码
 this.persons[0]= { id: '01', name: 'zy', age: '30', sex: 'man' }

​ 修改数组不会奏效,同时页面也不会渲染。在vue中给我们提供了方法

​ 也就是说我们需要变更数组的属性值时,需要用到上面的七个方法或者利用Vue.set去修改

vue 复制代码
 this.persons.splice(0,1,{ id: '01', name: 'zy', age: '30', sex: 'man' }) 

14、收集表单数据

  • 收集表单数据
    • 若:,则v-model收集的是value值为用户输入的value值
    • 若:,则v-model收集的是value值并且要给标签配置value值
    • 若:
      • 没有给input配置value,则收集起来的就是checked(布尔值)
      • 配置了input的value值
        • v-model的初始值不是为非数组形式,那么还是为checked
        • 如果为数组,那么就收集数组组成的值
  • v-model的三个修饰符
    • 用法:v-model.lazy
    • lazy:失去焦点在收集
    • number:输入的字符串转为有效的数字
    • trim:去掉首尾空格

14.1、案例---收集表单数据

vue 复制代码
    <div id="root">
        <form>
            <!-- 限制值为数字,传入的值也是数字-->
            账号:<input type="number" v-model.number.trim="account"><br>
            密码:<input type="password" v-model="password"><br>
            <!-- 分组归为一类,辨别性别 -->
            性别:男<input type="radio" value="1" name="sex" v-model="sex">
                 女<input type="radio" value="0" name="sex" v-model="sex"> <br>
                 <!-- 用数组形式存储 -->
            爱好: 吃饭<input type="checkbox" value="吃饭"v-model="hobby">
                  睡觉<input type="checkbox" value="睡觉"v-model="hobby">
                  打游戏<input type="checkbox" value="打游戏"v-model="hobby"><br>
            所属校区:<select v-model="school">
                <option value="">请输入你的校区</option>
                <option value="第一区">第一区</option>
                <option value="第二区">第二区</option>
            </select><br>
            其他信息:<textarea v-model.lazy="other"></textarea> <br>
            <input type="checkbox" v-model="agree">阅读并接收<a href="www.baidu.com">《用户协议》</a><br>
            <button>提交</button>
        </form>
    </div>    
    <script>
        new Vue({
            el:'#root',
            data:{
                account:'',
                password:'',
                sex:'',
                hobby:[],
                school:'',
                other:'',
                agree:''
            }
        })
    </script>
相关推荐
敲敲敲-敲代码34 分钟前
【SQL实验】触发器
数据库·笔记·sql
无责任此方_修行中1 小时前
每周见闻分享:杂谈AI取代程序员
javascript·资讯
Moonnnn.1 小时前
51单片机学习——动态数码管显示
笔记·嵌入式硬件·学习·51单片机
dorabighead3 小时前
JavaScript 高级程序设计 读书笔记(第三章)
开发语言·javascript·ecmascript
电棍2334 小时前
verilog笔记
笔记·fpga开发
让我安静会4 小时前
Obsidian·Copilot 插件配置(让AI根据Obsidian笔记内容进行对话)
人工智能·笔记·copilot
林的快手4 小时前
CSS列表属性
前端·javascript·css·ajax·firefox·html5·safari
世事如云有卷舒5 小时前
FreeRTOS学习笔记
笔记·学习
bug总结5 小时前
新学一个JavaScript 的 classList API
开发语言·javascript·ecmascript
网络安全-老纪5 小时前
网络安全-js安全知识点与XSS常用payloads
javascript·安全·web安全