Vue基础笔记

Vue是什么 :

一、初识Vue:

        1.1想让Vue工作,就必须创建一个Vue实例,且要传入 一个配置对象

        1.2root容器里代码依旧符合html规范,不过里面掺杂了一些Vue语法

        1.3root容器里的代码被称为【Vue模板】

        1.4Vue实例和容器是一一对应的

        1.5真实开发中只有一个Vue实例,并且配合组件一起使用

        1.6{{***}} ***要写js表达式,且***可以自动读取到data中的所有属性

        1.7一旦data中的数据发生改变,那么模板中用到该数据的地方也会自动更新

二、Vue模板语法

        2.1插值语法

                功能:用于解析标签体内容

                写法:见1.6

        2.2指令语法

                功能:用于解析标签(标签属性、标签体内容 、绑定事件......)

                举例:v-bind:href=“***”

<div id="root">
    <h1>插值语法</h1>
    <h3>你好,{{name}}</h3>
    <h1>指令语法</h1>
    <a v-bind:href="url">123</a>
</div>
<script>
    new Vue({
        el: '#root',
        data: {
            name: 'lisa',
            url: 'http://www.baidu.com/'
        },

    })
</script>

三、数据绑定

        3.1Vue中有两种绑定的方式

                1.单向数据绑定(v-bind):数据只能从data流向页面

                                                                                //简写方式删掉v-bind留冒号

                2.双向数据绑定(v-model):数据不仅可以从data流向页面也可以从页面流向data

                                                                                 //简写方式只留v-model

                备注:双向绑定一般应用在表单类元素上(如:input、select等)

        3.2 el和data的两种写法 

                        el的两种写法:

                                (1)new Vue时配置el属性 

                                (2)先创建Vue实例,随后再通过vm.$mount(‘#root’)指定el的值

                                

    const v = new Vue({
           // el:'#root',//ew Vue,配置el属性
           data:{
               name:'lisa'
           }//对象法
           //  data:function (){
           //      return{
           //          name:'lisa'
           //      }
           //  }//函数法
        })
        v.$mount('#root')

                        data的两种写法:

                                (1)对象法

                                (2)函数式

    <div id="root">
        单向数据绑定:<input type="text" v-bind:value="name"></br>
        单向数据绑定:<input type="text" v-model:value="name">
    </div>
    <script>
        const v = new Vue({
           // el:'#root',//ew Vue,配置el属性
           data:{
               name:'lisa'
           }//对象法
           //  data:function (){
           //      return{
           //          name:'lisa'
           //      }
           //  }//函数法
        })
        v.$mount('#root')
    </script>

四、MVVM模型

        M:模型(Model):对应data中的数据

        V:视图(View):模板

        VM:视图模型(View Model):Vue实例对象

五、数据代理

                5.1回顾Object.definePrepert方法

    //Object.defineProperty:定义属性
    let person = {
        name:'丽丽',
        sex:'女 '
    }
    //{给那个对象添加属性,'属性名',{配置项}}
    Object.defineProperty(person,'age',{
        value:18//不可枚举、不能被遍历
    })
    console.log(person);

Object.definePrepert方法:遍历enumerable:true、修改属性值writable、删除属性configurable: true

    //Object.defineProperty:定义属性
    let person = {
        name:'丽丽',
        sex:'女 '
        //age:18//在这里定义属性在浏览器中可以修改但在Object.defineProperty(,,{})中添加在浏览器中不能修改
    }
    //{给那个对象添加属性,'属性名',{配置项}}
    Object.defineProperty(person,'age',{
        value:18,
        enumerable:true,//控制属性是否可以枚举,默认值是false
        writable:true,//控制属性是否可以被修改默认值是false
        configurable: true//控制属性是否可以被删除,默认值是false
    })
    console.log(Object.keys(person));
    // for (let key in person) {
    //     console.log(person[key]);
    // }
    console.log(person);

:get(){}、set(){}

    //Object.defineProperty:定义属性
    let number = 18
    let person = {
        name:'丽丽',
        sex: '女 ',

    }
    //{给那个对象添加属性,'属性名',{配置项}}
    Object.defineProperty(person, 'age', {
        /*value: 18,
        enumerable: true,//控制属性是否可以枚举,默认值是false
        writable: true,//控制属性是否可以被修改默认值是false
        configurable: true//控制属性是否可以被删除,默认值是false*/

        //当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值
        get(){//:function可省略
            console.log('有人读取了age属性')
            return number
        },

        //当有人修改person的age属性时,set函数(setter)就会被调用,且会收到修改的具体值
        set(value){
            console.log('有人修改了age属性,且值是'+value)
            number = value
        }
    });

        5.2什么是数据代理

        数据代理是通过一个对象代理对另一个对象中属性的操作(读/写)

let obj1 = {x:100}
    let obj2 = {y:700}
    Object.defineProperty(obj2,'x',{
        get(){
            return obj1.x
        },
        set(value){
            obj1.x = value
        }
    })

        6.1Vue中的数据代理

<div id="root">
    <h3>学校名称:{{name}}</h3>
    <h3>学校地址:{{address}}</h3>
</div>
</body>

  <script>
    const ww = new Vue({
      el: '#root',
      data:{
        name:'希望',
        address:'酒水将'
      }
    })
  </script>

 六、事件处理

<div id="root">
  <h3>欢迎来到{{name}}</h3>
<!--  <button v-on:click="showInFo">点我提示信息</button>-->
  <button @click="showInFo1">点我提示信息1</button><!--上述方法简写形式-->
  <button @click="showInFo2(66,$event)">点我提示信息2</button>
  <!--当你点击button时,它帮你找到名为showInFo的函数取调用-->
</div>
</body>
<script>
  const vm = new Vue({
    el:'#root',
    data:{
      name:'王者荣耀'
    },
    methods:{
      showInFo1(event) {
        // console.log(event.target.innerText)
        // console.log(this),//此处this是vm
        alert('请选择英雄')
      },
      showInFo2(number,a){
         // console.log(event.target.innerText)
         // console.log(this),//此处this是vm
        // alert('请选择技能')
        console.log(number,a)
   }
    }
  })
</script>

1、事件的基本使用:

1.使用v-on:xxx或@xxx绑定事件,其中xxx是事件名

2.事件 回调需要配置在methods对象中,最终会在vm上

3.methods中配置的函数,不要使用箭头函数,否则this指向全局

4.methods中配置的函数,都是被Vue所管理的函数,this指向 是vm或组件实例对象

5.@click=“demo”和@click=“demo($event)”效果一致,但后者可以传参

2、事件修饰符

Vue中的修饰符:

①click:点击事件的修饰符

1.prevent:阻止默认事件(常用)

 <a href="http://www.baidu.com/" @click.prevent = 'showInFo'>点我提示信息</a>

2.stop:阻止事件冒泡(常用) 

<div class="demo1" @click = 'showInFo'>
        <button @click.stop = 'showInFo'>点我提示信息</button>

    </div>

3.once:事件只会触发一次(常用)
 

<button @click.once="showInFo">点我提示</button>

4.capture:使用事件的捕获模式

<!--使用事件的捕获模式-->
    <div class="div1" @click.capture="showMsg(1)">
        div
        <div class="div2" @click="showMsg(2)">
            div
        </div>

5.self:只有event.target是当前操作的元素才时触发事件

6.passive:事件的默认行为立即执行,无需等待事件回调执行完毕

修饰符可连接使用:

<a href="http://www.baidu.com/" @click.prevent.stop = 'showInFo'>点我提示信息</a>
<!--        @click.prevent.stop先阻止默认行为再停止冒泡-->
<!--        @click.prevent.stop先停止冒泡再阻止默认行为-->

②scroll:给滚动条加的滚动修饰符

③wheel:鼠标滚动轮的滚动修饰符(滚轮动)

<body>
<div id="root">
  <h3>欢迎来到{{name}}</h3>
<!--    1.prevent:阻止默认事件(常用)-->
  <a href="http://www.baidu.com/" @click.prevent = 'showInFo'>点我提示信息</a>
    <!--2.stop:阻止事件冒泡(常用)-->
    <div class="demo1" @click = 'showInFo'>
        <button @click.stop = 'showInFo'>点我提示信息</button>
    </div>
<!--    事件只触发一次-->
    <button @click.once="showInFo">点我提示</button>
<!--使用事件的捕获模式-->
    <div class="div1" @click.capture="showMsg(1)">
        div
        <div class="div2" @click="showMsg(2)">
            div
        </div>
    </div>
<!--    self:只有event.target是当前操作的元素才时触发事件-->
    <div class="demo1" @click.self = 'showInFo'>
        <button @click = 'showInFo'>点我提示信息</button>
    </div>
<!--    passive:事件的默认行为立即执行,无需等待事件回调执行完毕-->
    <ul class="list" @scroll="demo">
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
    </ul>
</div>


</body>
<script>
  new Vue({
    el:'#root',
    data:{
      name:'王者荣耀',
    },
    methods:{
      showInFo(e){
          // e.stopPropagation();//阻止冒泡行为
          // e.preventDefault();//阻止默认行为,可省略在@click中施行
        alert('欢迎欢迎')
          // console.log(e.target);
      },
      showMsg(msg){
          console.log(msg)
      },
      demo(){
            for (let i = 0; i <10000; i++) {
                console.log('#')
            }
          console.log('终于结束了')
      }
    }
  })

</script>

④键盘事件:keydown(按下按键不用抬起就能触发)、keyup(按下按键需抬起)

Ⅰ、Vue中常用按键别名:

回车:enter

<input type="text" placeholder="按下回车提示输入" @keyup.enter="showInFo">

删除:delete、退出 :esc

空格:space、换行:tab(必须配合keydown使用)

上:up、下:down

左:left、右:right

<body>
<div id="root">
    <h3>欢迎来到{{name}}</h3>
    <input type="text" placeholder="按下回车提示输入" @keyup.enter="showInFo">
</div>
</body>
<script>
    new Vue({
        el:'#root',
        data:{
            name:'学习室',

        },
        methods:{
            showInFo(e){
                // if (e.keyCode !== 13) return //此语句等价于@keyup.enter
                console.log(e.target.value)
            }
        }
    })

</script>

Ⅱ、Vue未提供别名的按键,可以使用按键原始的key值去绑定,但要注意转为kebab-case(短横线命名)

Ⅲ、系统修饰键(用法特殊):ctrl、alt、shift、meta

(1)配合keyup使用:按下案件的同时再按其他键,随后释放其他键,事件才能被出发

(2)配合keydown使用:正常触发事件

  Ⅳ、也可以使用keyCode去指定具体的键

Ⅴ、Vue.config.keyCode.自定义键名 = 键码,可以去定制按键别名

Vue.config.keyCodes.huiche = 13//定义了一个别名
<body>
<div id="root">
    <h3>欢迎来到{{name}}</h3>
    <input type="text" placeholder="按下回车提示输入" @keydown.huiche="showInFo">
</div>
</body>
<script>
    Vue.config.keyCodes.huiche = 13//定义了一个别名
    new Vue({
        el:'#root',
        data:{
            name:'学习室',

        },
        methods:{
            showInFo(e){
                // if (e.keyCode !== 13) return //此语句等价于@keyup.enter
                console.log(e.target.value)
                // console.log(e.key,e.keyCode)
            }
        }
    })

</script>

七、计算属性与监视

1、姓名案例_插值语法实现

<body>
<div id="root">
    姓:<input type="text" v-model="firstName"><br/><br/>
    名:<input type="text" v-model="lastName"><br/><br/>
    全名:<span>{{firstName.slice(0,3)}}-{{lastName}}</span>
</div>
</body>
<script>
    new Vue({
        el:'#root',
        data:{
            firstName: '张',
            lastName:'三'
        }
    })
</script>

2、姓名案例_methods实现

<body>
<div id="root">
    姓:<input type="text" v-model="firstName"><br/><br/>
    名:<input type="text" v-model="lastName"><br/><br/>
    全名:<span>{{fullName()}}</span>
</div>
</body>
<script>
    new Vue({
        el:'#root',
        data:{
            firstName: '张',
            lastName:'三'
        },
        methods:{
            fullName(){
                return this.firstName + '-' + this.lastName
            }
        }
    })
</script>

3、姓名案例_计算属性实现

<body>
<div id="root">
    姓:<input type="text" v-model="firstName"><br/><br/>
    名:<input type="text" v-model="lastName"><br/><br/>
    全名:<span>{{fullName}}</span>
</div>
</body>
<script>
    const vm = new Vue({
        el:'#root',
        data:{
            firstName: '张',
            lastName:'三'
        },
        computed:{
            fullName:{
                //get作用:当有人读取fullName时get就会被调用 ,
                //且返回值就作为fullName的值
                //get什么时候调用?1、初次读取fullName时 
                //2、所依赖的数据发生变化时
                get(){
                    // console.log(this)//此处的this是vm
                    return this.firstName + '-' + this.lastName
                },

                //set什么时候调用?当fullName被修改时
                set(value){
                    console.log('set', value)
                    const arr = value.split('-')
                    this.firstName = arr[0]
                    this.lastName = arr[1]
                }
            }
        }
    })

计算属性:

1.定义:要用的属性不存在,要用已有的属性计算得来

2.原理:底层借助了Object.defineproperty方法提供的 getter和setter

3.get函数什么时候执行:

(1)初次读取fullName时

(2)所依赖的数据发生变化时

4.优势:与methods相比,内部有缓存机制(复用),效率更高,调试方便

5.备注:

(1)计算属性最终会出现再 vm上,直接读取使用即可

(2)如果计算属性要被修改,那必须写set函数相应修改,且set中要引起计算时依赖的数据发生改变

4、姓名案例_计算属性的简写

只考虑读取不考虑修改的时候才能用简写形式

const vm = new Vue({
        el:'#root',
        data:{
            firstName: '张',
            lastName:'三'
        },
        computed:{
            //完整写法
            /*fullName:{
                get(){
                    return this.firstName + '-' + this.lastName
                },

                set(value){
                    console.log('set', value)
                    const arr = value.split('-')
                    this.firstName = arr[0]
                    this.lastName = arr[1]
                }
            },*/
            //简写
            fullName(){
                return this.firstName + '-' + this.lastName
            }
        }
    }) 

监视属性:watch

1.当监视的属性变化时,回调函数自动调用 进行相关操作

2.监视的属性必须存在,才能进行监视

3.监视的两种写法:

(1)new Vue时传入watch配置

(2)通过vm.$watch监视

1.天气案例

<body>
<div id="root">
  <h3>今天天气很{{info}}</h3>
<!--    绑定事件的时候@xxx=’yyy‘,yyy可以写一些简单的语句-->
<!--  <button @click="isHot = !isHot">切换天气</button>-->
  <button @click="changeWeather">切换天气</button>
</div>
</body>
<script>
  new Vue({
    el:'#root',
    data:{
      isHot:true
    },
    computed:{
        info(){
            return this.isHot ? '炎热' : '凉爽'
        }
    },
    methods:{
        changeWeather(){
            this.isHot = !this.isHot
        }
    }
  })
</script>

2.天气案例-监视属性:watch

<body>
<div id="root">
  <h3>今天天气很{{info}}</h3>
  <button @click="changeWeather">切换天气</button>
</div>
</body>
<script>
  new Vue({
    el:'#root',
    data:{
      isHot:true
    },
    computed:{
        info(){
            return this.isHot ? '炎热' : '凉爽'
        }
    },
    methods:{
        changeWeather(){
            this.isHot = !this.isHot
        }
    },
    watch:{
        isHot:{
            immediate:true,//初始化时 让handler调用一下
            //handler函数什么时候去调用? 当isHot发生改变时
            handler(){
                // console.log('isHot被修改了')
                if (this.isHot == true){
                    console.log('天气被修改,“凉爽”被修改成“炎热”')
                }
                else{
                    console.log('天气被修改,“炎热”被修改成“凉爽”')
                }
            }
        }
    }
  })

3.watch另一种写法:(写在Vue外)

  vm.$watch('isHot',{
      immediate:true,//初始化时 让handler调用一下
      //handler函数什么时候去调用? 当isHot发生改变时
      handler(){
          // console.log('isHot被修改了')
          if (this.isHot == true){
              console.log('天气被修改,“凉爽”被修改成“炎热”')
          }
          else{
              console.log('天气被修改,“炎热”被修改成“凉爽”')
          }
  }})

深度监视:

(1)Vue中的watch默认不监测对象内部值的改变(一层)

(2)配置deep:true可以监测对象内部值的改变(多层)

备注:

(1)Vue自身可以监测对象内部值的改变,但 Vue提供的watch默认不可以

(2)使用watch时根据数据的具体结构,决定是否采用深度监测

<body>
<div id="root">
  <h3>今天天气很{{info}}</h3>
  <button @click="changeWeather">切换天气</button>
    <hr/>
    <h3>a的值是:{{numbers.a}}</h3>
    <button @click="numbers.a++">点我让a++</button>
    <hr/>
    <h3>b的值是:{{numbers.b}}</h3>
    <button @click="numbers.b++">点我让b++</button>
</div>
</body>
<script>
  const vm = new Vue({
    el:'#root',
    data:{
        isHot: true,
        numbers:{
            a: 1,
            b: 1,

        }
    },
    computed:{
        info(){
            return this.isHot ? '炎热' : '凉爽'
        }

    },
    methods:{
        changeWeather(){
            this.isHot = !this.isHot
        },
        numbersa(){
            this.numbers.a  = this.numbers.a + 1
        }

    },
    watch:{
        isHot:{
            // immediate:true,//初始化时 让handler调用一下
            //handler函数什么时候去调用? 当isHot发生改变时
            handler(){
                // console.log('isHot被修改了')
                if (this.isHot == true){
                    console.log('天气被修改,“凉爽”被修改成“炎热”')
                }
                else{
                    console.log('天气被修改,“炎热”被修改成“凉爽”')
                }
            }
        },
        //监视多级结构中某个属性的变化
        // 'numbers.a':{
        //     handler(){
        //         console.log('numbers 变了')
        // },
        'numbers':{
            //监视多级结构中所有属性的变化
            deep:true,
            handler(){
                console.log('numbers 变了')
      }
  }

    }

  })

</script>

4.监视属性-简写

正常写法:

watch:{
      //正常写法
        isHot:{
          // immediate: true,//初始化时让handler调用
          // deep:true,//深度监测
            handler(newValue,oldValue){
                // console.log('isHot被修改了')
                if (this.isHot == true){
                    console.log('天气被修改,“凉爽”被修改成“炎热”')
                }
                else{
                    console.log('天气被修改,“炎热”被修改成“凉爽”')
                }
            }
        },
    }

简写:

watch:{
      //简写
      isHot(newValue,oldValue){
        console.log('isHot被修改',newValue,oldValue)
      }
      
    }

正常写法:

 //正常写法
  vm.$watch('isHot',{
    handler(newValue,oldValue){
      // console.log('isHot被修改了')
      if (this.isHot == true){
        console.log('天气被修改,“凉爽”被修改成“炎热”')
      }
      else{
        console.log('天气被修改,“炎热”被修改成“凉爽”')
      }
    }
  })

简写:

//简写
  vm.$watch('isHot',function (newValue,oldValue){
    console.log('isHot被修改',newValue,oldValue)
  })

注:简写不能配置 immediate、deep属性

姓名案例-watch属性实现

<body>
<div id="root">
    姓:<input type="text" v-model="firstName"><br/><br/>
    名:<input type="text" v-model="lastName"><br/><br/>
    全名:<span>{{fullName}}</span>
</div>
</body>
<script>
    new Vue({
        el:'#root',
        data:{
            firstName: '张',
            lastName: '三',
            fullName:'张-三'
        },
        watch:{
          firstName(val){
                setTimeout(() => {//等待一秒实现
                    this.fullName = val + '-' + this.lastName
                },1000);
            },
            lastName(val){
                this.fullName = this.firstName + '-' + val
            }
        }
    })
</script>

总结:computed和watch之间的区别

        1.computed可以完成的watch都可以完成

        2.watch可以完成的computed不一定能完成 例:watch可以进行异步操作

两个重要 小原则:

        1.所被Vue管理的函数写成普通函数,这样this指向才是vm或组件实例对象

        2.所有不被Vue所管理的函数(定时器 的回调函数 ,ajax的回调函数),最好写成箭头函数,这样this的指向才是vm或 组件实例对象

八、绑定样式

1.绑定class样式

    <style>
        .basic{
            width: 1000px;
            height: 500px;
            border: 1px solid #f0ad4e;
        }
        .happy {
            background-color: burlywood;
        }
        .sad {
            background-color: #555555
        }
        .normal {
            background-color: #3F536E
        }
    </style>
</head>
<body>
    <div id="root">
<!--绑定class样式 字符串写法 适用于:样式类名不确定,需要动态指定        -->
        <div class="basic" :class="mood" @click="changeMood">{{name}}</div>
<!--绑定class样式 数组写法 适用于:要绑定的样式个数不确定,名字也不确定-->
        <div class="basic" :class="['happy', 'sad', 'normal']" @click="changeMood">{{name}}</div><br>
<!--绑定class样式 对象写法 适用于:要绑定的样式个数确定,名字也确定 但要动态决定用不用-->
        <div class="basic" :class="clas" >{{name}}</div>
    </div>
</body>
<script>
    new Vue({
        el:'#root',
        data:{
            name:'丽丽',
            mood:'normal',
            clas:{
                happy:false,
                sad:false,
                normal:false
            }
        },
        methods: {
            changeMood(){
                const arr = ['happy', 'sad', 'normal'];
                const idex = Math.floor(Math.random() * 3);
                this.mood = arr[idex];
            }
        },
    })

</script>

2.绑定style样式

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>style绑定样式</title>
    <script src="../../js/vue.js"></script>
    <link rel="icon" href="../资讯.svg">
</head>
<style>
    .basic{
        width: 1000px;
        height: 500px;
        border: 1px solid #f0ad4e;
    }
    .happy {
        background-color: burlywood;
    }
    .sad {
        background-color: #555555
    }
    .normal {
        background-color: #3F536E
    }
</style>
<body>
<div id="root">
<!--绑定style样式 对象写法-->
<div class="basic" :style="styleObj">{{name}}</div>
<!--绑定style样式 数组写法-->
    <div class="basic" :style="styleArr">{{name}}</div>
</div>
</body>
<script>
    new Vue({
        el:'#root',
        data: {
            name: '黎明',
            styleObj: {
                fontSize: '40px'
            },
            styleArr:[
                {
                    fontSize : '40px',
                    color : 'blue'
                },
                {
                    backgroundColor : 'red'
                }]
        },


    })
</script>
</html>

总结:

class样式

        写法:class="xxx",xxx可以是字符串,对象,数组

                字符串写法适用于:类名不确定,要动态获取

                对象写法适用于:要绑定多个样式个数不确定,名字也不确定

                数组写法适用于:要绑定多个样式,个数确定,名字也确定但不确定用不用

style样式:

        :style={fontSize : xxx}

        :style="[a,b]"其中a b是样式对象

九、条件渲染

1.v-if       v-else-if       v-else

2.v-show

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>条件渲染</title>
    <script src="../../js/vue.js"></script>
    <link rel="icon" href="../资讯.svg">
</head>
<body>
<div id="root">
    <h2>当前的n值是:{{n}}</h2>
    <button @click="n++">点我加1</button>

    <!--    使用v-show做渲染-->
    <!--<h2 v-show="false">欢迎来到{{name}}</h2>-->
    <!--<h2 v-show="1 === 1">欢迎来到{{name}}</h2>-->
<!--    display:none-->

<!--    使用v-if做渲染-->
<!--    <h2 v-if="false">欢迎来到{{name}}</h2>-->
<!--<h2 v-if="1 === 1">欢迎华宁</h2>-->

    <!--    使用v-else和v-else-if做渲染-->
<!--    <div v-if="n === 1">hi我是1</div>-->
<!--    <div v-else-if="n === 2">hi我是2</div>-->
<!--    <div v-else-if="n === 3">hi我是3</div>-->
<!--    <div v-else>哈哈哈</div>-->

<!--    v-if和template的配合使用-->
    <template v-if="n === 1">
        <h2>nihao</h2>
        <h2>666</h2>
        <h2>888</h2>
    </template>
</div>
</body>
<script>
    new Vue({
        el: '#root',
        data:{
            name: '美丽的世界',
            n:'0'
        }
    })
</script>
</html>

总结:

条件渲染:

1.v-if:

写法:1)v-if = "表达式"

           2)v-else-if = "表达式"

           3)v-else = "表达式"

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

