Vue2(一)初始vue、模板语法、数据绑定、数据代理、事件处理、计算和监视属性

目录

一、第一次使用Vue

1.script引入式

el两种写法

data两种写法

二、模板语法

三、数据绑定

四、MVVM模型

五、数据代理

(1)回顾Object.defineProperty(双向数据传输原理)

(2)数据代理

(3)Vue中的数据代理

六、事件处理*

(1)事件绑定 

(2)函数传参 

(3)事件修饰符

(4)键盘事件

七、computed和watch*

1.计算属性computed

 2.监视属性watch

(1)监视属性

(2)深度监视

3.计算属性和监听属性的比较


一、第一次使用Vue

1.script引入式

输出hello 狗蛋

    <script src="../js/vue.js"></script>
</head>

<body>
    <div id="root">
        <!-- {{}}引用vue实例里的元素 -->
        <h1>hello {{name}}!</h1>
    </div>
    <script>
        // 关闭启动时的生产提示 在官网api全局配置可查
        Vue.config.productionTip = false

        // 创建启动vue实例
        const vm = new Vue({
            el: '#root', //元素名 与div语句连接
            data: {
                name: '狗蛋'
            }
        })
    </script>
</body>

el两种写法

(1)写在vue实例内:el: '#root'

(2)写在vue实例外:vue实例.$mount('#root')

        $mount() 挂载

data两种写法

(1)对象式(不建议)

        data: {
                name: '狗蛋'
        }

(2)函数式       

