IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 尚硅谷_vue -> 正文阅读

[JavaScript知识库]尚硅谷_vue

1. Vue基础

01 初始vue

1. 想让vue工作,就必须创建一个Vue实例,且要传入一个配置对象;
2. root容器里的代码依然符合html规范,只不过混入了一些特殊的Vue语法;
3. root容器里的代码被称为【Vue模板】;
4. Vue实例和容器是一一对应的;
5. 真实开发中只有一个Vue实例并且会配合着组件一起使用;
6. {{xxx}}中的xxx要写js表达式,且xxx可以自动读取到data中的所对应的属性;
7. 一旦data中的数据发生改变,那么模板中用到该数据的地方也会自动更新;

注意区分:js表达式 和 js代码(又称为“语句”)
    1. 表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方,如:
        Date.now() // 获取当前时间戳
        a+b
        demo(1)
        x === y ? 'a' : 'b'
    2. js代码(语句)
        if(){}
        for(){}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="../js/vue.js"></script>
    <title>初始vue</title>
</head>
<body>
    <div id="root">
        <!-- 使用{{数据键}}取出vue实例中的值 -->
        <h1>hello, {{name.toUpperCase()}}, {{address}}</h1>
    </div>
    <script>
        Vue.config.productionTip = false;
        // 创建vue实例
        new Vue({
            // el用于指定当前vue实例为那个容器服务,值通常为css选择器字符串
            el: '#root',
            // data中用于存储数据,数据供el所所指定的容器去使用。值我们暂时写成一个对象。
            data: {
                name: 'badi',
                address: "贵州花溪"
            }
        });
    </script>
</body>
</html>

02 Vue模板语法

1. 插值语法:
    功能:用于解析标签体内容;
    写法:{{xxx}},xxx是js表达式,且可以直接读取到data中的所有属性。
2. 指令语法:
    功能:用于解析标签(包括:标签属性、标签体内容、绑定事件...)
    举例:v-bind:href="xxx" 或简写为 :href="xxx", xxx同样需要写为js表达式。且可以直接读取到data中所有的属性。

注:Vue中有很多的指令,且形式都是:v-???,此处我们只是拿v-bind举个例子。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>模板语法</title>
    <script src="../js/vue.js"></script>
</head>
<body>
    <!-- 准备好一个容器 -->
    <div id="root">
        <h1>插值语法</h1>
        <h3>你好, {{name}}</h3>
        <hr>
        <h1>指令语法</h1>
        <!-- 
            v-bind:(这里的冒号不能省略)的作用是将属性后面的值当做“js语句”来执行,即自动从vue实例当中取寻找url的变量,并将变量值作为该属性的值。
            v-bind: === 可以简写为 :
         -->
        <a v-bind:href="school.url">点击我去{{school.name}}学习1</a>
        <a :href="school.url">点击我去{{school.name}}学习2</a>
    </div>
    <script>
        Vue.config.productionTip=false;
        new Vue({
            el: "#root",
            data:{
                name: 'zhangsan',
                school: {
                    name: "尚硅谷",
                    url: 'http://www.atguigu.com/'
                }
            }
        });
    </script>
</body>
</html>

03 数据绑定

Vue当中有两种数据绑定的方式:
	1. 单向绑定(v-bind):数据只能从data流向页面;
	2. 双向绑定(v-model):数据不仅能从data流向页面,还可以从页面流向data
注:
	3. 双向绑定一般都应用在表单类元素上(如:input、select等)
	4. v-model:value可以简写为v-model,因为v-model默认收集的就是value的值。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <script src="../js/vue.js"></script>
</head>
<body>
    <div id="root">
        <!-- 普通写法 -->
        <!-- 单向的数据绑定:<input type="text" v-bind:value="name"><br>
        双向的数据绑定:<input type="text" v-model:value="name"> -->

        <!-- 简写 -->
        单向的数据绑定:<input type="text" :value="name"><br>
        双向的数据绑定:<input type="text" v-model="name"><br>

        <!-- 如下代码是错误的,因为v-model只能应用在表单类元素(输入类元素)上! -->
        <!-- <h1 v-model:x="name">你好呀</h1> -->
    </div>
    <script>
        Vue.config.productionTip=false;
        new Vue({
            el: "#root",
            data:{
                name: "尚硅谷"
            }
        });
    </script>
</body>
</html>

04 el与data的两种写法

data与el的2种写法:
  1. el有2中写法
      1)new Vue()时配置el属性;
      2)先创建Vue实例,随后在通过vm.$mount("#root")指定el的值;
  2. data有2中写法
      1)对象式;
      2)函数式;

      如何选择?目前那种写法都可以,以后学习到组件时,data必须使用函数式,否则会报错。
  3. 一个重要的原则:
      有Vue管理的函数,一定不要写箭头函数,一旦写成了箭头函数,函数的this就不再是Vue实例了。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <script src="../js/vue.js"></script>