特点:不展示DOM元素直接被移除

注意:v-if、v-else-if、v-else一起使用,要求结构不被打断

2.v-show

写法:v-show = "表达式"

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

特点:不展示DOM元素未被移除,仅仅是使用样式隐藏掉

3.备注:使用v-if时元素可能无法获取到,而使用v-show一定可以获取到

十、列表渲染

1.基本列表

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>基本列表</title>
    <script src="../../js/vue.js"></script>
    <link rel="icon" href="../资讯.svg">
</head>
<body>
<div id="root">
<!--    遍历数组-->
    <h2>人员列表</h2>
    <ul>
        <li v-for = "p in persons" :key = "p.id">
            {{p.name}}-{{p.age}}
        </li>
        <br/>
        <li v-for = "(p,inndex) in persons" :key = "inndex">
            {{p.name}}--{{p.age}}--{{inndex}}
        </li>
    </ul>

<!--    遍历对象-->
    <h2>汽车信息</h2>
    <ul>
        <li v-for = "(vul,k) of car" :key = "k">
            {{k}}--{{vul}}
        </li>
    </ul>

    <!--    遍历字符串-->
    <h2>测试遍历字符串</h2>
    <ul>
        <li v-for = "(char,inndex) of str" :key = "inndex">
            {{char}}--{{inndex}}
        </li>
    </ul>

    <!--    遍历指定次数-->
    <h2>测试遍历指定次数</h2>
    <ul>
        <li v-for = "(number,inndex) of 5" :key = "inndex">
            {{number}}--{{inndex}}
        </li>
    </ul>
