vue2基础

vue

vue2基础语法

1.初识vue

引入vue

<!-- 引入vue -->
    <script type="text/javascript" src="../js/vue.js">
    </script>

1.先准备一个容器

容器的作用:1.为vue提供模板 2.告诉vue将解析好的成果往哪里放

容器中的{{}}括号里要写js表达式,并且可以读到vue实例中的所有属性

所谓js表达式,就是返回一个具体值的特殊的js语句

<div id="id1">
<h1>hello,{{name}}</h1>
</div>
<div id="id2">
<h1>hello,{{name}}</h1>
</div>

注:vue代码要写在

2.创建vue实例

vue实例必须要传入一些配置对象

容器和vue实例是一一对应的,一个vue实例只能对应接管一个容器

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

一旦data中的数据发生修改,那么模块中所有用到该数据的地方都会自动修改

new Vue({
        el:'#id1',
        data:{
          name:"world"
        }
      })
      new Vue({
        el:"#id2",
        data:{
          name:"南工"
        }
      })

注:

el指定当前vue实例为哪个容器服务,通常为css选择器字符串

data用于存储数据,数据供el所指定的容器去使用,值暂时先写成对象

2.vue语法

差值语法:用于解析标签体的内容

指令语法:用于解析标签(包括标签属性,标签体内容,绑定事件等等)

因为在vue中有好多种指令语法,这里只是使用v-bind来演示,用于解析标签属性

<div id="div1">
        <h1>差值语法</h1>
        <h3>hello,{{name}}</h1>
        <hr>
        <h1>指令语法</h1>
        <a v-bind:href="person.url">点一下,{{person.name}}1</a>
        <a :href="person.url">点一下,哈哈哈2</a>
    </div>

注:对于指令语法种的v-bind,可以简写成:,英文的冒号

new Vue({
            el:"#div1",
            data:{
                //data中设计多层级结构
                name:"jack",
                person:{
                    name:"来喽来喽",
                    url:"http://www.baidu.com"
                }
                
            }
        })

3.数据绑定

数据绑定分为单向数据绑定和双向数据绑定

<div id="div1">
        单向数据绑定:<input type="text" v-bind:value="name"><br>
        双向数据绑定:<input type="text" v-model:value="name"><br>
    </div> 

单向数据绑定:data中数据的改变会引起模板中内容的变化,但是模板中内容的改变不会引起data中数据的改变

双向数据绑定:data中数据的改变会引起模板中内容的变化,模板中内容的改变也会引起data中数据的变化

v-model只能用在表单类或者输入类元素上

v-model:value可以简写成v-model,因为v-model默认的找的属性就是value

new Vue({
        el:"#div1",
        data:{
          name:"我最棒"
        }
      })

4.el与data的两种写法

el的两种写法

第一种

new Vue({
        el:"#div1",
        data:{
          name:"南京"
        }
      })

第二种——使用x承接vue,使用$mount进行挂载

var x= new Vue({
            data:{
                name:"南京"
            }
        })
        console.log(x);
        x.$mount('#div1');
data的两种写法

第一种——对象式

new Vue({
        el:"#div1",
        data:{
          name:"南京"
        }
      })

第二种——函数式

new Vue({
        el:"#div1",
        data(){
                    console.log('@@@',this)//此处的this就是指vue实例
                    return{
                        name:"南京"
                    }
                }
      })

注:使用函数式时,必须要有返回值

5.MVVM模型

MVVM

M:model 模型,data中的数据

V:view 视图,模板代码

VM:viewmodel 视图模板,vue实例

通过观察发现:

1.data中所有的数据,到最后都出现在vue(vm)身上了

2.vue身上所有的属性,及vue原型上的所有属性,在vue模板中都可以直接使用

6.数据代理

(1)回顾object.defineProperty方法
        var number=18
        var person={
            name:"张三",
            sex:"男"
        }

现在有需求,想在person中添加age属性,使age和number之间有一座桥梁可以沟通

就要通过defineProperty里的get和set函数

往一个对象上添加一个属性

Object.defineProperty(person,'age',{
            // value:18,
            // enumerable:true,设置属性可以枚举,默认值为false
            // writable:true,设置属性可以修改,默认值为false
            // configurable:true 控制属性可以被删除
    
            //当有人读取person中的age属性时,get函数(getter)就会被调用,返回值就是age属性的值
            get(){
                console.log('有人读取属性了')
                return number
            },

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

            }
        })

注:get方法是在有人读取到对象中的属性时,get方法会被调用,返回值就是读取属性的值

set方法是在有人修改对象中的属性时,set方法会被调用,且收到修改的值

object.defineProperty方法详解

Object.defineProperty()方法是给对象添加属性用的

Object.defineProperty(object, propertyname, descriptor);

其中三个参数分别是:

object:对象

propertyname:属性名

descriptor:要添加的属性值

let person = {
	name: '张三',
	sex: '男'
}

Object.defineProperty(person, 'age', {
	value: 18,   //这个age不能被枚举(不能遍历)
})	

console.log(person);

输出的结果如下:

image-20220918170652848

这个age和name、sex的颜色是不一样的,它不能被枚举(不能遍历)。

Object.defineProperty()方法添加的属性默认是不能修改、删除、遍历,但可以通过修改一些默认值设置是否可修改、删除、遍历。

(2)何为数据代理

数据代理就是通过一个对象代理对另一个对象中属性的操作

通过object2代理object1,往object2身上添加object1身上的属性

 <script>
        var obj={x:100}
        var obj2={y:200}
        
        Object.defineProperty(obj2,'x',{
            get(){
                return obj.x
            },
            set(value){
                obj.x=value
            }
        })
    </script>
(3)vue中的数据代理

vue中的数据代理,通过vm对象来代理data对象中的属性操作,包括读写

数据代理的好处:更加方便地操作data中的数据

基本原理:

​ 通过object.defineProperty方法将data中的所有属性都添加到vm上

​ 为每一个添加到vm上的属性都添加一个setter和getter

​ 在setter和getter内部去操作data中的数据

vm操作data中的数据,将data中的数据全部封装到_data中,并且加上get和set方法,就是所谓的数据代理

<div id="div1">
        <h1>hello,{{name}}</h1>
        <h1>{{address}}</h1>
    </div>
<script>
        var vm =new Vue({
            el:"#div1",
            data:{
                name:"南京",
                address:"南京工业职业技术大学"
            }
        })
        console.log(vm)
 </script>

7.事件处理

1.事件的基本使用

绑定点击事件

