记录vue学习

123 阅读4分钟

模板语法

插值:{{ }},在标签体内输出数据

指令

v-bind:,简写为:,用来给标签的属性绑定变量

v-model:用来给表单类标签做数据的双向绑定

el与data的两种写法

el的两种写法

MVVM

1.M:模型,对应data中的数据

2.V:视图,模板

3.VM:视图模型:Vue实例对象,作为模板和视图的中间层,处理双向绑定

数据代理

通过一个对象可以操作另一个对象中属性的值,即通过对象a可以操作对象b中属性的值

// 想通过操作obj1来操作obj2
let obj1 = {}
let obj2 = {
    age:20
}
// 如果访问obj1中的age,那么getter会去查obj2中的age
// 如果修改obj1中的age,那么setter会将修改的值赋给obj2中的age
// 达成了通过obj1来操作obj2中的属性
Object.defineProperty(obj1,'age',{
    // 当obj1对象的age属性被查看时触发get方法,get方法的返回值就是age属性的值
    get() {
        return obj2.age
    },
    // 当obj1对象的age属性被修改时触发set方法,参数就是被修改的值
    set(val) {
        obj2.age = val
    }
})       

Vue中的数据代理

vue中通过new Vue()实例出的vm对象来代理对data对象中属性的操作

具体来讲,就是vue先将data保存在vm对象自身的_data属性中,其中有数据劫持的操作暂时忽略,然后把data中的每一个属性通过Object.defineProperty添加属性到vm实例对象中,当我们通过vm访问name属性时,触发getter方法,实际访问的是_data中的name,修改也是一样,触发setter

const vm = new Vue({
    el:'#app',
    data:{
        name:'张三'
    }
})

image.png

数据代理的好处:利于操作data中数据,比如不用数据代理使用data中数据时得加上_data,{{data_.name}}, 数据代理后直接写{{name}}

Vue中的事件处理

通过指令v-on:可以绑定事件,简写为@,事件的回调函数需要写在methods中

<div id="app">
    <button v-on:click='handle1'>按钮1</button>;
    <button @click='handle2(12,$event)'>按钮2</button>;
</div>
<script>
    Vue.config.productionTip = false
    const vm = new Vue({
        el: '#app',
        data: {
        },
        methods: {
            handle1(event) {
                console.log(event);
            },
            handle2(age, event) {
                console.log(age, event);
            }
        }
    })
</script>

其中有三点需要注意

1、如果回调函数不传参,默认传一个事件对象event,如果回调函数传参数则需要用$event占位,不然接收不到事件对象

2、methods中方法要用普通函数定义,方法内this指向vm或组件实例,如果用箭头函数定义,方法内this会指向window

3、传入的methods也会挂在vm上,但是不会数据代理,也不要将方法定义在data,会让vue累成狗

事件修饰符

1、.prevent:阻止默认事件

2、.stop:阻止冒泡

3、.once:事件只触发一次

4、.capture:使用事件的捕获模式,即在捕获阶段就开始触发事件

5、.self:当前操作的元素是e.target时才触发事件

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

键盘事件

vue中可以使用按键别名来实现特定按键事件

<input @keyup.enter='handle'></input>

enter:回车, delete:删除, esc:返回, space:空格,up:上,down:下,left:左,right:右

计算属性

依赖已有属性计算出的属性,依赖属性发生改变时计算属性也会改变

计算属性存在缓存,只要依赖的值不发生改变,访问计算属性会返回缓存中之前计算的值,不会触发getter重新计算

computed:{
    age:{
        get(){
            return age + 1;
        },
        set(value){
            console.log(value);
        }
    }
}

getter的触发时机:

1、初次访问age

2、依赖的值age发生改变

如果计算属性只用来访问可以简写

computed:{
    age(){
            return age + 1;
        }
}

侦听属性

侦听vue实例上数据的变化情况,被侦听的数据发生变化时触发侦听方法

immediate配置项为true会在注册侦听属性时执行一次侦听函数

watch默认不会侦听对象内部的数据变化,只会侦听一层,使用deep可以侦听对象内部属性变化

watch:{
    age:{
        immediate: true,//age初始化侦听时会先执行一次侦听函数
        deep:true,
        handler(new,old) {
            console.log(new);//变化后的值
            console.log(old);//变化前的值
        }
    }
}

如果没有配置项可以简写

watch:{
    age(new,old) {
        console.log(new);//变化后的值
        console.log(old);//变化前的值
    }
}

绑定样式

vue中尽量避免直接操作dom,如果要修改样式,通过v-bind绑定动态属性实现

动态class

  • 字符串方式
<div id="app">
    <div :class="class"></div>
</div>
<script>
    new Vue({
        el: '#app',
        data: {
            class: 'flex'
        }
    })
</script>
  • 数组方式
<div id="app">
    <div :class="class"></div>
</div>
<script>
    new Vue({
        el: '#app',
        data: {
            class: ['flex1','flex2','flex3']
        }
    })
</script>
  • 对象方式
<div id="app">
    <div :class="class"></div>
</div>
<script>
    new Vue({
        el: '#app',
        data: {
            class:{
                flex1:true,
                flex2:true
            }
        }
    })
</script>

动态style

<div id="app">
    <div :style="style"></div>
</div>
<script>
    new Vue({
        el: '#app',
        data: {
            style:{
                color:'red',
                fontSize:'16px',
                backgroundColor:'#000',
                width:'100px',
                height:'100px'
            }
        }
    })
</script>

条件渲染

v-if

1、不渲染时节点不存在于dom

2、适合切换频率较低的场景

v-show

1、不渲染的元素只是用样式隐藏

2、适合切换频率较高的场景

列表渲染

key的原理:vue中发生数据更新时,会创建新的虚拟dom,vue会对比新旧虚拟dom来更新真实dom,而对比虚拟dom时,vue会将相同key的节点进行对比,其中有不同的元素则重新创建生成真实元素,相同的元素则不重新创建而是直接复用,

用index作为key:如果对数据的顺序进行了破坏,那么遍历时的索引就会改变,相应的key就会和之前的key对应不上,这样在vue进行对比时会进行不必要的dom生成消耗性能,如果渲染项存在表单输入,那么页面还会错乱

vue监测对象数据的原理

模拟一个简单的vue监测对象数据,它只能监测一层数据

let data = {
    name: '张三',
    age: 18
}
// 定义一个观察者构造函数,通过构造出的实例来监测数据
function Observe(obj) {
    // 首先获取对象的所有key
    let keys = Object.keys(obj)
    // 遍历keys
    keys.forEach(key =>{
        // 向观察者实例添加getter,setter做数据劫持
        Object.defineProperty(this,key,{
            get() {
                return obj[key]
            },
            set(val) {
                obj[key] = val
                console.log(`${key}改变了,我要去更新模板了`);
            }
        })
    })
}
// 创建一个观察者实例,通过观察者实例可以监测data数据
let obs = new Observe(data)
//创建一个vm实例
let vm = {}
vm._data = obs

image.png

vue监测数组

没有对数组中的属性进行数据劫持,通过数组下标修改数组数据时,vue不能监听,不是响应式的

通过数组方法操作数组时,vue可以监听到,是响应式的