</div>
</body>
<script>
    new Vue ({
        el: '#root',
        data:{
            persons: [
                {id: '001', name: '张三', age: 18},
                {id: '002', name: '李四', age: 19},
                {id: '003', name: '王五', age: 20}
            ],
            car: {
                name: "劳斯莱斯暗影",
                price: "500w",
                color: "blue"
            },
            str:"green"
        }
    })
</script>
</html>

总结:v-for指令:

                1.用于展示列表数据

                2.语法:v-for =  "(item,inndex) in xxx" :key = "yyy"

                3.可遍历:数组、对象、字符串(用的很少)、指定次数(用的很少)

2.key的原理

当 :key= "inndex" 时出现错误

而key="p.id"正常

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>key的原理</title>
    <script src="../../js/vue.js"></script>
    <link rel="icon" href="../资讯.svg">
</head>
<body>
<div id="root">
    <!--    遍历数组-->
    <h2>人员列表</h2>
    <button @click.once="add">点击添加老刘</button>
    <ul>
        <li v-for = "(p,inndex) in persons" :key = "p.id">
            {{p.name}}--{{p.age}}
            <input >
        </li>
    </ul>
</div>
</body>
<script>
    new Vue({
        el: '#root',
        data: {
            persons: [
                {id: '001', name: '张三', age: 18},
                {id: '002', name: '李四', age: 19},
                {id: '003', name: '王五', age: 20}
            ],
        },
        methods: {
            add(){
                const p = {id: '004', name:'老刘', age:'30'}
                this.persons.unshift(p)
            }
        }
    })