<body>
    <div id="div1">
        <h1>欢迎来到{{name}}学习</h1>
        <!-- <button v-on:click="showInfo">点我提示信息</button> -->
        <!-- v-on:click也有简写方式 -->
        <button @click="showInfo1">点我提示信息1</button>
        <button @click="showInfo2(66,$event)">点我提示信息2</button>
    </div>
    
    <script>
        new Vue({
            el:"#div1",
            data:{
                name:"南京"
            },
            methods:{
                showInfo1(event){
                    alert('同学你好!')
                },
                showInfo2(number,event){
                    alert('同学你好!!')
                    console.log(number,event)
                }
            }
        })
    </script>
</body>

注:

如果想向函数里传参数,但是如果单纯的传参数,那么会把event搞丢,于是用个关键字占位

当使用vue写触发函数的时候,函数也要写在vue实例中,使用methods属性

不是所有的触发函数都需要给event占位

2.vue中的事件修饰符

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

2.stop阻止事件冒泡

3.once事件只触发一次

4.capture使用事件的捕捉模式

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

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

<div id="div1">
        <h1>欢迎来到{{name}}</h1><br>
        <a href="http://www.niit.edu.cn" @click.prevent.stop="showInfo">点我一下</a>
    </div>
    
    <script>
        new Vue({
            el:"#div1",
            data:{
                name:"南京"
            },
            methods:{
                showInfo(){
                    alert('同学你好')
                }
            }
        })
    </script>

注:

修饰符是可以连着写的

@click.prevent.stop这样写就代表先阻止默认事件再停止冒泡

3.键盘事件

(1)vue中常用的按键别名:

1.回车——> enter

2.删除——> delete

3.退出——> esc

4.空格——> space

5.换行——> tab(特殊:必须配合keydown去使用,因为tab本身会失去焦点,使用keyup达不到目的)

6.上——> up

7.下——> down

8.左——> left

9.右——> right

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

(3)系统修饰键(用法特殊)

ctrl alt shift meta

【1】配个keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才会被触发

【2】配合keydown使用:正常触发事件

【3】可以使用keycode去指定具体的按键(不推荐)

(4) Vue.config.keyCodes.自定义键名= 键码, 可以去定制按键别名

 <div id="div1">
        <input type="text" placeholder="按下回车提示输入" @keyup.huiche="showInfo">
        <br>
        <input type="text" placeholder="按下回车提示输入" @keyup.enter="showInfo">
        <br>
        <!-- 对于现在有需求,只有按下ctrl+y时才能提示 -->
        <!-- 对于系统修饰符,也可以连着写,后面再带一个就表示组合使用时才有效 -->
        <input type="text" placeholder="按下ctrl+y提示输入" @keyup.ctrl.y="showInfo">
    </div>
    
    <script>
        //创建个别名
         Vue.config.keyCodes.huiche=13,
        new Vue({
           
            el:"#div1",
            data:{
                name:"南京"
            },
            methods:{
                showInfo(event){
                   console.log(event.target.value)
                }
            }
        })
    </script>

8.计算属性

1.使用差值语法实现姓名案例
<div id="div1">
        姓:<input type="text" v-model="firstName"><br><br>
        名:<input type="text" v-model="lastName"><br><br>
        全名:<span>{{firstName}}-{{lastName}}</span>
    </div>

    <script>
        new Vue({
            el:"#div1",
            data:{
                firstName:"张",
                lastName:"三"
            }
        })
    </script>

注:

data域中的数据发生变化,vue一定会重新解析模板,并且这里用到的v-model双向绑定

2.使用methods实现姓名案例
<div id="div1">
        姓:<input type="text" v-model="firstName"><br><br>
        名:<input type="text" v-model="lastName"><br><br>
        全名:<span>{{fullName()}}</span>
    </div>

    <script>
        new Vue({
            el:"#div1",
            data:{
                firstName:"张",
                lastName:"三"
            },
            methods:{
                fullName(){
                    //因为这里的this代表的是vue实例,所以可以直接获取data域中的数据
                    return this.firstName+"-"+this.lastName
                }
            }
        })
    </script>

注:

对于函数使用差值语法调用,如果不加括号就是在页面上显示函数内容,加了括号显示函数返回值

3.使用计算属性实现姓名案例

什么叫属性,data域中定义的就叫做属性,例如:firstName就叫做属性,张就叫做属性值

计算属性的概念:利用现有属性,通过拼拼凑凑使之成为一个全新的属性就叫做计算属性

data域中的属性会出现在_data中,但是计算属性中的属性不会出现在下划线data中

<div id="div1">
        姓:<input type="text" v-model="firstName"><br><br>
        名:<input type="text" v-model="lastName"><br><br>
        全名:<span>{{fullName}}</span>
    </div>

    <script>
        var vm= new Vue({
            el:"#div1",
            data:{
                firstName:"张",
                lastName:"三"
            },
            computed:{
                fullName:{
                    get(){
                        return this.firstName+'-'+this.lastName
                    },
                    set(value){
                        //将value按照-来拆分成两个部分
                        var arr = value.split("-");
                        this.firstName=arr[0]
                        this.lastName=arr[1]

                    }
                }

                //计算属性也存在简写形式
                //如果要是想使用计算属性的简写形式就必须确定不会用到set方法
                // fullName(){
                //     return this.firstName+'-'+this.lastName
                // }
            }
        })
    </script>

注:

和defineProperty中的getter类似,只要有人读取了fullname,get就会被调用,返回值就作为fullname的值

get函数何时调:1.初次使用fullname时会调用get函数 2.当get函数中所依赖的属性发生改变时,会调用get函数(因为计算属性有缓存的存在,为了能拿到最新的数据,所以产生了第二种会调用get函数的情况)

计算属性最终会出现在vm身上,直接读取使用即可

有get肯定就会有set,set函数何时调用:当fullname被修改的时候会调用set

有种感觉计算属性不是真实存在的东西,它有所依赖,所以要想把计算属性给改掉,要从根本下手,也就是把计算属性依赖的属性给改掉

9.监视属性

1.天气案例
<body>
    <div id="div1">
        <h2>今天天气很{{info}}</h2>
        <button @click="changeWeather">点击切换</button>
    </div>
    
    <script>
        new Vue({
            el:"#div1",
            data:{
                isHot:true
            },
            //为了使差值语法中的内容不是很复杂,使用计算属性
            computed:{
                info(){
                    return this.isHot ? '炎热' : '凉爽'
                }
            },
            methods: {
                changeWeather(){
                    this.isHot = !this.isHot
                }
            }
        })
    </script>
</body>
2.天气案例-监视属性

监视属性:watch

对于监视属性同样可以监视计算属性,监视属性必须存在才能监视

 watch:{
                isHot:{
                immediate:true,
                     //handler什么时候调用,当isHot发生改变时调用
                handler(newValue,oldValue){
                    console.log('isHot已经发生改变',newValue,oldValue)
                }
                },
                info:{
                     //handler什么时候调用,当info发生改变时调用
                handler(newValue,oldValue){
                    console.log('info已经发生改变',newValue,oldValue)
                }
                }
            }