</head>
<body>
    <div id="root">
        <h1>hello, {{name}}</h1>
    </div>
    <script>
        Vue.config.productionTip=false;
        const x = new Vue({
            // el的第一种写法
            // el: "#root",

            // data的第一种写法,对象式
            // data:{
            //     name: 'zhangsan'
            // }

            // data的第二种写法,函数式
            // 也可以写成data(){}这种方式
            data: function(){
                return {
                    name: 'zhangsan'
                }
            }
        });
        // el的第二种写法
        x.mount("#root");
    </script>
</body>
</html>

05 MVVM模型

MVVM模型总结:
    1. M模型(Model):data中的数据
    2. V视图(View):模板代码
    3. VM视图模型(ViewModel):Vue实例
观察发现:
    1. data中所有的属性,最后都出现再了vm身上;
    2. vm身上所有的属性以及Vue原型上所有属性,在Vue模板中都可以直接使用。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <script src="../js/vue.js"></script>
</head>
<body>
    <div id="root">
        <h1>学校名称:{{name}}</h1>
        <h1>学校地址:{{url}}</h1>
        <h1>测试1:{{1+1}}</h1>
        <h1>测试2:{{$options}}</h1>
    </div>
    <script>
        Vue.config.productionTip=false;
        const vm = new Vue({
            el: "#root",
            data:{
                name: "尚硅谷",
                url: "北京"
            }
        });
        console.log(vm);    
    </script>
</body>
</html>

06 数据代理

06.1 回顾Object.defineproperty

<script>
   let number = 20;
   let person = {
       name: 'zhangsan',
       sex: 'male'
       // age: 20
   }
   // 给person对象添加age属性
   Object.defineProperty(person, 'age', {
       // 给age属性赋值
       // value: 20,
       // // 通过defineProperty()方法添加的属性默认不能被遍历(枚举),可以使用下面的属性进行指定。
       // enumerable: true,
       // writable: true, // 是否可以被修改,默认为false
       // configurable: true // 是否可以被删除,默认为false
       
       // 取值
       get(){
           console.log('有人读取age属性了');
           return number;
       },

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

   // 遍历person对象中的属性
   // console.log(Object.keys(person));
   console.log(person);
</script>

06.2 何为数据代理

<!-- 数据代理:通过一个对象代理另一个对象中属性的操作(读/写) -->
<script>
    let obj = {x: 100};
    let obj2 = {y: 200};
    // 通过在obj2对象当中添加x属性来操作obj中的x属性。
    Object.defineProperty(obj2, 'x', {
        get(){
            return obj.x;
        },
        set(value){
            obj.x = value;
        }
    });
</script>

06.3 Vue当中的数据代理

1. Vue中的数据代理:通过vm对象来代理data对象中属性的操作(读/写);
2. Vue中数据代理的好处:更加方便的操作data中的数据;
3. 基本原理:
    通过Object.defineProperty()把data对象中所有属性添加到vm上;
    为每一个添加到vm上的属性,都指定一个getter/setter,在getter/setter内部去操作data中对应的属性;
<body>
    <div id="root">
        <h1>学校名称:{{name}}</h1>
        <h1>学校地址:{{address}}</h1>
    </div>
    <script>
        Vue.config.productionTip=false;
        const vm = new Vue({
            el: "#root",
            data: {
                name: '尚硅谷',
                address: '滨江区'
            }
        });
    </script>
</body>

07 事件处理

07.1 事件的基本使用

事件的基本使用:
    1. 使用v-on:xxx 或 @xxx 绑定事件,其中xxx是事件名称;
    2. 时间的回调函数需要配置在methods对象中,最终会在vm上;
    3. methods中配置的函数,不要使用箭头函数!否则this就不再是vm了;
    4. methods中配置的函数,都是被Vue所管理的函数,this的只想是vm 或 组件实例对象;
    5. @click="demo" 和 @click="demo($event)" 效果是一样的,但后者可以传指定的参数;
<body>
    <div id="root">
        <h1>欢迎来到{{name}}学习</h1>
        <!-- vue当中给button绑定点击事件 -->
        <!-- <button v-on:click="showInfo">点我弹出提示信息</button> -->

        <!-- v-on: 可以简写为 @ -->
        <button @click="showInfo1">点我弹出提示信息1(不传递参数)</button>
        <!-- 
            需求:当点击“点我弹出提示信息2”按钮时,传递数值666。
        
            在vue当中调用函数时,函数名后面的括号可以不写,也可以写,如果需要传参就写括号并将参数写在括号里面。但是如果仅仅是这样会导致
            一些另外的信息无法被传递,如event时间,vue的解决是使用$event这种关键字来解决。
        -->
        <button @click="showInfo2(666, $event)">点我弹出提示信息2(传递参数)</button>
    </div>
    <script>
        Vue.config.productionTip=false;
        new Vue({
            el: "#root",
            data:{
                name: '尚硅谷'
            },
            // 在vue当中编写函数
            // 其实在methods中的函数也可以定义在data中,但是不建议这样做,这样会使得Vue的工作量变得很大,因为函数本身是不需要做数据代理的。
            methods:{
                // 在对象当中定义函数时,不需要function关键字,直接编写函数名即可
                showInfo1(event){
                    // 通过event事件对象的target属性获取发生该事件的元素
                    // console.log(event.target);
                    // 此处的this是Vue实例
                    // console.log(this); 
                    alert("同学你好!");
                },
                showInfo2(number, event){
                    console.log(number);
                    console.log(event);
                    // alert("同学你好!!");
                }
            }
        });
    </script>
</body>

07.2 事件修饰符

Vue中的时间修饰符:
    1. prevent:阻止默认事件(常用);
    2. stop:阻止时间冒泡(常用);
    3. once:事件只触发一次(常用);
    4. self:只有event.target是当前操作的元素时才触发事件;
    5. passive:事件的默认行为立即执行,无需等待时间回调执行完毕;
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <script src="../js/vue.js"></script>
    <style>
        *{
            margin-top: 5px;
        }
        #wrapper{
            height: 100px;
            background-color: #bfa;
            line-height: 100px;
        }
        #box1, #box2{
            padding: 5px;
        }

        #box1{
            height: 100px;
            background-color: #bfa;
        }
        #box2{
            height: 40px;
            background-color: orange;
        }
        #list{
            height: 100px;
            background-color: skyblue;
            overflow: auto;
        }
        #list li{
            margin: 20px;
        }
    </style>