</script>
</html>

面试题:react、Vue中的key有什么作用(key的内部原理)

1.虚拟DOM中key的作用:

key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】

随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:

2.对比规则:

(1)旧虚拟DOM中找到了与新虚拟DOM相同的key:

        ①若虚拟DOM中内容没改变,直接使用之前的真实DOM!

        ②若虚拟DOM中内容变了 ,则生成新的真实DOM,随后替换掉页面中之前的真实DOM

(2)旧虚拟DOM中未找到与新虚拟DOM相同的key

        创建新的真实DOM,随后渲染到页面

3.用index作为key值可能引发的问题:

(1)若对数据进行:逆序添加、逆序删除等破坏顺序操作,

        会产生没有必要的真实DOM更新==>页面效果没问题但效率低

(2)如果解构中还包含输入类的DOM:

        会产生错误DOM更新==>页面有问题

4.开发中如何选择key?

(1)最好使用每条数据的唯一标识作为key,比如id、手机号、身份证号、学号等唯一值

(2)如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示

        使用index作为key值是没有问题 

3.列表过滤

列表过滤

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>列表过滤</title>
    <script src="../../js/vue.js"></script>
    <link rel="icon" href="../资讯.svg">
</head>
<body>
<div id="root">
    <h2>人员列表</h2>
    <input type="text" placeholder="请输入要查找的名字" v-model="keyWord">
    <ul>
        <li v-for = "(p,inndex) in filPersons" :key = "p.id">
            {{p.name}}--{{p.age}}--{{p.sex}}
        </li>
    </ul>


