vue笔记(二)

7、事件处理

7.1、事件的基本处理

  • 事件的使用
    • 使用v-on:xxx或者用@xxx绑定事件,其中XXX是事件名
    • 事件的回调需要配置在methods对象中,最终出现在VM上
    • methods配置的函数,不需要箭头函数
    <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
    <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.自定义的键位 = 键码
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、使用插值语法实现

    <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方法实现

    <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>

动画12

8.3、computed计算属性实现

  • 计算属性
    • 定义:要用的属性都是通过已经有的属性计算得来。
    • 原理:底层借助了Object.defineProperty方法提供getter和setter
    • 优势:与methods实现相比,内部有缓存机制,效率更高
    • 注意事项
      • 如果计算属性要被修改,那必须用set去响应修改,并要引起被计算属性的值发生变化
    <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>

动画123

9、监视属性

9.1、基础监视

  • 监视属性watch:
    • 用法:当监视的属性发生变化时,自动调用进行相关参数
    • 可以监听 计算属性
    • 注意事项
      • 监视属性必须存在,才能监视。不存在控制台不会提示
    • 两种写法
      • 通过new Vue时传入watch配置,用于已经知道需要监听的属性
      • 通过vm.$watch监视,用于开始并不知道需要监视时
    <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方法默认不会监视多层级的值

动画12345

  • vue中给我们提供了方法deep
    • vue自身可以监控到内部值的改变,但是vue提供的watch默认不可以
    • 需要根据数据具体结构来决定是否开启deep
    <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>

1

9.3、watch与computed区别

我们拿一个小案例来举例

computed版本

image-20220508151037892

watch版本

  • 从代码层面来看两者对比,conputed的代码更精简
  • 但如果涉及到异步操作时,只有watch能够实现
    • 如:让它延迟一秒后再显示修改的全名

2

  • 这里涉及到两个小原则
    • 只要是被Vue管理的函数,最好都写成普通函数,这样this指向的才是组件实例对象
    • 不被vue所管理的函数(定时器回调函数、ajax回调函数),最好写成箭头函数这样this才能指向组件实例对象

10、绑定样式

10.1、绑定class样式

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

image-20220508160137036

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

  • 数组的写法

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

  • 对象写法

image-20220508161041172

动态的决定样式是否开启

10.2、内联style样式写法

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

image-20220508162941361

134

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

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的使用

    <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>

234

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

11.2、v-show的使用

    <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>

image-20220508170751601

这里可以看到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,替换旧的
    <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

image-20220508184356371

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

先看效果

34

  1. watch监听实现
 <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计算实现

<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、排序列表案例

效果:

344

代码实现

    <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 -->
<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 -->
<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>

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

image-20220509093135509

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

image-20220509093820584

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

image-20220509094120752

image-20220509094501817

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

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

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

    <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>

image-20220509100550859

13.3、vue.set方法

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

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

image-20220509102346753

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

    <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 -更新一个人的信息

​ 在开头我们直接利用

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

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

image-20220509105411737

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

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

3446

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、案例—收集表单数据

46

    <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>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

周粥粥ya

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值