</head>
<body>
    <div id="root">
        <h2>欢迎来到{{name}}学习</h2>
        
        <!-- 阻止默认行为,同:event.preventDefault(); -->
        <a href="http://www.atguigu.com" @click.prevent="showInfo">点我提示信息</a>
        
        <!-- 阻止事件冒泡行为:何为事件冒泡?即子元素中的行为会传递到父元素当中去。 -->
        <div id="wrapper" @click="wrapperInfo">
            <!-- 通过stop来阻止冒泡的传递行为。 -->
            <!-- 先阻止冒泡,在阻止超链接的默认行为。stop与prevent的顺序可以交换,效果也是一样的。即修饰符通常是可以连着写的。 -->
            <a href="#" @click.stop.prevent="wrapperInner">去百度</a>
        </div>

        <!-- 设置事件只触发一次。 -->
        <button @click.once="showInfo">我只会触发一次</button>

        <!-- 使用事件的捕获模式:事件的捕获与事件的冒泡顺序恰好相反。 -->
        <div id="box1" @click.capture="showMsg(1)">
            div1
            <div id="box2" @click="showMsg(2)">
                div2
            </div>
        </div>

        <!-- 只有event.target是当前操作的元素时才触发事件。 -->
        <div id="demo1" @click.self="showEvent">
            div1
            <div id="demo1" @click="showEvent">
                div2
            </div>
        </div>

        <!-- 事件的默认行为立即执行,无需等待时间回调执行完毕; -->
        <!-- 
            注意@scroll与@wheel的区别:这个.passive事件的默认行为常常跟@wheel搭配一起使用;
         -->
        <ul id="list" @scroll="demo">
            <li>1</li>
            <li>2</li>
            <li>3</li>
            <li>4</li>
        </ul>
    </div>
    <script>
        Vue.config.productionTip=false;
        new Vue({
            el: "#root",
            data:{
                name: '尚硅谷'
            },
            methods:{
                showInfo(evnet){
                    // 阻止超链接a标签的默认跳转行为
                    // event.preventDefault();
                    alert("同学你好!");
                },
                wrapperInfo(){
                    alert("wrapper");
                },
                wrapperInner(){
                    alert("wrapper inner");
                },
                showMsg(msg){
                    console.log(msg);
                },
                showEvent(event){
                    console.log(event.target);
                },
                demo(){
                    // 默认情况下,一些元素的默认行为要等到回调函数执行完毕之后才会执行,当回调函数太复杂时,可以使用passive事件修饰符进行修饰。
                    for(i = 0; i < 1000000; i++){
                        console.log(i);
                    }
                    console.log('累坏了');
                }
            }
        });
    </script>