</div>
</body>
<script>
    //用watch实现
/*
 //region
    new Vue ({
        el: '#root',

        data: {
            keyWord: '',
            persons: [
                {id: '001', name: '马冬梅', age: 18, sex: '女'},
                {id: '002', name: '周冬雨', age: 19, sex: '女'},
                {id: '003', name: '周杰伦', age: 20, sex: '男'},
                {id: '004', name: '温兆伦', age: 22, sex: '男'}
            ],
            filPersons: [],

        },

        watch: {
            keyWord: {
                immediate: true,
                handler(vul) {
                    this.filPersons = this.persons.filter((p) => {
                        return p.name.indexOf(vul) !== -1;
                    })
                }
            }
        },
        //#endregion
    })
*/


    //用computed实现
    new Vue ({
        el: '#root',

        data: {
            keyWord: '',
            persons: [
                {id: '001', name: '马冬梅', age: 18, sex: '女'},
                {id: '002', name: '周冬雨', age: 19, sex: '女'},
                {id: '003', name: '周杰伦', age: 20, sex: '男'},
                {id: '004', name: '温兆伦', age: 22, sex: '男'}
            ]
        },
        computed:{
            filPersons(){
                return this.filPersons = this.persons.filter((p) => {
                    return p.name.indexOf(this.keyWord) !== -1;
                })
            }
        }
    })