data(){
    return {
        name:'狗蛋'
    {
}

 data()函数必须有返回值,该函数的this指向Vue实例对象

注意:不建议使用箭头函数,这样this会指向window,导致后续操作报错!

二、模板语法

1.插值语法{{}}

用于解析标签体内容

2.指令语法

用于解析标签(包括标签属性、标签体内容、事件绑定等)

格式:v-XXXX 如:v-bind,v-if等

<!-- html部分 -->
<a v-bind:href="website.url">点我去网站</a>
<!-- 缩写v-bind:变为: -->
<a :href="website.url">点我还去这个网站</a>

<!-- script部分 -->
// 创建启动vue实例
const vm = new Vue({
    el: '#root', //元素名 与div语句连接
    data: {
        name: '狗蛋',
        website: {
            name: '狗蛋网站',
            url: 'https://www.bilibili.com/'
            }
        }
    })

注意:v-bind:可缩写为 “:”

          href="url"中,url必须是js表达式

三、数据绑定

(1)单向数据绑定:v-bind

        vue实例中的数据->表单的值

(2)双向数据绑定:v-model(只能用于表单元素)

        vue实例中的数据->表单的值

        表单的值修改->vue实例中的数据也被修改

        缩写方法:v-model:value="name"简写为 v-model="name"

<div id="root">
    单向数据绑定:<input type="text" v-bind:value="name"> <br>
    双向数据绑定:<input type="text" v-model:value="name">
</div>
<script>
    new Vue({
        el: '#root',
        data: {
        name: '狗蛋'
        }
    })
</script>

单项数据修改value值,实例中的值不会改变

 双向数据修改value值,实例中的值也会跟着改变

四、MVVM模型

 

 

五、数据代理

(1)回顾Object.defineProperty(双向数据传输原理)

    <script>
        let num = 18
        const person = {
            name: 'csq'
        }
        // 向对象person添加一个属性
        Object.defineProperty(person, 'age', {
            // value: 18,
            // enumerable: true,  //可枚举、可遍历
            // writable: true,  //可修改
            // configurable: true, //可删除

            // 访问age属性数据时,getter会被调用,触发返回年龄数据
            get() {
                console.log('age属性被访问!')
                return num
            },
            // 修改age属性数据时,setter会被调用,触发修改年龄数据
            //同时,修改age后会触发get(),使得属性和数值连接起来,修改属性后,后台数值也被修改
            set(value) {
                console.log('age属性被修改!')
                num = value
            }
        })
    </script>

访问age属性

 修改age属性

 从后台修改num可以改变age属性的值,从控制台修改age属性的值可以改变num的值,实现了双向数据传输的基本原理

(2)数据代理

         基本结构:

//最简 数据代理结构
let obj1 = {
    x: 100
}
let obj2 = {
    y: 10
}
Object.defineProperty(obj2, 'x', {
    get() {
        return obj1.x
    },
    set(value) {
        obj1.x = value
    }
})

(3)Vue中的数据代理

        通过vm对象来代理data对象中属性的操作,更加方便对data的操作

基本原理:通过Object.defineObject()把data对象中的所有属性添加到vm中,为每一个添加到vm中的属性指定一个getter和setter,在getter和setter中去操作(读、写)data中对应的属性

<div class="root">
    <h1>姓名:{{name}}</h1>
    <h1>年龄:{{age}}</h1>
</div>
<script>
    //Vue 数据代理 最简结构
    const vm = new Vue({
        el: '.root',
        data() {
            return {
                name: 'csq',
                age: 18
            }
        }
    })
</script>

 读取vm.name触发getter,修改vm.name触发setter,符合数据代理

 注意:Vue实例vm的数据data存储在vm._data对象中,vm._data.name=vm.name 

六、事件处理*

v-on:事件类型="函数"  缩写为@事件类型="函数" (该函数只能写在vm实例中才能被访问到)

函数方法写在methods对象中,不能写在data对象中

原因:函数在最开始内容就被指定,后期不必更改,放在data对象中会被数据代理,添加函数方法的getter/setter功能(实际不会用到)

(1)事件绑定 

    <div class="root">
        <h2>我是谁?</h2>
        <button v-on:click="showInfo">点我提示信息</button>
    </div>
    <script>
        const vm = new Vue({
            el: '.root',
            data: {
                name: 'csq'
            },
            methods: {
                showInfo() {
                    alert("my name is csq")
                }
            }
        })
    </script>

        点击按钮事件,alert信息 

(2)函数传参 

        v-on:事件类型="函数",引号中的语句会被解析为js语句,故需要传参的时候在函数名后写上          括号和实参即可

        关键字$event,用于给event对象占位

<button @click="showInfo2($event,77)">点我提示信息2</button>
methods: {
    showInfo(event) {
        alert("my name is csq")
    },
    showInfo2(event, num) {
        console.log(event)
        console.log(num)
    }
}

(3)事件修饰符

  1. prevent 阻止默认事件
  2. stop 阻止事件冒泡
  3. once 事件只能触发一次
  4. capture 使用事件的捕获机制
  5. self 只有event.target是当前操作的元素才会触发事件
  6. passive 事件的默认行为立即执行,无需等待回调事件结束
    <div class="root">
        <!-- prevent 阻止默认事件 -->
        <a @click.prevent="showInfor" href="https://www.bilibili.com">点我</a> <br>

        <div @click="showInfor1" class="son">
            <!-- stop 阻止事件冒泡 -->
            <button @click.stop="showInfor">点我</button>
        </div>

        <!-- once 事件只能触发一次 -->
        <button @click.once="showInfor">点我只能点一次</button>

        <!-- capture 使用事件的捕获机制 -->
        <div @click.capture="showInfor1" class="son">
            <button @click.stop="showInfor">点我</button>
        </div>
        <!-- self 只有event.target是当前操作的元素才会触发事件 -->
        <div @click.self="showInfor1" class="son">
            <button @click.stop="showInfor">点我</button>
        </div>
        <!-- passive 事件的默认行为立即执行,无需等待回调事件结束 -->
        <!-- 不添加passive时,ul先执行鼠标滚动的回调事件循环输出i,再完成默认行为:滚动 -->
        <ul v-on:wheel.passive="move">
            <li>1</li>
            <li>2</li>
            <li>3</li>
            <li>4</li>
            <li>5</li>
            <li>6</li>
        </ul>
    </div>

    <script>
        const vm = new Vue({
            el: '.root',
            methods: {
                showInfor() {
                    alert("点我")
                },
                showInfor1() {
                    alert("点我爸爸")
                },
                move() {
                    for (let i = 0; i < 10000; i++)
                        console.log(i)
                }
            }
        })
    </script>

(4)键盘事件

        按回车响应事件(不使用关键字)

<div class="root">
    <input @keyup="showInfor" type="text">
</div>
<script>
    const vm = new Vue({
        el: '.root',
        methods: {
            showInfor(e) {
            if (e.keyCode == 13)
                console.log('你按了回车')
            }
        }
    })
</script>

         按回车响应事件(使用关键字enter)

<!-- 使用关键字 -->
<div class="root">
    <input @keyup.enter="showInfor" type="text">
</div>
<script>
    const vm = new Vue({
        el: '.root',
        methods: {
            showInfor(e) {
                console.log('你按了回车')
            }
        }
    })
</script>

键盘关键字,按下对应按键响应事件   

七、computed和watch*

1.计算属性computed

 根据一个简单的案例来看看计算属性的高级之处:分别输入姓和名来拼接出全名并显示在屏幕中

(1)直接在标签中用插值语句拼接

<!-- 1.插值方法 -->
<div class="root">
    <span>姓:</span><input v-model="xing" type="text"> <br>
    <span>名:</span><input v-model="ming" type="text"> <br>
    <p>全名:{{xing}}-{{ming}}</p>
</div>
<script>
    const vm = new Vue({
        el: '.root',
        data: {
            xing: '',
            ming: ''
        }
    })
</script>

弊端:直接在标签中插值连接,不便于后期有更多需求时的修改,在标签中添加更多不利于可读性

(2) 在methods中写一个方法

    <!-- 2.methods方法 -->
    <div class="root">
        <span>姓:</span><input v-model="xing" type="text"> <br>
        <span>名:</span><input v-model="ming" type="text"> <br>
        <p>全名:{{fullname()}}</p>
    </div>
    <script>
        const vm = new Vue({
            el: '.root',
            data: {
                xing: '',
                ming: ''
            },
            methods: {
                fullname() {
                    return this.xing + '-' + this.ming
                }
            }
        })
    </script>

弊端:每次修改姓或名后,fullname()方法会被重新调用,且若多次调用函数,会大大增加系统的压力,不利于Vue轻便减负的特点

(3)计算属性方法*

添加计算属性fullname,通过get读取调用,计算属性具有缓存特点,即,在该属性值不变动时,将该属性存在缓存中,以后每次用到该属性直接拿出来用即可,不需要再向Vue实例调用属性,大大减负。显而易见,将需要计算的值保存在计算属性中更加高效

    <!-- 计算属性 -->
    <div class="root">
        <span>姓:</span><input v-model="xing" type="text"> <br>
        <span>名:</span><input v-model="ming" type="text"> <br>
        <p>全名:{{fullname}}</p>
    </div>
    <script>
        const vm = new Vue({
            el: '.root',
            data: {
                xing: '',
                ming: ''
            },
            computed: {
                fullname: {
                    // get在什么时候调用?(缓存机制,减少调用)
                    //1.初次访问fullname属性时; 2.fullname内数据更新时
                    get() {
                        return this.xing + '-' + this.ming
                    },
                    // set在fullname被修改时调用
                    //确定该计算属性只用于显示计算结果就不必写set函数
                    set(value) {
                        const arr = value.split('-')
                        this.xing = arr[0]
                        this.ming = arr[1]
                    }
                }
            }
        })
    </script>

大部分情况下,计算属性不需要修改值,即不需要set()函数,故将计算属性简写:

computed: {
    // 简写:只使用get()
    fullname() {
        return this.xing + '-' + this.ming
    }
}

 2.监视属性watch

用于监视属性是否被修改

根据案例修改天气来看看具体效果

(1)监视属性

在watch属性中写入需要监视的属性a,handler函数用于在修改时自动调用,可包含两个参数,新值和旧值

 

监视属性中还有别的函数和属性可以添加,例如immediate:true,在网页打开时就进行一次监视,旧值为undefined 

    <div class="root">
        <p>今天天气很{{show}}</p>
        <button @click="changeWeather">点我切换天气</button>
    </div>
    <script>
        const vm = new Vue({
            el: '.root',
            data: {
                a: true
            },
            computed: {
                show() {
                    return this.a ? '炎热' : '凉爽'
                }
            },
            methods: {
                changeWeather() {
                    this.a = !this.a
                }
            },
            watch: {
                a: {
                    // handler函数在a被修改时调用
                    handler(newValue, oldValue) {
                        console.log('a被修改了');
                        console.log('新值:', newValue, '旧值:', oldValue)
                    }
                }
            }
        })
    </script>

另一种写法:写在Vue实例外

vm.$watch('a',{
    immediate: true,
    handler(newValue, oldValue) {
    console.log('a被修改了');
    console.log('新值:', newValue, '旧值:', oldValue)
    }
})

(2)深度监视

 不使用深度监视只能这样监视深层的属性a.b

    <div class="root">
        <p>b={{a.b}}</p>
        <button @click="changeB">点我b+1</button>
    </div>
    <script>
        const vm = new Vue({
            el: '.root',
            data: {
                a: {
                    b: 0,
                    c: 0
                }
            },
            computed: {
            },
            methods: {
                changeB() {
                    this.a.b = this.a.b + 1
                }
            },
            watch: {
                'a.b': {
                    // handler函数在a被修改时调用
                    handler(newValue, oldValue) {
                        console.log('b被修改了');
                        console.log('新值:', newValue, '旧值:', oldValue)
                    }
                }
            }
        })
    </script>

使用深度监视deep:true

// 深度监视 可以监视属性a内的多层属性
a: {
    deep: true,
    handler(newValue, oldValue) {
        console.log('b被修改了');
        console.log('新值:', newValue, '旧值:', oldValue)
    }
}

监视a属性,也可以监视到a属性内的多层属性;若不添加深层监视,则只能监视到属性a本身的改变,看不到内层属性的改变

(3)监视属性的简写(前提是监视属性只需要handler()函数)

 写在实例内的简写:

watch: {
    a(newValue, oldValue) {
    console.log('a被修改了');
    console.log('新值:', newValue, '旧值:', oldValue)
    }
}

写在实例外的简写:

vm.$watch('a', function (newValue, oldValue) {
    console.log('a被修改了');
    console.log('新值:', newValue, '旧值:', oldValue)
})

注意:需要指向vm实例的函数不要使用箭头函数,否则this指针会指向外层,如window

3.计算属性和监听属性的比较

上文中的全名案例:用watch来写

 可见,上面代码是命令式且重复的,不如computed计算属性来写更加简单明了

监视属性watch可以进行异步操作,用computed是无法替代的,如下,计时器1s后再写入全名,再computed属性中不可实现

const vm = new Vue({
    el: '.root',
    data: {
        xing: '',
        ming: '',
        fullname: ''
    },
    watch: {
        xing(newValue) {
            // 1s后再返回全名
            setTimeout(() => {
                this.fullname = newValue + '-' + this.ming
            }, 1000)
        },
        ming(newValue) {
            setTimeout(() => {
                this.fullname = this.xing + '-' + newValue
            }, 1000)
        }
    }
})

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值