</body>
</html>

07.3 键盘事件

1.Vue中常用的按键别名:
    回车 => enter
    删除 => delete (捕获“删除”和“退格”键)
    退出 => esc
    空格 => space
    换行 => tab (特殊,必须配合keydown去使用)
    上 => up
    下 => down
    左 => left
    右 => right

2.Vue未提供别名的按键,可以使用按键原始的key值去绑定,但注意要转为kebab-case(短横线命名,如:CapsLock要替换为caps-lock)

3.系统修饰键(用法特殊):ctrl、alt、shift、meta(win键)
    (1).配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发。
    (2).配合keydown使用:正常触发事件。

4.也可以使用keyCode去指定具体的按键(不推荐)

5.Vue.config.keyCodes.自定义键名 = 键码,可以去定制按键别名(不推荐使用,因为一般情况下默认的都已经够使用了)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <script src="../js/vue.js"></script>
</head>
<body>
    <div id="root">
        <h1>键盘事件测试</h1>
        <!-- 按下enter键(回车键)时触发demo回调函数。 -->
        <!-- 这里系统修饰键后面还可以加上其他的按键,表示只有系统修饰键+指定的键时才会触发。 -->
        <input type="text" placeholder="请输入你的字符" @keyup.ctrl.y="demo">
    </div>
    <script>
        Vue.config.productionTip=false;
        new Vue({
            el: "#root",
            data:{
                
            },
            methods:{
                demo(event){
                    // event.key 按键名称;
                    // event.keyCode 按键编码;
                    console.log(event.key,event.keyCode);
                }
            }
        });
    </script>
</body>
</html>

08 计算属性

08.1 姓名按钮_插值语法实现

<div id="root">
    姓:<input type="text" v-model="firstName"><br>
    名:<input type="text" v-model="lastName"><br>
    <!-- 截取firstName中的前三个字符。 -->
    全名:<span>{{firstName.substring(0,3)}}-{{lastName}}</span>
</div>
<script>
    Vue.config.productionTip=false;
    new Vue({
        el: "#root",    
        data:{
            firstName: '张',
            lastName: '三'
        }
    });
</script>

08.2 姓名按钮_methods实现

<div id="root">
    姓:<input type="text" v-model="firstName"><br>
    名:<input type="text" v-model="lastName"><br>
    <!-- 调用fullName函数,fullName()表示调用函数;fullName表示函数对象。 -->
    <!-- 在Vue当中,data当中的数据发生变化时,Vue模板当中的数据会被自动更新。模板中的函数会被重新调用。 -->
    全名:<span>{{fullName()}}</span>
</div>
<script>
    Vue.config.productionTip=false;
    new Vue({
        el: "#root",    
        data:{
            firstName: '张',
            lastName: '三'
        },
        methods:{
            fullName(){
                return this.firstName + '-' + this.lastName;
            }
        }
    });
</script>

08.3 姓名按钮_计算属性实现

计算属性:
     1.定义:要用的属性不存在,要通过已有属性计算得来。
     2.原理:底层借助了Objcet.defineProperty方法提供的getter和setter。
     3.get函数什么时候执行?
         (1).初次读取时会执行一次。
         (2).当依赖的数据发生改变时会被再次调用。
     4.优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便。
     5.备注:
         1.计算属性最终会出现在vm上,直接读取使用即可{{fullName}}。
         2.如果计算属性要被修改,那必须写set函数去响应修改(否则会报错),且set中要引起计算时依赖属性数据发生改变后,该计算属性的值才有效。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <script src="../js/vue.js"></script>
</head>
<body>
    <div id="root">
        姓:<input type="text" v-model="firstName"><br>
        名:<input type="text" v-model="lastName"><br>
        <!-- 调用fullName函数,fullName()表示调用函数;fullName表示函数对象。 -->
        <!-- 在Vue当中,data当中的数据发生变化时,Vue模板当中的数据会被自动更新。模板中的函数会被重新调用。 -->
        全名:<span>{{fullName}}</span> <br><br>
        <!-- 全名:<span>{{fullName}}</span> <br><br>
        全名:<span>{{fullName}}</span> <br><br>
        全名:<span>{{fullName}}</span> <br><br>
        全名:<span>{{fullName}}</span> <br><br> -->
    </div>
    <script>  
        Vue.config.productionTip=false;
        const vm = new Vue({
            el: "#root",    
            data:{
                firstName: '张',
                lastName: '三'
            },
            // 计算属性
            computed:{
                // 这个fullName并不会直接出现在vm的_data属性中,因为fullName计算属性是通过计算出来的。
                fullName:{
                    // 当fullName这个属性被调用时,get()方法会被执行。
                    // get()什么时候调用?
                    //  1. 初次读取fullName时,一般情况下之后都是读取缓存的内容;
                    //  2. 所依赖的数据发生变化时,get()也会被调用;
                    get(){
                        // 此处的this就是vm
                        
                        // 延迟1秒
                        /*setTimeout(function() {
                            // 在计算属性中这样写是不行的,因为计算属性靠的就是get函数的返回值,而这里的返回值会被当成是
                            // setTimeout里面回调函数的返回值。但是在watch当中却可以。即:计算属性不支持异步任务,但是watch却可以。
                            return this.firstName + '-' + this.lastName;
                        }, 1000);*/
                        return this.firstName + '-' + this.lastName;
                    },
                    set(value){
                        const temp = value.split("-");
                        this.firstName = temp[0];
                        this.lastName = temp[1];
                    }
                }
            }
        });
    </script>