注:

immediate属性,默认值是false,在初始化时调用一下handler

handler什么时候调用,当被监视的属性发生改变时调用handler

监视属性的语法:

要监视的属性名:{
         immediate(可以设置也可以不设置)
         handler(newValue,oldValue){
         handler有两个参数,newValue和oldValue,表示改变后的记录和改变前的记录
         }
}

另一种实现监视属性的方法

vm.$watch('isHot',{
            immediate:true,
                     //handler什么时候调用,当isHot发生改变时调用
                handler(newValue,oldValue){
                    console.log('isHot已经发生改变',newValue,oldValue)
                }
        })

注:

有两个注意点:

1.vm的这个api有两个参数要传

2.当你指定了要去监视谁时一定要用引号括起来

其他的写法跟内部的watch写法完全相同

那么这两种方式分别在什么时候用

当创建vue实例时就已经知道要监视的是谁了,就在内部用watch

如果创建实例的时候不清楚要监听谁,那就用vm的外部接口

监视属性实现天气案例完整代码

<body>
    <div id="div1">
        <h2>今天天气很{{info}}</h2>
        <button @click="changeWeather">点击切换</button>
    </div>
    
    <script>
        var vm= new Vue({
            el:"#div1",
            data:{
                isHot:true
            },
            computed:{
                info(){
                    return this.isHot ? '炎热' : '凉爽'
                }
            },
            methods: {
                changeWeather(){
                    this.isHot = !this.isHot
                }
            },
            watch:{
                isHot:{
                immediate:true,
                handler(newValue,oldValue){
                    console.log('isHot已经发生改变',newValue,oldValue)
                }
                },
                info:{
                handler(newValue,oldValue){
                    console.log('info已经发生改变',newValue,oldValue)
                }
                }
            }
        })
    </script>
</body>
3.天气案例-深度监视

vue中的watch默认不监测对象内部值的改变(默认只看一层)

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

watch:{
                isHot:{
                handler(newValue,oldValue){
                    console.log('isHot已经发生改变',newValue,oldValue)
                }
                },
                //现在有需求是想监视a但是不想监视b
                //这种写法是监视多级结构中某个属性的变化
                'numbers.a':{
                    handler(){
                        console.log('a已经被改变了')
                    }
                },
                //如果想要监视numbers中所有属性的变化
                //这种写法是监视多级结构中所有属性的变化
                numbers:{
                    deep:true,
                    handler(){
                        console.log('numbers中的属性发生了变化')
                    }
                }
            }

注:

需要注意的是如果只想监视多级结构中的某个属性的变化,对于要监视的属性,一定要拿引号引起来,for example: ‘numbers.a’

完整代码

<div id="div1">
        <h2>今天天气很{{info}}</h2>
        <button @click="changeWeather">点击切换</button>
        <hr/>
        <h3>a的值是{{numbers.a}}</h3>
        <button @click="numbers.a++">点我让a加1</button>
        <h3>b的值是{{numbers.b}}</h3>
        <button @click="numbers.b++">点我让b加1</button>
    </div>
    
    <script>
        var vm= new Vue({
            el:"#div1",
            data:{
                isHot:true,
                numbers:{
                    a:1,
                    b:2
                }
            },
            computed:{
                info(){
                    return this.isHot ? '炎热' : '凉爽'
                }
            },
            methods: {
                changeWeather(){
                    this.isHot = !this.isHot
                }
            },
            watch:{
                isHot:{
                handler(newValue,oldValue){
                    console.log('isHot已经发生改变',newValue,oldValue)
                }
                },
                'numbers.a':{
                    handler(){
                        console.log('a已经被改变了')
                    }
                },
                numbers:{
                    deep:true,
                    handler(){
                        console.log('numbers中的属性发生了变化')
                    }
                }
            }
        })
    </script>
4.使用watch实现姓名案例

当监听属性和计算属性都能完成一个功能时,首先选择计算属性,简单

但是如果你想在实现功能的同时在实现异步任务,还是监听属性方便

例如:你想在修改姓名一秒钟之后再显示改完的名字,就只能用监听属性

watch:{
                firstName(newValue){
                    //在使用监视属性实现功能时,用新的姓+原来的名进行拼接
                    setTimeout(() => {
                        this.fullName=newValue+'-'+this.lastName
                    }, 1000);
                },
                lastName(newValue){
                    this.fullName=this.firstName+'-'+newValue
                }
            }

注:在使用监视属性时可以内置箭头函数,但是使用计算属性时不可以

完整代码

<div id="div1">
        姓:<input type="text" v-model="firstName"><br><br>
        名:<input type="text" v-model="lastName"><br><br>
        全名:<span>{{fullName}}</span>
    </div>

    <script>
        var vm= new Vue({
            el:"#div1",
            data:{
                firstName:"张",
                lastName:"三",
                fullName:'张-三'
            },
            watch:{
                firstName(newValue){
                    //在使用监视属性实现功能时,用新的姓+原来的名进行拼接
                    setTimeout(() => {
                        this.fullName=newValue+'-'+this.lastName
                    }, 1000);
                },
                lastName(newValue){
                    this.fullName=this.firstName+'-'+newValue
                }
            }
        })
    </script>

10.vue绑定样式

(1)

在这里插入图片描述

注:绑定class样式,适用于,样式的类名不确定,需要动态绑定

(2)

在这里插入图片描述

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

两种方法最大的区别就在于,绑定的样式的个数是不是确定的,如果需要绑定的样式个数写死的话那么用字符串方便,但是如果个数不确定的话,数组明显比字符串方便

(3)

在这里插入图片描述

注:对象写法,适用于:需要绑定的样式个数确定,名字也确定,但是需要动态决定用还是不用

(4)绑定style内联样式

在这里插入图片描述

注:将style样式写成一个对象,然后通过vue去动态调整

11.条件渲染

使用v-show做条件渲染,如果v-show后面的判别式成立的话就显示内容,不成立的话就不显示内容

<script>
        new Vue({
            el:"#div1",
            data:{
                name:'南京',
                a:false,
                n:0
            },
           
        })
    </script>
 <h2 v-show="true">欢迎来到{{name}}</h2>
 <h2 v-show="1===3">欢迎来到{{name}}</h2>

使用v-if做条件渲染,用法和v-show相同,但是v-if有一些延申用法

<h2 v-if="1===3">欢迎来到{{name}}</h2>
<h2 v-if="true">欢迎来到{{name}}</h2>

既然有v-if,那么对应的肯定有v-else-if,这两者属于一组判断

,一般情况下使用else-if能提高效率,当然还有v-else