</script>
</html>

4.列表排序

列表排序

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>列表排序</title>
    <script src="../../js/vue.js"></script>
    <link rel="icon" href="../资讯.svg">
</head>
<body>
<div id="root">
    <h2>人员列表</h2>
    <input type="text" placeholder="请输入要查找的名字" v-model="keyWord">
    <button @click="sortType = 0">原顺序</button>
    <button @click="sortType = 1">年龄降序</button>
    <button @click="sortType = 2">年龄升序</button>
    <ul>
        <li v-for = "(p,inndex) in filPersons" :key = "p.id">
            {{p.name}}--{{p.age}}--{{p.sex}}
        </li>
    </ul>


</div>
</body>
<script>
    //用computed实现
    new Vue ({
        el: '#root',
        data: {
            keyWord: '',
            sortType: 0,//0升序、1降序、2原顺序
            persons: [
                {id: '001', name: '马冬梅', age: 19        , sex: '女'},
                {id: '002', name: '周冬雨', age: 26, sex: '女'},
                {id: '003', name: '周杰伦', age: 30, sex: '男'},
                {id: '004', name: '温兆伦', age: 22, sex: '男'}
            ]
        },
        computed:{
            filPersons(){
                const arr = this.filPersons = this.persons.filter((p) => {
                    return p.name.indexOf(this.keyWord) !== -1;
                })
                //判断是否排序
                if (this.sortType){
                    arr.sort((p1,p2)=>{
                        return this.sortType === 1 ? p2.age-p1.age : p1.age-p2.age;
                    })
                }
                return arr;
             }
        }
    })
</script>
</html>

5.更新时的一个问题

更新时的一个问题

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>更新时的一个问题</title>
    <script src="../../js/vue.js"></script>
    <link rel="icon" href="../资讯.svg">
</head>
<body>
<div id="root">
    <h2>人员列表</h2>
    <button @click = "updataMei">更新马冬梅信息</button>
    <ul>
        <li v-for = "(p,inndex) in persons" :key = "p.id">
            {{p.name}}--{{p.age}}--{{p.sex}}
        </li>
    </ul>