</body>
</html>

08.4 计算属性的简写

Vue.config.productionTip=false;
const vm = new Vue({
    el: "#root",    
    data:{
        firstName: '张',
        lastName: '三'
    },
    // 计算属性
    computed:{
        // 完整写法
        // fullName:{
        //     get(){
        //         // 此处的this就是vm
        //         return this.firstName + '-' + this.lastName;
        //     },
        //     set(value){
        //         const temp = value.split("-");
        //         this.firstName = temp[0];
        //         this.lastName = temp[1];
        //     } 
        // }

        // 简写形式
        /* 
        因为我们使用计算属性时大多数情况都是只读取而很少去改变,即大多数都是使用get方法。所以我们可以直接将get方法简写为:

        fullName: function(){

        }

        当然还可以简写为:
        fullName(){

        }
        一定要注意,上面的fullName计算属性并不是一个函数,而是将fullName这个计算属性的get方法执行的返回值返回给fullName计算属性。
        在Vue模板当中使用fullName属性时,也是直接写fullName,而不是fullName()。
        */
       fullName(){
        return this.firstName + "-" + this.lastName;
       }
    }
});

09 监视属性

09.1 天气案例

如果methods中的方法实现的功能很简单,如这里只是对当前的天气取反,那么可以直接在@click后面进行编写,即@后面可以编写一些简单的js语句。
但是不建议编写较为复杂的语句。

@xxx="yyy";xxx事件名,yyy执行的语句。

<button @click="isHot = !isHot">切换天气</button>

以下的代码会报错:
	<button @click="alert(1)">切换天气</button>
	因为被Vue所管辖的模板当中,所有的方法、变量都是在vue实例当中取寻找,如果找不到则报错,而不会跳转到上一级作用域当中去寻找(window)。
<div id="root">
    <h2>今天天气很{{info}}</h2>
    <button @click="changeWeather">切换天气</button>
</div>
<script>
    Vue.config.productionTip=false;
    new Vue({
        el: "#root",
        data:{
            isHot: true
        },
        computed:{
            info(){
                return this.isHot ? '炎热' : '凉爽';
            }
        },
        methods: {
          changeWeather(){
            // 要修改当前的天气,直接取反即可
            this.isHot = !this.isHot;
          }  
        },
    });
</script>

09.2 天气案例_属性监视

监视属性watch:
    1.当被监视的属性变化时, 回调函数自动调用, 进行相关操作
    2.监视的属性必须存在(不存在也不会报错,但是没有意义),才能进行监视!!
    3.监视的两种写法:  
        (1).new Vue时传入watch配置
        (2).通过vm.$watch监视
<div id="root">
    <h2>今天天气很{{info}}</h2>
    <button @click="changeWeather">切换天气</button>
</div>
<script>
    Vue.config.productionTip=false;
    const vm = new Vue({
        el: "#root",
        data:{
            isHot: true
        },
        computed:{
            info(){
                return this.isHot ? '炎热' : '凉爽';
            }
        },
        methods: {
          changeWeather(){
            this.isHot = !this.isHot;
          }  
        },
        // 属性监视
        // 第一种方式
        // watch:{
        //     // 这里监视的属性不仅可以是data中的属性,也可以是computed中的计算属性。
        //     isHot:{
        //         immediate: true, // 让handler()在初始化的时候就执行一次。
        //         // 当isHot属性被修改时handler()函数会被执行
        //         // 该函数有两个参数,第一个为属性的改变后的值,第二个为属性修改之前的值。
        //         handler(newValue, oldValue){
        //             console.log("handler()被执行了:" + newValue, oldValue);
        //         }   
        //     }
            
        // }
    });

    // 属性监视的第二种方式
    vm.$watch('isHot', {
        immediate: true,
        handler(newValue, oldValue){
            console.log("handler()被执行了:" + newValue, oldValue);
        }   
    });