如果想满足需求,有三个h2标签,想让标签在n=1时全部显示出来,一种选择就是在每个h2上都加上判断,但是这样实现起来太麻烦

还有一种办法就是使用div将代码块包裹起来,但是这样会破坏原来的结构,即

<div v-show="n===1">
        <h2>你好</h2>
        <h2>南京</h2>
        <h2>仙林大学城</h2>
        </div>

最好的办法是使用template将代码块包裹起来,通过控制台可以看出并没有影响结构

但是需要注意的一点是template只能配合v-if去使用

<template v-if="n===1">
        <h2>你好</h2>
        <h2>南京</h2>
        <h2>仙林大学城</h2>
        </template>

12.列表渲染

(1)基本列表
<script>
        new Vue({
            el:"#div1",
            data:{
                persons:[
                    {id:"001",name:"张三",age:"18"},
                    {id:"002",name:"李四",age:"19"},
                    {id:"003",name:"王五",age:"20"}
                ],
                cars:{
                    name:"奥迪A8",
                    price:"70w",
                    color:"黑色"
                }
            }
        })
    </script>

对于遍历使用的是v-for标签

使用v-for遍历数组

 <h2>人员列表</h2>
        <ul v-for="p in persons" :key="p.id">
            <!-- 此处的in也可以换成of,跟js中的两个循环一致for in 和 for of -->
            <li>{{p.name}}-{{p.age}}</li>
        </ul>

使用v-for遍历对象

<h2>汽车信息</h2>
        <ul v-for="(value,key) in cars" :key="key">
            <!-- 此处的in也可以换成of,跟js中的两个循环一致for in 和 for of -->
            <li>{{key}}-{{value}}</li>
        </ul>

注:对于遍历对象时,是先拿到值再拿到键,注意一个顺序问题

还可以遍历字符串,但是用的不多

还可以遍历指定次数,但是用的更少

(2)key的原理

react,vue中的key有什么作用

【1】虚拟dom中key的作用,key是虚拟dom对象的标识,当状态中的数据发生改变时,vue会根据新数据生成新的虚拟dom,随后,vue进行 新虚拟dom与旧虚拟dom的差异比较,比较规则如下

【2】对比规则

旧虚拟dom中找到与新虚拟dom中相同的key

​ 若虚拟dom中的内容不变,直接使用之前的真实dom

​ 若虚拟dom中的内容变了,就生成新的真实dom,随后替换掉页面中原来的真实dom

旧虚拟dom中未找到与新虚拟dom相同的key

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

【3】使用index可能会引发的问题

1.若数据进行逆序添加,逆序删除等破坏顺序的操作,会产生没有必要的真实dom更新,界面效果没有问题,但是效率低

2.如果结构中还包含输入类的dom:会产生错误的dom更新,界面就有问题了

【4】开发中如何选择key

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

2.如果不存在对数据的逆序操作,仅用渲染列表进行展示,使用index作为key是没有问题的

(3)列表过滤

列表过滤,其实就是一个模糊查询

<div id="div1">
        <h2>人员列表</h2>
        <input type="text" placeholder="请输入姓名" v-model="keyWord">
        <ul v-for="p in filPersons" :key="p.id">
            <li>{{p.name}}-{{p.age}}-{{p.sex}}</li>
        </ul>
    </div>
el:"#div1",
            data:{
                keyWord:"",
                persons:[
                    {id:"001",name:"马冬梅",age:"19",sex:"女"},
                    {id:"002",name:"周冬雨",age:"20",sex:"女"},
                    {id:"003",name:"周杰伦",age:"21",sex:"男"},
                    {id:"004",name:"温兆伦",age:"22",sex:"男"},
                ],
                filPersons:[]
            },

用监视属性来实现

取到用户的输入内容之后,如果用户输入的内容发生改变了,也应该知道改变的是什么,变成了什么

watch:{
                keyWord:{
                    immediate:true,
                    handler(val){
                    //接下来要做的就是对比,也就是过滤
                    //这里要注意过滤函数的一点就是,过滤函数会返回一个新的数组,要让数组persons承接一下新数组
                    //但是使用persons去承接新数组,逻辑上又有问题,进行搜索动作之后,除了被搜索的数据,其他数据都不见了
                    //所以,要使用一个新的空数组去承接,就是filePersons
                    //使用新的空数组去承接又有一个新问题,刚打开页面的时候,新数组还是空的,不会显示数据
                    //解决:因为indexOf方法里将空串也判断进包含,所以,不使用简写的方法,而是使用完整的方法实现数据监视属性
                    //然后,使用immediate属性,这样刚打开页面的时候就会调用一次监视器,此时,input输入框中是空值,就可以显示数据了
                    this.filPersons= this.persons.filter((p)=>{
                        return p.name.indexOf(val) !==-1
                        // 在一个字符串里判断是否包含所传的字符,有了就返回下标索引,没有就返回-1
                    })
                    }
                }
            }

用计算属性来实现

el:"#div1",
            data:{
                keyWord:"",
                persons:[
                    {id:"001",name:"马冬梅",age:"19",sex:"女"},
                    {id:"002",name:"周冬雨",age:"20",sex:"女"},
                    {id:"003",name:"周杰伦",age:"21",sex:"男"},
                    {id:"004",name:"温兆伦",age:"22",sex:"男"},
                ]
            },
            computed:{
                filPersons(){
                    return this.persons.filter((p)=>{
                        return p.name.indexOf(this.keyWord) !==-1
                    })
                }
            }

注:

计算属性和监视属性其实逻辑实现上是相同的,都用到了数组过滤器,只是计算属性实现的要更简单一些

(4)列表排序

使用计算属性实现

<div id="div1">
        <h2>人员列表</h2>
        <!-- 对于人员的年龄进行排序 -->
        <input type="text" placeholder="请输入姓名" v-model="keyWord">
        <!-- 如果想知道用户点的到底是哪一个,那么对于排序的标识也及其重要 -->
        <button @click="sortNum=2">年龄升序</button>
        <button @click="sortNum=1">年龄降序</button>
        <button @click="sortNum=0">原顺序</button>
        <ul v-for="p in filPersons" :key="p.id">
            <li>{{p.name}}-{{p.age}}-{{p.sex}}</li>
        </ul>
    </div>
el:"#div1",
            data:{
                keyWord:"",
                sortNum:0,//当降序时是1,升序时是2
                persons:[
                    {id:"001",name:"马冬梅",age:"31",sex:"女"},
                    {id:"002",name:"周冬雨",age:"20",sex:"女"},
                    {id:"003",name:"周杰伦",age:"32",sex:"男"},
                    {id:"004",name:"温兆伦",age:"22",sex:"男"},
                ]
            },
            computed:{
                filPersons(){
                    var arr= this.persons.filter((p)=>{
                        return p.name.indexOf(this.keyWord) !==-1
                    })
                    //判断是否需要进行排序
                    if(this.sortNum!==0){
                        arr.sort((p1,p2)=>{
                            return this.sortNum ===1 ? p2.age-p1.age : p1.age-p2.age
                        })
                    }
                    return arr
                }
            }