</div>
</body>
<script>
    new Vue ({
        el: '#root',
        data: {
            persons: [
                {id: '001', name: '马冬梅', age: 19, sex: '女'},
                {id: '002', name: '周冬雨', age: 26, sex: '女'},
                {id: '003', name: '周杰伦', age: 30, sex: '男'},
                {id: '004', name: '温兆伦', age: 22, sex: '男'}
            ]
        },
        methods:{
            updataMei() {
                // this.persons[0].name = '马六六';//奏效
                // this.persons[0].age = 21;      //奏效
                // this.persons[0].sex = '男';    //奏效
                this.persons[0] = {id: '001',name: '马六六', age: 21, sex: '男' }//不奏效
            }

        }
    })
</script>
</html>

十一、Vue监测数据

1.Vue监测数据改变的原理

Vue

2.模拟一个数据监测

数据监测使用定时器不现实,

let data = {
    name: '丽丽',
    address: '安徽',
  }
  let tmp = '丽丽';
  setInterval(() => {
    if(data.name != tmp){
      tmp = data.name;
      console.log('name被修改')
    }
  },100)

使用geterr seterr实现

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>模拟一个数据监测</title>
    <script src="../../js/vue.js"></script>
    <link rel="icon" href="../资讯.svg">
</head>
<body>
<script type="text/javascript">
  let data = {
    name: '丽丽',
    address: '安徽',
  };
  //创建一个监视的实例对象,用于监视data中属性的变化
  const obs = new Observer(data);

  //准备一个vm实例对象
    let  vm = {}
  vm._data = data = obs;

  function Observer(obj){
    //汇总对象中所有属性形成一个数组
    const keys = Object.keys(obj)
    //遍历
    keys.forEach((k) => {
    //函数体
      Object.defineProperty(this, k, {
        get() {
          return obj[k]
        },
        set(vul) {
            obj[k] = vul;
            console.log('${k}值被修改');
        }
      })
    })
  }
</script>
</body>
</html>

3.Vue.set()方法

响应式、给学生追加属性

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue.set()的使用</title>
  <script src="../../js/vue.js"></script>
  <link rel="icon" href="../资讯.svg">
</head>

<body>
<div id="root">
    <h1>学校信息</h1>
    <h2>学校名称:{{shool.name}}</h2>
<h2>学校地址:{{shool.address}}</h2>
    <h2>校长信息:{{shool.leader}}</h2>
    <br>
    <h1>学生信息</h1>
     <button @click="addsex">添加一个性别属性,默认值是男</button>
<h2>姓名:{{stu.name}}</h2>
<h2 v-if="stu.sex">性别:{{stu.sex}}</h2>
<h2>年龄:真实{{stu.age.rAge}} 对外{{stu.age.sAge}}</h2>
    <h2>朋友们</h2>
    <ul>
        <li v-for="(f,index) in stu.friends" :key="index">
            {{f.name}}-{{f.age}}
        </li>
    </ul>
</div>
</body>

<script>

  const vm = new Vue({
    el: '#root',
      data: {
        shool:{
            name: '希望学校',
            address: '九水路',
        },
          stu: {
              name: '啾啾',
              age: {
                  rAge: 19,
                  sAge: 22,
              },
              friends: [
                  {name: '卡卡', age: 20},
                  {name: '菇菇', age: 23}
              ]
          },
      },
      methods:{
        addsex(){
            // Vue.set(this.stu, 'sex', '男'),
            this.$set(this.stu, 'sex', '男')//另一种写法同样起作用
        }
      }

  })

</script>
</html>

 4.总结Vue数据监测

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue.set()的使用</title>
  <script src="../../js/vue.js"></script>
  <link rel="icon" href="../资讯.svg">
</head>

<body>
<div id="root">
    <h1>学校信息</h1>
    <h2>学校名称:{{shool.name}}</h2>
<h2>学校地址:{{shool.address}}</h2>
    <h2>校长信息:{{shool.leader}}</h2>
    <hr>
    <h1>学生信息</h1>

<button @click="stu.age++">点击年龄加一</button><br>
<button @click="addsex">点击添加性别属性</button><br>
<button @click="stu.sex='女'">点击修改性别</button><br>
<button @click.once="addfriend">在列表首位添加一个朋友</button><br>
<button @click="reviseFriendName">修改第一位朋友的名字是张三</button><br>
<button @click.once="addHobby">添加一个爱好</button><br>
<button @click.once="reviseHobby">修改第一个爱好为开车</button><br>

<h2>姓名:{{stu.name}}</h2>
    <h2 v-if="stu.sex">性别:{{stu.sex}}</h2>
<h2>年龄:{{stu.age}}</h2>
    <h2>爱好</h2>
    <ul>
        <li v-for="(h,index) in stu.hobby" :key="index">
            {{h}}
        </li>
    </ul>
    <h2>朋友们</h2>
    <ul>
        <li v-for="(f,index) in stu.friends" :key="index">
            {{f.name}}-{{f.age}}
        </li>
    </ul>
</div>
</body>

<script>

  const vm = new Vue({
    el: '#root',
      data: {
        shool:{
            name: '希望学校',
            address: '九水路',
        },
          stu: {
              name: '啾啾',
              age: 22,
              hobby:['抽烟', '喝酒', '烫头'],
              friends: [
                  {name: '卡卡', age: 20},
                  {name: '菇菇', age: 23}
              ]
          },

      },
      methods:{
          addsex() {
              Vue.set(this.stu, 'sex', '男')
          },
          addfriend() {
              this.stu.friends.unshift({name: '龙骨', age: '26'})
          },
          reviseFriendName() {
              this.stu.friends[0].name = '张三'
          },
          addHobby() {
              this.stu.hobby.push('唱歌');
          },
          reviseHobby() {
              // this.stu.hobby.splice(0, 1, '开车');//奏效
              Vue.set(this.stu.hobby, '0', '开车');
          }
      }

  })