</script>

09.4 天气案例_深度监视

深度监视:
    1. Vue中的watch默认不监视对象内部值的改变(默认只能监视一层);
    2. 配置deep:true可以检测对象内部值的改变(可以监视多层);
注:
    1. Vue自身可以检测对象内部值的改变,但Vue提供的watch默认不可以;
    2. 使用watch时根据数据的具体结构,决定是否采用深度监视;
<div id="root">
  <h2>今天天气很{{info}}</h2>
  <button @click="changeWeather">切换天气</button>
  <hr>
  <h2>a的值是{{numbers.a}}</h2>
  <button @click="numbers.a++">点我给a+1</button>
  <h2>b的值是{{numbers.b}}</h2>
  <button @click="numbers.b++">点我给b+1</button>
</div>
<script>
  Vue.config.productionTip=false;
  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;
        }  
      },
      // 属性监视
      // 第一种方式
      watch:{
          // 这里监视的属性不仅可以是data中的属性,也可以是computed中的计算属性。
          isHot:{
              immediate: true, // 让handler()在初始化的时候就执行一次。
              // 当isHot属性被修改时handler()函数会被执行
              // 该函数有两个参数,第一个为属性的改变后的值,第二个为属性修改之前的值。
              handler(newValue, oldValue){
                  console.log("handler()被执行了:" + newValue, oldValue);
              }   
          },
          // 监视多级结构中某个属性的变化
          // 注意:在JavaScript对象中:
          // key: value 这里的key并没有使用''包裹起来,这是一种简写,正常情况下应该使用单引号包裹起来。
          // 'numbers.a': {
          //     handler(){
          //         console.log("a改变了");
          //     }
          // }
          
          // 监视多级结构中对象所有的属性的变化
          numbers: {
              // 开启深度监测
              deep: true,
              handler(){
                  console.log("numbers属性变化了");
              }
          }
      }
  });     
</script>

09.5 天气案例_深度监视_简写属性

<div id="root">
    <h2>今天天气很{{info}}</h2>
    <button @click="changeWeather">切换天气</button>
</div>
<script>
    Vue.config.productionTip=false;
    const vm = new Vue({
        el: "#root",
        data:{
            isHot: true,
        },
        computed:{
            info(){
                return this.isHot ? '炎热' : '凉爽';
            }
        },
        methods: {
          changeWeather(){
            this.isHot = !this.isHot;
          }  
        },
        /*
        watch:{
            //完整写法
            // isHot:{
            //     // immediate: true, // 初始化时执行handler()方法
            //     // deep: true, // 深度监视
            //     handler(newValue, oldValue){
            //         console.log("handler()被执行了:" + newValue, oldValue);
            //     }   
            // },

            // 简写形式
            // 当我们监视的属性只是简单的调用handler()方法而不处理没有其它的配置时,如:immediate、deep等。
            // 我们就可以使用简写的方式,这里的(){}就相当于是handler()函数。
            isHot(newValue, oldValue){
                console.log("isHot", newValue, oldValue);
            }
        }*/
    });  
    // watch的第二种写法
    // vm.$watch('isHot', function(newValue, oldValue){
    //     console.log("天气的值改变了", newValue, oldValue);
    // }); 
    
    vm.$watch('isHot', {
        // immediate: true, // 初始化时执行handler()方法
        // deep: true, // 深度监视
        handler(newValue, oldValue){
            console.log("handler()被执行了:" + newValue, oldValue);
        }   
    });
</script>

09.5 姓名案例_watch实现

computed和watch之间的区别:
     1.computed能完成的功能,watch都可以完成。
     2.watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作。
两个重要的小原则:
     1.所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm 或 组件实例对象。
     2.所有不被Vue所管理的函数(如定时器的回调函数、ajax的回调函数等、Promise的回调函数),最好写成箭头函数,
         这样this的指向才是vm 或 组件实例对象。
     3. 其实以上两个步骤的目的就是想让函数的this指向vm。
<div id="root">
    姓:<input class="firstName" type="text" v-model="firstName"><br>
    名:<input class="lastName" type="text" v-model="lastName"><br>
    全名:<span>{{fullName}}</span> <br><br>