注:

这里要说明一下,js自带的sort排序函数,带有两个参数,例如

arr.sort(a,b),如果是a-b,那就是升序排序,如果是b-a,那就是降序排序

还有,计算属性是真的牛逼

(5)更新时的一个问题

现在有一个需求,有一个按钮,点击按钮之后,就会更新页面上马冬梅的信息

<div id="div1">
        <h2>人员列表</h2>
        <button @click="updateMei">点我更新马冬梅信息</button>
        <ul v-for="p in persons" :key="p.id">
            <li>{{p.name}}-{{p.age}}-{{p.sex}}</li>
        </ul>
    </d
methods: {
             updateMei(){
            this.$set(this.persons,0,{id:"001",name:"马老师",age:"50",sex:"男"})
           }
            }

注:

这里存在一个数组更新监测的问题

this.persons[0].name=“马老师” //奏效

​ this.persons[0].age=50 //奏效

​ this.persons[0].sex=“男” //奏效

​ 但是如果这样写,就会出问题

​ this.persons[0] = {id:“001”,name:“马老师”,age:“50”,sex:“男”}

​ vue就不承认信息更新了

​ 对于这个vue不会承认更新的问题,可以有解决办法

​ 1.见word文档,或者是vue官方文档中列表渲染关于数组更新监测

​ this.persons.splice(0,1,{id:“001”,name:“马老师”,age:“50”,sex:“男”})

​ 2.是使用vue.set方法一样可以对于数组进行更新

​ 传入三个参数,1.想要更新的数组,2.更新数组中的哪个对象,3.更新的对象信息

(6)vue_set的使用

这里又有新的需求,本来在定义的data的student里并没有sex这一属性,但是到后来发现必须要有这个属性了,于是通过vue.set的方法进行添加属性

<h2>学生信息</h2>
        <button @click="updateSex">点我添加性别,默认值是男</button>
        <h2>学生姓名:{{student.name}}</h2>
        <h2 v-if="student.sex">学生性别:{{student.sex}}</h2>
        <h2>学生年龄,真实年龄:{{student.age.relAge}},对外年龄:{{student.age.vAge}}</h2>
methods: {
                updateSex(){
                    // vue的set方法,有两种写法
                    // Vue.set(this.student,'sex','男')
                    // 往对象身上添加一个属性,后面是属性名和属性值
                    this.$set(this.student,'sex','男')
                    //这里的this是vm实例
                }
            },
(7)大总结

vue 监视数据的原理:

  1. vue 会监视data 中所有层次的数据·
  2. 如何监测对象中的数据?
    通过setter 实现监视, 且要在new Vue 时就传从入要监视的数据。
    ( 1 )对象中后追加的属性, vue 默认不做响应式处理
    (2 )如需给后添加的属性做响应式, 请使用如下API :
    Vue .set(target , propertyName/index , value) 或
    vm. $set(target , propertyName/index, value)
  3. 如伺监测数组中的数据?
    通过包裹数组更新元素的方法实现, 本质就是做了两件事:
    ( 1 ) 调用原生对应的方法对数组进行更新。
    ( 2 ) 重新解析模板, 进而更新页面。
  4. 在Vue 改数组中的某个元素一 定要用如下方法:
    1 .使用这些api: push() 、pop() 、shift() 、unshift() 、splice() 、sort () 、reverse()
    2.vue.set() 或vm. s e t ( ) ∗ ∗ 特 别 注 意 : v u e . s e t ( ) 和 v m . set () **特别注意: vue.set() 和vm. set()vue.set()vm.set() 不能给vm或者vm的根数据对象添加属性! !**
    将自己写的vm.data中的数据经由vue转变成vm._data的过程叫做数据劫持

13.收集表单数据

<div id="div1">
        <!-- 可以在表单上设置方法阻止默认提交 -->
        <form @submit.prevent="demo">
            <!-- v-model修饰符.trim,去掉字符串前后的空格 -->
              账号:<input type="text" v-model.trim="userInfo.account"> <br><br>
              密码:<input type="password" v-model="userInfo.password"><br><br>
              <!--如果用原生的number来控制,那么传到vm中的数值是字符串类型的,不是数值类型的 -->
              <!-- v-model有修饰符.number会帮你把数据转成数值类型的,而且两个一起使用的话还有输入限制,只能输入数值类型数值 -->
              年龄:<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"><br><br>
              所在校区:
              <select v-model="userInfo.area">
                <option value="">请选择校区</option>
                <option value="xianlin">仙林校区</option>
                <option value="tiantang">天堂校区</option>
                <option value="zhongshan">中山校区</option>
              </select>
              <br><br>
              补充;
              <!-- v-model的修饰符.lazy,不进行实时的数据捕获,只有当输入框失去焦点的一瞬间才会捕获数据 -->
              <textarea v-model="userInfo.otherInfo"></textarea>
              <br><br>
              <input type="checkbox" v-model="userInfo.whether">阅读并接受<a href="http://www.niit.edu.cn">用户协议</a>
              <br><br>
              <!-- 当点击提交按钮时,表单就默认提交了 -->
              <button>提交</button>
        </form>
    </div>

注:

v-model的修饰符:trim,lazy,number

new Vue({
            el:"#div1",
            data:{
                userInfo:{
                account:"",
                password:"",
                sex:"",
                //除了上面的单选框性别要指定value以外,对于可能有多个选择的checkbox,要将v-model指定的对象变成数组的形式
                //否则只会显示单选框是否勾选,不会显示value指定的值,还带着些其他的奇葩错误
                hobby:[],
                area:"",
                otherInfo:"",
                age:"",
                whether:""
                }
            },
            methods: {
                demo(){
                    console.log(JSON.stringify(this.userInfo))
                }
            },
            
        })

注:

这里要特别注意多选checkbox的使用,要将v-model指定的对象变成数组形式,要不然会出现各种各样的奇葩错误,而且得不到想要的value返回

14.过滤器

过滤器一般有两种语法,可以在差值语法里使用,一种是v-bind动态绑定里可以使用

下面这个小案例实现时间格式的转变

(1)使用计算属性实现

        <h2>转变格式后的时间</h2>
        <!-- 计算属性实现 -->
        <h3>当前的时间是:{{formTime}}</h3>
new Vue({
            // 现在这些过滤器只是写在一个vue实例中,是局部过滤器,在new vue实例之前就创建的过滤器是全局过滤器
            el:"#div1",
            data:{
                time:1656302701355
            },
            computed:{
                formTime(){
                    return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss');
                }
            },
      })