</script>
</html>

总结:Vue监视数据的原理:

1.Vue会监视data中所有层次的数据

2.如何监测对象中的数据?

        通过seterr实现监视,且要在new Vue时就传入要检测的数据

        (1)对象中后追加的属性,Vue默认不做响应处理

        (2)如需给后添加的数据做响应式,请使用如下API:

                Vue.set(target, propertName/index, vule)或

                vm.$set(target, propertName/index, vule)

3.如何监测数组中的数据?

        通过包裹数组更新元素的方法实现,本质就是做了两件事:

        (1)调用原生对应的方法对数组进行更新

        (2)重新解析模板,进而更新页面

4.在Vue修改数组中的某个元素一定要使用如下方法:

        1.使用这些API:push()   pop()   shift()   unshift()   splice()   sort()   reverse()

        2.Vue.set()或vm.$set()

特别注意:Vue.set() 和 vm.$set() 不能给vm 或vm的跟数据对象添加属性

十二、收集表单数据

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>收集表单数据</title>
    <script src="../../js/vue.js"></script>
    <link rel="icon" href="../资讯.svg">
</head>
<body>
<div id="root">
    <form @submit="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="smoke">
        喝酒 <input type="checkbox" v-model="userInfo.hobby" value="drink">
        烫头发<input type="checkbox"v-model="userInfo.hobby" value="Perm your hair"><br><br>
        所属校区:
        <select v-model="userInfo.city">
            <option value="">请选择校区</option>
            <option value="beijing">北京</option>
            <option value="shanghai">上海</option>
            <option value="anhui">安徽</option>
            <option value="shenzhen">深圳</option>
            <option value="shandon">山东</option>
        </select>
        <br><br>
        其他信息:<textarea v-model.lazy="userInfo.other"></textarea><br><br>
        <input type="checkbox" v-model="userInfo.agree">我已阅读并接受<a href="#">《用户协议》</a>
        <button>提交</button>
    </form>
</div>
</body>
<script>
    new Vue({
        el: '#root',
        data:{
            userInfo:{
                account: '',
                password: '',
                sex: 'female',
                hobby: [],
                city: '',
                other: '',
                agree: '',
                age:''
            }
        },
        methods:{
            demo(){
                console.log(JSON.stringify(this.userInfo))
            }
        }

    })
</script>
</html>

总结:收集表单数据:

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

        若:<input type="radio"/>,则v-model收集的是value值,且要给标签配置value值

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

            1.没有配置input的value属性,那么收集的就是checkbox(勾选 or 未勾选,是布尔值)

            2.配置input的value属性:

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

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

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

                lazy:失去焦点再收集数据

                number:输入字符串转为有效的数字

                trim:输入首位空格过滤

十三、内置指令

我们学过的指令:

v-on:绑定事件监听可简写为@

v-bind:单向绑定解析表达式,可简写‘xxx’

v-model:双向数据绑定

v-for:遍历数组/对象/字符串

v-if:条件渲染(动态控制节点是否存在)

v-else:条件渲染(动态控制节点是否存在

v-show:条件渲染(动态控制节点是否展示))

1.v-text指令

        1.作用:向其所在的节点中渲染文本内容

        2.与插值语法的区别:v-text会替换掉节点中的内容,{{}}则不会

2.v-html指令

        1.作用:向指定节点中渲染包含html结构的内容

        2.与插值语法的区别:

          (1)v-html会替换掉节点中的内容,{{}}则不会

          (2)v-html可以势识别html解构

3.严重注意:v-html有安全性问题

          (1)在网站上动态渲染任意html是非常危险的,容易导致XSS攻击

          (2)一定要在可信的内容上使用v-html,永远不要在用户提交的内容上!

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>v-html指令</title>
  <script src="../../js/vue.js"></script>
  <link rel="icon" href="../资讯.svg">
</head>
<body>
<div id="root">
  <h2>{{name}}</h2>
  <h2 v-html="str"></h2>
  <h2 v-html="str2"></h2>
</div>
</body>
<script>
  new Vue({
    el: '#root',
    data:{
      name: 'lili',
        str: '<h3>你好</h3>',
        str2:'<a href=javascript:location.href="http://www.baidu.com">这里有你想要的东西,快来</a>'
    }
  })
</script>
</html>

3.v-cloak指令(没有值)

        1.本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性

        2.使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题

4.v-once指令

        1.v-once所在节点在初次动态渲染后,就视为静态内容了

        2.以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>v-once指令</title>
  <script src="../../js/vue.js"></script>
  <link rel="icon" href="../资讯.svg">
</head>
<body>
<div id="root">
<h2 v-once>初始的n值是:{{n}}</h2>
<h2>当前的n值是:{{n}}</h2>
  <button @click="n++">点我n加一</button>
</div>
</body>
<script>
  new Vue({
    el: '#root',
    data:{
      n:0
    }
  })
</script>
</html>

5.v-pre指令

        (1)跳过其所在节点的编译过程

2.可以用它跳过:没有使用指令语法、没有使用插值语法的

十四、自定义指令

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

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

            三、备注:
                1.指令定义时不加v-,但使用时要加v-;
                2.指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名。
十五、生命周期

生命周期:
            1.又名:生命周期回调函数、生命周期函数、生命周期钩子。
            2.是什么:Vue在关键时刻帮我们调用的一些特殊名称的函数。
            3.生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的。
            4.生命周期函数中的this指向是vm 或 组件实例对象。

 

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值