</div>
<script>  
    Vue.config.productionTip=false;
    const vm = new Vue({
        el: "#root",    
        data:{
            firstName: '张',
            lastName: '三',
            // 让全名默认是firstName-lastName
            fullName: '姓-名'
        },
        watch:{
            // 拥有两个形参,第一个是新的值,第二个是改变后的值
            firstName(val){
                // 这里应该特别注意箭头函数与普通函数的区别:
                // 由于setTimeout中的函数是有js引擎来调用,如果我们这里使用普通函数做回调,则回调函数的this为window。
                // 如果使用箭头函数的话由于这个函数本身没有this,它会向外层寻找this,找到firstName的回调函数时,
                // 将firstName的回调传给setTimeout作为回调函数的this。
                setTimeout(() => {
                    this.fullName = val + '-' + this.lastName;
                }, 1000);
            },
            lastName(val){
                this.fullName = this.firstName + '-' + val;
            }
        }
    });
</script>

10 绑定样式

绑定样式:
   1. class样式
       写法:class="xxx" xxx可以是字符串、对象、数组。
           字符串写法适用于:类名不确定,要动态获取。
           对象写法适用于:要绑定多个样式,个数不确定,名字也不确定。
           数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用。
   2. style样式(了解)
       :style="{fontSize: xxx}"其中xxx是动态值。
       :style="[a,b]"其中a、b是样式对象。
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title></title>
		<style>
			.basic{
				width: 400px;
				height: 100px;
				border: 1px solid black;
			}
			
			.happy{
				border: 4px solid red;;
				background-color: rgba(255, 255, 0, 0.644);
				background: linear-gradient(30deg,yellow,pink,orange,yellow);
			}
			.sad{
				border: 4px dashed rgb(2, 197, 2);
				background-color: gray;
			}
			.normal{
				background-color: skyblue;
			}

			.atguigu1{
				background-color: yellowgreen;
			}
			.atguigu2{
				font-size: 30px;
				text-shadow:2px 2px 10px red;
			}
			.atguigu3{
				border-radius: 20px;
			}
		</style>
		<script type="text/javascript" src="../js/vue.js"></script>
	</head>
	<body>
		<!-- 准备好一个容器-->
		<div id="root">
            <!-- 绑定class样式,字符串写法。适用于:样式的类名不确定而需要动态指定的情况。 -->
			<div class="basic" :class="mood" @click="changeMood">{{name}}</div>
            <br><br>
			
			<!-- 绑定class样式,数组写法。适用于:要绑定的样式个数不确定、名字也不确定。 -->
            <div class="basic" :class="classArr">{{name}}</div>
			<br><br>

			<!-- 绑定class样式,对象写法。适用于:要绑定的样式个数确定、名字也确定,弹药动态决定用不用。 -->
			<div class="basic" :class="classObj">{{name}}</div>
			<br><br>
			
			<!-- style样式,对象的写法 -->
			<div class="basic" :style="styleObj">{{name}}</div>
			<br><br>

			<!-- style样式的数组写法,使用的很少,以下的这两种写法是一样的。 -->
			<!-- <div class="basic" :style="[styleObj, styleObj2]">{{name}}</div> -->
			<div class="basic" :style="styleArr">{{name}}</div>

		</div>
	</body>

	<script type="text/javascript">
		Vue.config.productionTip = false;
		
		const vm = new Vue({
			el: '#root',
            data:{
                name: 'my mood',
                mood: 'normal',
                classArr: ['atguigu1', 'atguigu2', 'atguigu3'],
				classObj:{
					// 默认不启用该属性
					atguigu1: false,
					atguigu2: false
				},
				// 下面的都是样式对象,什么是样式对象?指的是对象的key是不能随便起名的。
				styleObj:{
					// 这里的键名不能随便写,是跟css样式的名一样的,只是多个单词之间使用驼峰命名法进行命名
					fontSize: '40px',
					color: 'blue',
				},
				styleObj2:{
					backgroundColor: '#bfa'
				},
				styleArr:[
					{
						fontSize: '40px',
						color: 'blue',
					},
					{
					backgroundColor: '#bfa'
					}
				]
            },
            methods: {
                changeMood(){
                    // 让mood随机生成
                    const arr = ['happy', 'normal', 'sad'];
                    // random()函数自动生成0~1之前的数,但是娶不到1.
                    this.mood = arr[Math.floor(Math.random()*3)];
                }
            },
		});
	</script>
	
</html>

11 条件渲染

条件渲染:
     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元素未被移除,仅仅是使用样式隐藏掉,底层为display:none
         
     3.备注:使用v-if的时,元素可能无法获取到,而使用v-show一定可以获取到。