(2)使用过滤器实现

过滤器的写法: time | 过滤器名称

前面是你想传给过滤器的参数,加一个空格,管道符|,再加一个空格,过滤器名称

 <h3>当前的时间是:{{time | formTimer}}</h3>
        <!-- 过滤器的传参 -->
        <!-- 'YYYY_MM_DD',传到过滤器里的形式 -->
        <h3>当前的时间是:{{time | formTimer('YYYY_MM_DD')}}</h3>

过滤器的使用,多个过滤器可以串联,像一条链一样从头到尾往下走,往下筛选

filters:{
                // 过滤器里会接受参数,所以
                // 这里就会有一个问题,当过滤器传参指定时间形式时,传参的那个好用,不传参的那个又不好用了
                // 这里可以用es6的默认参数来解决,当有参数传进来时使用传进来的参数,没有的话用默认设定好的
                // str="YYYY-MM-DD HH:mm:ss"设置好的默认值
                formTimer(value,str="YYYY-MM-DD HH:mm:ss"){
                    return dayjs(value).format(str);

                }
            }

当然也可以设置全局过滤器

 Vue.filter('myslice',function(value){
            return value.slice(0,4)
        })

全局过滤器,前面的myslice是过滤器名称,后面的function内容是过滤器内容体

15.内置指令

v-text和v-html
<div id="div1">
        <div>{{name}}</div>
        <div v-text="str"></div>
        <div v-html="str"></div>
    </div>
    
    <script>
        new Vue({
            el:"#div1",
            data:{
                name:"南工",
                str:"<h2>南工额</h2>"
           }
        })

这里有特别需要注意的几点

1.v-html支持结构的解析,但是v-text不支持

2.v-html有很严重的安全问题,及其容易导致xss跨站脚本攻击

v-clock

v-clock指令没有值,本质上是一个特殊属性,当vue实例创建完毕并接管容器后,会删掉v-clock属性

使用css配合v-clock解决因为网速慢的时候页面出现{{xxx}}的问题

v-once

用途

1.v-once所在的节点在初次渲染后就视为静态内容了,不在发生变化

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

用例

现在想要的需求是获得一个初始化的n,但是与vue实例有关联不是直接写死的数值

<h2 v-once>初始化的数值是{{n}}</h2>
        <h2>当前的数字是{{n}}</h2>
        <button @click="n++">点我n+1</button>
new Vue({
            el:"#div1",
            data:{
                n:1
            }
        })

在这里,v-once修饰的节点虽然是从data中读取的数据,但是data中数据的改变就不会影响到这个节点的变化了

v-pre

用途

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

2.可利用它跳过没有使用指令语法没有使用差值语法的节点,可以提高效率,加快编译

<div id="div1">
        <h2 v-pre>vue其实真够难的</h2>
        <h2>当前的数值是{{n}}</h2>
        <button @click="n++">点我n+1</button>
    </div>

    <script>
        new Vue({
            el:"#div1",
            data:{
                n:1
            }
        })
        </script>

16.自定义指令

需求1:定义一个v-big指令,与v-text的功能相同,但是会把字体放大十倍(函数指令)

需求2:定义一个v-fbind指令,与v-bind指令功能类似,但是可以让其所绑定的元素自动获取焦点(对象指令)

注意:指令名的问题

如果指令中存在多个单词,那么每个单词之间使用-连接,在下面定义指令体的时候要写完整的形式,也就是用’'把指令包起来

<div id="div1">
            <h2>当前的数值是<span v-text="n"></span></h2>
            <h2>放大之后的数值是<span v-big-number="n"></span></h2>
            <button @click="n++">点我n+1</button>
            <hr>
            <input type="text" v-fbind="n">
</div>

自定义指令往模块中渲染不是靠return,而是靠两个参数,element和binding

new Vue({
                el:"#div1",
                data:{
                    n:1
                },
                directives:{
                    'big-number'(element,binding){
                        // console.log(element,binding)
                        element.innerText=binding.value*10
                        console.log('big-number',this)//注意此处的this就不再是vm了,此处的this是window
                    },
                    fbind:{
                        // 指令与元素成功绑定时会有vue来帮你调用
                        bind(element,binding){
                            console.log(element,binding)
                            // 把n=1放入输入框
                            element.value=binding.value
                        },
                        // 指令所在元素被插入页面时会有vue来帮你调用
                        inserted(element,binding){
                            element.focus()
                        },
                        // 指令所在模板被重新解析时,会有vue来帮你调用
                        update(element,binding){
                            // 把n=1放入输入框
                            element.value=binding.value
                        }
                    }
                }
            })

big-number函数何时会被调用

1.指令与元素成功绑定时会调用

2.指令所在的模板被重新解析时,也就是id="div1"这个模板

对于两个参数,element代表的是span元素,binding中主要关注的就是value值,就是v-big-number中用到的n

vue给定了固定的函数指令三个 bind inserted update

至于为何需求二要使用对象指令来完成

因为,如果你想在元素上获取焦点,就只能在元素已经被放到页面后再去执行.focus()才会奏效

如果继续使用函数自定义指令的话,那么再怎么执行.fouces()也不能在元素放到页面后执行,只会在之前执行,那样就无法达到目的

在vue实例中的指令是局部指令,如果想变成全局指令就和过滤器一样

Vue.directive('fbind2',{
                        bind(element,binding){
                            element.value=binding.value
                        },
                        inserted(element,binding){
                            element.focus()
                        },
                        update(element,binding){
                            element.value=binding.value
                        }
                    })
            Vue.directive('big2',function(element,binding){
                        element.innerText=binding.value*10
                        console.log('big-number',this)
                    })

17.生命周期

引出生命周期

使用一个案例引出生命周期,完成渐变效果

<div id="div1">
        <h2 :style="{opacity}">欢迎学习vue</h2>
    </div>
    
    <script>
       var vm= new Vue({
            el:"#div1",
            data:{
                opacity:1
            },
            mounted() {
                console.log('mounted')
                setInterval(()=>{
                   this.opacity-=0.01
                   if(vm.opacity<=0) this.opacity=1
                },16)
            },
        })
       </script>


mount有挂载的意思,那么何为挂载

vue将模板从虚拟dom变成真实dom,将真实dom放在页面上的过程叫做挂载

vue完成模板解析,并把初始的真实dom元素放在页面中(挂载完毕)调用mounted

需要特别注意的是,是初始的真实dom,也就是说mounted只会在开头被调用一次

总结:

生命周期

1.又名 生命周期钩子,生命周期回调函数,生命周期函数

2.是什么:vue在关键时刻帮我们的一些特殊名称的函数

3.生命周期函数的名字不可更改,但是函数的具体内容是程序员根据需求编写的

4.生命周期中的this指向的是vm或组件实例对象

分析生命周期
 <div id="div1">
        <h2>当前的n值为:{{n}}</h2>
        <button @click="add">点我n+1</button>
        <button @click="bye">点我销毁vm</button>
    </div>
    
    <script>
        new Vue({
            el:"#div1",
            data:{
                n:1
            },
            methods:{
                add(){
                    this.n++
                },
                bye(){
                    this.$destroy()
                }
            },
            // vue生命周期函数
            // 创建之前和创建完毕一定不是vm创建之前和创建完毕
            // 是数据监测和数据代理的创建之前和创建完毕
            beforeCreate() {
                console.log('beforeCreate')
                console.log(this)
            },
            created() {
                console.log('created')
                console.log(this)
            },
            beforeMount() {
                // 页面呈现的是未经vue编译的dom结构,此时对所有dom的操作最终都不奏效
                console.log('beforeMount')
                console.log(this)
            },
            mounted() {
                // 页面呈现的是经vue编译的dom结构
                console.log('mounted')
                console.log(this)
            },
            beforeUpdate() {
                // 此时数据是新的,但是页面是旧的,就意思数据和页面并没有保持同步
                console.log('beforeUpdate',this.n)
            },
            updated() {
                //此时页面是新的,数据也是新的
                console.log('update',this.n)
            },
            beforeDestroy() {
                console.log('beforeDestroy')
            },
            destroyed() {
                console.log('Destroyed')
            },

        })
    </script>
总结完善

常用的生命周期钩子:

1.mounted:发送ajax请求 ,启动定时器,绑定自定义事件,订阅消息等【初始化操作】

2.beforeDestory:清除定时器,解绑自定义事件,取消订阅消息等【收尾工作】

关于销毁vue实例

1.销毁后借助vue开发者工具看不到任何信息

2.销毁后自定义事件会失效,但是原生dom事件依然有效

3.一般不会在beforeDestoryc操作数据,因为即使操作数据,也不会触发更新流程了

<div id="div1">
        <h2 :style="{opacity}">欢迎学习vue</h2>
        <button @click="stop">点击停止变换</button>
    </div>
    
    <script>
       var vm= new Vue({
            el:"#div1",
            data:{
                opacity:1
            },
            methods: {
                stop(){
                    this.$destroy()
                }
            },
            mounted() {
                console.log('mounted')
               this.timer= setInterval(()=>{
                   this.opacity-=0.01
                   if(vm.opacity<=0) this.opacity=1
                },16)
            },
            beforeDestroy() {
                clearInterval(this.timer)
            },
        })

    </script>

18.组件

对于组件的理解

1.理解:用来实现局部(特定)功能效果的代码集合

2.为什么要使用组件:一个界面的功能很复杂

3.作用:复用代码,简化项目编码,提高运行效率

什么叫模块化
当应用中的 js 都以模块来编写的, 那这个应用就是一个模块化的应用。

非单文件组件
一个文件中包含有n个组件
单文件组件
一个文件中只包含有1个组件

非单文件组件

第一步:创建一个组件

const school= Vue.extend({
            // 组件里应当包括完成局部内容交互中的所有内容,所以上面的div中的内容也应该放到组件里来
            template:`<div>
                <h2>学校名称:{{schoolName}}</h2>
                <h2>学校地址:{{address}}</h2>
                <button @click="showName">点我提示学校名</button>
                    </div>`, 

           //对于组件里的data只能写成函数式,而不能再写成对象式了,如果写成对象式会报错,提醒你写成函数式
           data(){
            // 在函数里返回一个对象
            return{
                schoolName:"南京工业职业技术大学",
                 address:"仙林大学城"
            }
           },
           methods: {
            showName(){
                alert(this.schoolName)
            }
           },

        })

        const student = Vue.extend({
            template:`<div>
                <h2>学生姓名:{{studentName}}</h2>
                <h2>学生年龄:{{age}}</h2>
                    </div>`,

            data(){
                return {
                studentName:"张鑫",
                age:"22"
                }
            }
        })

第二步:注册组件(局部注册)

new Vue({
            el:"#div1",
            // 第二步:注册组件(局部注册)
            components:{
                school,
                student
            }
        })

第三步:使用组件标签使用组件

<div id="div1">
        <school></school>
        <hr>
        <student></student>
    </div>

将上述两个内容创建成两个组件,一个school组件,一个student组件

需要特别注意的是,在组件里是没有资格写el的,el只有在创建vue实例对象时候才能写

因为最终所有的组件都是由一个vm进行统一管理,由vm来决定到底用在哪而不是由组件来决定到底用在哪

既然有局部组件那么一定还有全局组件

几个注意点

关于组件标签的写法

​ 1.开始结束

​ 如:

​ 2.自闭和

​ 如:

​ 注意:在不使用脚手架时,使用会导致后续组件不能渲染

​ 3.关于组件的创建方式

​ const school =Vue.extend(options)

​ 简写方式:

​ const school = options

<div id="div1">
        <my-school></my-school>
    </div>

    <script>
        const s= Vue.extend({
            // 可以使用name配置项规定组件在开发者工具中呈现的名字,不随注册组件中的名字改变而改变
            name:'Njuit',
            template:`<div>
                <h2>学校名称:{{schoolName}}</h2>
                <h2>学校地址:{{address}}</h2>
                <button @click="showName">点我提示学校名</button>
                    </div>`, 
           data(){
            return{
                schoolName:"南京工业职业技术大学",
                 address:"仙林大学城"
            }
           },
           methods: {
            showName(){
                alert(this.schoolName)
            }
           },

        })

        new Vue({
            el:"#div1",
            components:{
                // 第一个注意点:当组件的名称是多个单词组成的,vue建议是单词中间用短横杠去表示
                'my-school':s
            }
        })
    </script>
组件的嵌套

在标准化开发中,通常有一个app组件,这个app组件由vm来直接领导,然后这个app组件来管理其他组件

对于嵌套的组件,要把哪个组件嵌套在哪里,就在父组件里进行组件的注册和组件的调用

 <div id="div1">
        <app></app>

    </div>

    <script>
         const student= Vue.extend({
            template:`<div>
                <h2>学生姓名:{{name}}</h2>
                <h2>学生年龄:{{age}}</h2>`,
           data(){
            return{
                name:"张鑫",
                age:22
            }
           }
        })

       const school= Vue.extend({
            template:`<div>
                <h2>学校名称:{{schoolName}}</h2>
                <h2>学校地址:{{address}}</h2>
                <student></student>
                <button @click="showName">点我提示学校名</button>
                    </div>`, 
           data(){
            return{
                schoolName:"南京工业职业技术大学",
                 address:"仙林大学城"
            }
           },
           methods: {
            showName(){
                alert(this.schoolName)
            }
           },
           components:{
            student
           }

        })

        const app = {
            template:`
                      <div>
                        <school></school>
                      </div>`,
            components:{
                school
            }
        }


        new Vue({
            el:"#div1",
            components:{
                app
            }
        })
    </script>