<div id="root">
    <!-- v-show可以控制元素节点是否显示(节点本身是存在的),底层使用的是display标签进行控制。 -->
    <!-- <h2 v-show="false">欢迎来到{{name}}学习</h2> -->
    <!-- <h2 v-show="1 === 1">欢迎来到{{name}}学习</h2> -->

    <!-- 使用v-if进行条件的渲染。v-if也可以控制一个节点是否显示,但是与v-show的区别就是当一个元素的v-if为false时,该节点会被删除。 -->
    <!-- <h2 v-if="false">欢迎来到{{name}}学习</h2> -->
    <!-- <h2 v-if="false">欢迎来到{{name}}学习</h2> -->

    <!-- 如何在v-show与v-if之间选择呢?如果切换的频率高则使用v-show,否则使用v-if。 -->

    <!-- 一个简单的小测试 -->
    <h2>n的值是:{{n}}</h2>
    <button @click="n++">点我n的值会加1</button>

    <!-- 进行条件判断,这里也可以换成v-if效果时一样的。 -->
    <!-- <div v-show="n===1">html</div>
    <div v-show="n===2">css</div>
    <div v-show="n===3">js</div> -->

    <!-- 
        使用多层分支:
        if
        else if
        else
        注意:同一组条件判断之前不允许出现其他的元素,否则该条件判断会被打断。
    -->
    <!-- <div v-if="n===1">html</div>
    <div v-else-if="n===2">css</div>
    <div v-else-if="n===3">js</div> -->
    <!-- 这里的v-else可以不用写条件 -->
    <!-- <div v-else>vue</div> -->


    <!-- template与v-if的配合使用,使用template的好处就是template在被解析时不会渲染到页面,即不会影响页面的布局。 -->
    <template v-if="n===1">
        <h2>html</h2>
        <h2>css</h2>
        <h2>js</h2>
    </template>
    
</div>
<script>
    Vue.config.productionTip=false;
    new Vue({
        el: "#root",
        data:{
            name: '尚硅谷',
            n: 0
        }
    });
</script>

12 列表渲染

12.1 基本列表

v-for指令:
    1.用于展示列表数据
    2.语法:v-for="(item, index) in xxx" :key="yyy",这里的key要求是唯一的;
    3.可遍历:数组、对象、字符串(用的很少)、指定次数(用的很少)
<div id="root">
    <h2>人员列表</h2>
    <ul>
        <!-- 使用v-for遍历persons数组,v-for的本质就是js中的for in循环,这里的in也可以换成of,效果是一样的。 -->
        <!-- 以下语句的代表从persons中依次取出数据并赋值给形参person。这里的index代表取出的数据在数组中的索引位置。 -->
        <li v-for="(person, index) in persons" :key="person.id">
            {{person.name}}-{{person.age}}--{{index}}
        </li>
    </ul>

    <h2>汽车信息</h2>
    <ul>
        <li v-for="(car, key) of cars" :key="key">
            {{car}}---{{key}}
        </li>
    </ul>

    <h2>遍历字符串(使用的少)</h2>
    <ul>
        <li v-for="(char,index) of strs" :key="index">
            {{char}}---{{index}}
        </li>
    </ul>

    <h2>直接遍历次数(使用的少)</h2>
    <ul>
        <!-- number从1到10,index从0到9 -->
        <li v-for="(number, index) of 10" :key="index">
            {{number}}---{{index}}
        </li>
    </ul>
</div>
<script>
    Vue.config.productionTip=false;
    new Vue({
        el: "#root",
        data:{
            persons:[
                {id: '001',name: '张三', age:18},
                {id: '002',name: '李四', age:19},
                {id: '003',name: '王五', age:16},
            ],
            cars:{
                name: 'audi a6',
                price: '50w',
                color: 'black'
            },
            strs: 'hello'
        }
    });
</script>

12.2 key的作用与原理

面试题: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是没有问题的。
    5. 值得注意的是:如果么有指定key,key的默认值为index; 

在这里插入图片描述
在这里插入图片描述

<div id="root">
    <h2>人员列表</h2>
    <button @click.once="add">添加人员信息</button>
    <ul>
        <li v-for="(person, index) in persons" :key="person.id">
            {{person.name}}-{{person.age}}--{{index}}
            <input type="text">
        </li>
    </ul>
</div>
<script>
    Vue.config.productionTip=false;
    new Vue({
        el: "#root",
        data:{
            persons:[
                {id: '001',name: '张三', age:18},
                {id: '002',name: '李四', age:19},
                {id: '003',name: '王五', age:16},
            ],
            cars:{
                name: 'audi a6',
                price: '50w',
                color: 'black'
            },
            strs: 'hello'
        },
        methods:{
            add(){
                const liu = {
                    id:'004',
                    name: '老刘',
                    age: 40
                };
                // unshift(),在数组的首位插入元素
                this.persons.unshift(liu);
            }
        }
    });
</script>
  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-09-21 00:19:29  更:2022-09-21 00:19:57 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 10:51:21-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码