VueComponent
 <div id="div1">
        <school></school>
    </div>
    
    <script>
        const hello = Vue.extend({
            template:`<span>欢迎来到南京</span>`
        })

        const school = Vue.extend({
            template:`<div>
                      <h2>{{name}}</h2>
                      <h2>{{address}}</h2>
                      <hello></hello>
                      </div>`,
             data() {
                    return {
                            name:"南京工业职业技术大学",
                            address:"仙林大学城"
                        }
                      },
            components:{
                hello
            }
        })

        new Vue({
            el:"#div1",
            components:{
                school
            }
        })

    </script>

总结

关于 VueComponent :

1.schoo1组件本质是一个名为 Vuecomponent 的构造函数,且不是程序员定义的,是 Vue.extend 生成的。

2.我们只需要写<school/>或<school></ school >, Vue 解析时会帮我们创建 school 组件的实例对象,

即 Vue 帮我们执行的: new Vuecomponent ( options )。

3.特别注意:每次调用 Vue . extend ,返回的都是一个全新的 VueComponent !!!

4.关于 this 指向:

(1).组件配置中:

data 函数、 methods 中的函数、 watch 中的函数、 computed 中的函数它们的 this 均是【 Vuecomponent 实例对象】.

(2). new Vue ()配置中:

data 函数、 methods 中的函数、 watch 中的函数、 computed 中的函数它们的 this 均是【 Vue 实例对象】。

5.Vuecomponent的实例对象,以后简称 vc (也可称之为:组件实例对象)。

Vue 的实例对象,以后简称 Vm 。

关于vc和vm的区别,如果不那么认真的比较话,vc和vm是可以画等号的,vm身上有的东西vc身上也有,但是vm还是有一些vc身上没有的东西

例如:vm中可以使用el来断定vm为哪个容器服务,但是vc中不能写el,还有vm中的data可以使用对象的形式进行定义,但是vc中的data只能是函数的形式

一个重要的内置关系

一个重要的内置关系

VueComponent.prototype.杠杠proto杠杆 = Vue.prototype

为什么要有这个关系

想要组件的实例对象vc也能使用vue上面的属性和方法

<script>
        // 重温一下原型
        // 定义一个构造函数
        function Demo(){
            this.a=1
            this.b=2
        }

        // 创建一个实例
        const d= new Demo()

        console.log(Demo.prototype) // 显示原型属性
        console.log(d.__proto__) // 隐式原型属性
        // 对于显示,隐式原型,显示原型对象只有函数才可以拥有,隐式原型对象是实例拥有

        // 隐式原型对象总是指向他缔造者的原型对象

        console.log(Demo.prototype===d.__proto__)

        // 通过显示原型属性操作原型对象,往对象中添加一个新的属性 x=99
        Demo.prototype.x=99

        console.log('@',d.x)
        
    </script>

19.浅学一下css3样式

2D转化
<style>
        div{
    margin: 150px;
    width: 200px;
    height: 100px;
    background-color: yellow;
    border: 1px solid black;
    border: 1px solid black; 
      /*scale(2,3)转变宽度为原来的大小的2倍,和其原始大小3倍的高度。  */
    /* transform: scale(2,3); */
    /* translate值(50px,100px)是从左边元素移动50个像素,并从顶部移动100像素。
       定义的是图像的左右和上下移动 */
    /* transform: translate(150px,200px); */
    /* rotate()方法,在一个给定度数顺时针旋转的元素。负值是允许的,这样是元素逆时针旋转。
       rotate(180deg)延顺时针方向转180度 */
    /* transform: rotate(180deg); */
    /* 包含两个参数值,分别表示X轴和Y轴倾斜的角度,如果第二个参数为空,则默认为0,参数为负表示向相反方向倾斜。
skewX(<angle>);表示只在X轴(水平方向)倾斜。
skewY(<angle>);表示只在Y轴(垂直方向)倾斜。
     skew(30deg,20deg) 元素在X轴和Y轴上倾斜20度30度。*/ 
    /* transform: skew(30deg,20deg); */
    /* matrix其实就是将所有的2d转换方法进行了一个大融合
    matrix 方法有六个参数,包含旋转,缩放,移动(平移)和倾斜功能。 */
    transform: matrix(0.866,0.5,-0.5,0.866,0,0);
        }
       
    </style>
</head>
<body>
    <div>
        <h3>直接难上加难</h3>
    </div>
</body>
过渡
<style>
       div {
    width: 100px;
    height: 100px;
    background: red;
    transition: width 2s, height 2s, transform 2s;
}
/* 注意: 如果未指定的期限,transition将没有任何效果,因为默认值是0。

指定的CSS属性的值更改时效果会发生变化。一个典型CSS属性的变化是用户鼠标放在一个元素上时:
 */

      div:hover {
    width: 200px;
    height: 200px;
    transform: rotate(180deg);
}

    </style>

</head>
<body>
    <div>
        <h3>真是难上加难喽</h3>
    </div>
    
</body>
动画
/* 
        当在 @keyframes 创建动画,把它绑定到一个选择器,否则动画不会有任何效果。

指定至少这两个CSS3的动画属性绑定向一个选择器:

规定动画的名称
规定动画的时长

动画是使元素从一种样式逐渐变化为另一种样式的效果。

您可以改变任意多的样式任意多的次数。

请用百分比来规定变化发生的时间,或用关键词 "from" 和 "to",等同于 0% 和 100%。

0% 是动画的开始,100% 是动画的完成。

为了得到最佳的浏览器支持,您应该始终定义 0% 和 100% 选择器。
*/
        div{
    width:100px;
	height:100px;
	background:red;
    position: relative;
    animation: myFirstAnimal;
    /* 以下就是动画中的所有属性 */
	animation-duration:5s;
	animation-timing-function:linear;
	animation-delay:2s;
	animation-iteration-count:infinite;
	animation-direction:alternate;
	animation-play-state:running;
        }

        @keyframes myFirstAnimal
        {
            /* 0% {background-color: red;}
            25% {background-color: purple;}
            50% {background-color: black;}
            75% {background-color: greenyellow;}
            100% {background-color: pink;} */
            0%   {background:red; left:0px; top:0px;}
	        25%  {background:yellow; left:200px; top:0px;}
	        50%  {background:blue; left:200px; top:200px;}
	        75%  {background:green; left:0px; top:200px;}
	        100% {background:red; left:0px; top:0px;}
        }
    
    </style>
</head>
<body>
    <div>

    </div>
</body>
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值