vue学习笔记

vue核心

vue安装

  1. npm安装vue-cli,即vue脚手架
  2. 通过CDN使用vue
  3. 直接下载并用 <script> 标签引入,Vue 会被注册为一个全局变量。

初识vue

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>初识vue</title>
    <!-- 引入vue -->
    <script type="text/javascript" src="../JS/vue.js"></script>
</head>

<body>
    <!-- 
        初识vue:
        1. 想让vue工作,就必须创建一个vue实例,且要传入一个配置对象;
        2. root容器里的代码依然符合html规范,只不过混入了一些特殊的vue语法;
        3. root容器里的代码被称为vue模板
		4. vue实例和容器是一一对应的;
		5. 真实开发中只有一个vue实例,并且会配合着组件一起使用;
		6. {{xxx}}中的xxx要写js表达式,且xxx可以自动读取到data中的所有属性;
		7. 一旦data中的数据发生改变,那么模板中用到该数据的地方也会自动更新;
		
		注意区分:js表达式和js代码
		表达式:一个表达式会生成一个值,可以放在任何一个需要值的地方。
			a
			a+b
			demo(1)
		js代码:
			if(){}
			for(){}
		js表达式是特殊的js代码或语句,会产生一个值!
     -->
    <!-- 准备好一个容器 -->
    <div id="root">
        <h1>hello {{name}}.</h1>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false
        //创建Vue实例,只传一个配置对象
        new Vue({
            el: document.getElementById('root'), //el用于指定当前vue实例为哪个容器服务,值通常为css选择器
            data: { //data中用于存储数据,数据供el所指定的容器使用
                name: "dad111"
            }
        })
    </script>
</body>

</html>

容器和vue实例之间是一对一的。

模板语法

插值语法往往用于指定标签体内容,起始标签和结束标签中间的内容就是标签体。

vue模板语法有两大类:

  • 插值语法:

    功能:用于解析标签体内容

    写法:,xxx是js表达式,且可以直接读取到data中的所有属性。

  • 指令语法:

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

    举例:v-bind:href="xxx"或简写为:href="xxx",xxx同样要写js表达式,且可以直接读取到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>
    <!-- 
        初识vue:
        1. 想让vue工作,就必须创建一个vue实例,且要传入一个配置对象;
        2. root容器里的代码依然符合html规范,只不过混入了一些特殊的vue语法;
        3. root容器里的代码被称为vue模板
     -->
    <!-- 准备好一个容器 -->
    <div id="root">
        <h1>插值语法</h1>
        <h3>hello, {{name}}</h3>
        <hr/>
        <h1>指令语法</h1>
        <a v-bind:href="url">go to xxx</a>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false
        //创建Vue实例,只传一个配置对象
        new Vue({
            el: document.getElementById('root'), //el用于指定当前vue实例为哪个容器服务,值通常为css选择器
            data: { //data中用于存储数据,数据供el所指定的容器使用
                name: "dad111",
                url:"www.xxx.com"
            }
        })
    </script>
</body>

</html>

数据绑定

vue中有两种绑定的方式:

  • 单向绑定:

    数据只能从data流向页面

  • 双向绑定:

    数据不只能从data流向页面,还可以从页面流向data。

备注:

v-bind最大的特点是单向的数据绑定。

v-model是双向绑定,但是v-model只能应用于表单类元素(输入类元素)上,如input、select等,应用于value属性。

<!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">
        双向数据绑定:<input type="text" v-model:value="name">
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false
        //创建Vue实例,只传一个配置对象
        new Vue({
            el: document.getElementById('root'), //el用于指定当前vue实例为哪个容器服务,值通常为css选择器
            data: { //data中用于存储数据,数据供el所指定的容器使用
                name: "dad111",
                url: "www.xxx.com"
            }
        })
    </script>
</body>

</html>

el与data的两种写法

el的两种写法

  • 用el指定容器
  • 用创建出的vue对象的$mount()指定容器,这种方式更灵活点
<!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">
        双向数据绑定:<input type="text" v-model:value="name">
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false;
        //创建Vue实例,只传一个配置对象
        const v = new Vue({
            data: { //data中用于存储数据,数据供el所指定的容器使用
                name: "dad111",
                url: "www.xxx.com"
            }
        });
        console.log(v);
        v.$mount('#root')
    </script>
</body>

</html>

data的两种写法:

  • 对象式

  • 函数式

    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-bind:value="name">
        双向数据绑定:<input type="text" v-model:value="name">
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false;
        //创建Vue实例,只传一个配置对象
        const v = new Vue({
            // data的第一种写法:对象式
            // data: { //data中用于存储数据,数据供el所指定的容器使用
            //     name: "dad111",
            //     url: "www.xxx.com"
            // }

            // data的第二种写法:函数式
            data: function () {
                console.log('@@@', this)//此处的this是vue实例对象
                return {
                    name: 'asd'
                }
            }
        });
        console.log(v);
        v.$mount('#root')
    </script>
</body>

</html>

由vue管理的函数,一定不要写箭头函数,一旦写了箭头函数,this就不再是vue实例了。

MVVM模型

  1. M:模型(Model),对应data中的数据
  2. V:视图(View),模板
  3. VM:视图模型,vue实例对象

image-20230607200511206

mvvm模型就是把数据和页面做了连接,页面的更改可以导致数据的更改,这就是监听DOM;数据的更改也可以导致页面的更改,这就是页面绑定数据。

因此经常用vm这个变量名代表VUE实例。

模板里可以写JS表达式,也可以写data中的属性。

模板能看见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">
        <h1>学校名称:{{name}}</h1>
        <h1>学校地址:{{address}}</h1>
        <h1>学校地址:{{$options}}</h1>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false;
        //创建Vue实例,只传一个配置对象
        const vm = new Vue({
            // data的第一种写法:对象式
            el: '#root',
            data: { //data中用于存储数据,数据供el所指定的容器使用
                name: "dad111",
                address: "www.xxx.com"
            }

            // data的第二种写法:函数式
            // data: function () {
            //     console.log('@@@', this)//此处的this是vue实例对象
            //     return {
            //         name: 'asd',
            //         address: 'beijing'
            //     }
            // }
        });
        console.log(vm);
    </script>
</body>

</html>

不仅是VM对象上的所有属性,模板能看见,能使用,而且能看见原型proto里的属性。

结论:

  • data中的所有属性,最后都出现在了VM对象。

  • VM的所有属性及Vue原型上的所有属性,在Vue模板中可以直接使用。

数据代理

Object.defineproperty方法

这是给对象定义属性的方法,这种方法给对象定义的属性,默认不可枚举。

<body>
    <!-- 准备好一个容器,这就是模板 -->
    <script type="text/javascript">
        let person = {
            name: 'zhangsan',
            sex: 'male'
        };
        // 以这种方式添加属性,此属性不可枚举
        Object.defineProperty(person, 'age', {
            value: 18
        })
        console.log(Object.keys(person))
        for (let key in person) {
            console.log(person[key])
        }
        console.log(person)
    </script>
</body>

以下这种方式设置属性,定义属性:

        Object.defineProperty(person, 'age', {
            value: 18,
            enumerable: true, // 控制属性是否可以枚举,默认值false
            writable: true, // 控制属性是否可以被修改,默认值false
            configurable: true, //控制属性是否可以被删除,默认值false
        })

getter/setter

    <script type="text/javascript">
        let number = 18;
        let person = {
            name: 'zhangsan',
            sex: 'male'
        };

        Object.defineProperty(person, 'age', {
            // 当读取person的age属性时,get函数就会被调用,且返回值就是age属性值
            get: function () {
                return number;
            },
            //当修改person的age属性时,setter会被调用,且会收到修改的具体值
            set: function (value) {
                number = value
            }
        })
        console.log(Object.keys(person))
        for (let key in person) {
            console.log(person[key])
        }
        console.log(person)
    </script>

数据代理的定义:

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

vm对象里的_data就时我们在代码里传递进去的data,即options.data

vue中的数据代理

image-20230608111033405

  • 通过vm对象来代理data对象中属性的操作(读、写)
  • 基本原理:
    • 通过Object.defineProperty()把data对象中所有属性添加到vm上;
    • 为每一个添加到vm上的属性都指定一个getter和setter
    • 在getter和setter内部去操作data中对应的属性

vue的数据代理是指vm对象和data对象两个对象之间的数据代理。

事件处理

一个最简单的事件绑定

<body>
    <div id="root">
        <h2>欢迎来到{{name}}学习</h2>
        <button v-on:click="showInfo">点我提示信息</button>
        <button @click="showInfo">点我提示信息</button>
    </div>
</body>
<script type="text/javascript">
    Vue.config.productionTip = false;
    new Vue({
        el: '#root',
        data: {
            name: 'dasdsa',
        },
        methods: {
            showInfo() {
                alert("ddsasadadsa");
            }
        },
    })
</script>

如果调用函数想传参,那么就加上小括号:

<body>
    <div id="root">
        <h2>欢迎来到{{name}}学习</h2>
        <button v-on:click="showInfo(66)">点我提示信息</button>
    </div>
</body>
<script type="text/javascript">
    Vue.config.productionTip = false;
    new Vue({
        el: '#root',
        data: {
            name: 'dasdsa',
        },
        methods: {
            showInfo(number) {
                alert(number);
            }
        },
    })
</script>

事件的基本使用:

  • 使用v-on:xxx或@xxx绑定事件,其中xxx是事件名;
  • 事件的回调需要配置在methods对象中,最终会在vm上;
  • methods中配置的函数,不要用箭头函数,否则this就不是vm对象了;
  • methods中配置的函数,都是被Vue管理的函数,this的指向是vm或组件实例对象;
  • @click="demo"和@click="demo($event)"效果一致,但后者可以传参。

vue中的事件修饰符

  • prevent:阻止默认事件;
  • stop:阻止事件冒泡;
  • once:事件只触发一次;
  • capture:使用事件的捕获模式;
  • self:只有event.target是当前操作的元素才触发事件;
  • passive:事件的默认行为立即执行,无需等待事件回调执行完毕;

键盘事件

@keyup

@keydown

  1. vue中常用的按键别名:

    • 回车:enter

    • 删除:delete(捕获删除和退格键)

    • 退出:esc

    • 空格:space

    • 换行:tab(特殊:必须配合keydown使用,因为tab本身有转换焦点的作用)

    • 上:up

    • 下:down

    • 左:left

    • 右:right

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

  3. 系统修饰键

    ctrl、alt、shift、meta

    配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发。

    配合keydown使用,正常触发事件

  4. 使用keyCode去指定具体的按键

  5. 自定义键名

计算属性

  1. 定义:

    要用的属性不存在,要通过已有属性计算得来

  2. 原理:

    底层借助了Object.defineproperty()方法提供的getter和setter。

  3. get函数什么时候执行:

    初次读取时会执行一次;

    当依赖的数据发生改变时会被再次调用;

  4. 优势:

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

  5. 备注:

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

    如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变,才能改变计算属性。

<body>
    <!-- 准备好一个容器 -->
    <div id="root">
        xing: <input type="text" v-model:value="firstName"> <br /><br />
        ming: <input type="text" v-model:value="lastName"> <br /><br />
        quanming: <span>{{fullName}}</span>
    </div>
</body>
<script type="text/javascript">
    Vue.config.productionTip = false;
    //创建Vue实例,只传一个配置对象
    const vm = new Vue({
        el: '#root',
        // data的第一种写法:对象式
        data: { //data中用于存储数据,数据供el所指定的容器使用
            firstName: "zhang",
            lastName: "san"
        },
        computed: {
            fullName: {
                // get 什么时候调用?
                // 1.初次读取fullName时;2.所依赖的数据发生变化时
                get: function () {
                    return this.firstName + '-' + this.lastName
                },
                // set什么时候被调用,当fullName被修改时。
                set(value) {
                    const arr = value.split('-')
                    this.firstName = arr[0];
                    this.lastName = arr[1];
                }
            }
        }
    });
</script>

监视属性

  1. 当被监视的属性变化时,回调函数自动调用,进行相关操作;
  2. 监视的属性必须存在,才能进行监视;
  3. 监视的两种写法:
    • new Vue时传入watch配置
    • 通过vm.$watch()监视
<body>
    <!-- 准备好一个容器 -->
    <div id="root">
        <h2>{{info}}</h2>
        <button @click="changeWeather">switch</button>
    </div>
</body>
<script type="text/javascript">
    Vue.config.productionTip = false;
    //创建Vue实例,只传一个配置对象
    const vm = new Vue({
        el: '#root',
        // data的第一种写法:对象式
        data: { //data中用于存储数据,数据供el所指定的容器使用
            isHot: true,
        },
        computed: {
            info: {
                get() {
                    return this.isHot ? 'hot' : 'cold';
                }
            }
        },
        methods: {
            changeWeather() {
                this.isHot = !this.isHot;
            }
        },
        // watch: {
        //     // 除了监视data里的属性,也可以监视计算属性
        //     isHot: {
        //         // immediate默认为false, 如果为true,则初始化时,让handler调用一下。
        //         immediate: false,
        //         // handler函数什么时候调用?当isHot被改变时
        //         // 不仅会发现isHot被修改了,还会得到isHot修改前和修改之后的值
        //         handler(newValue, oldValue) {

        //         }
        //     }
        // }

    });
    vm.$watch('isHot', {
        // immediate默认为false, 如果为true,则初始化时,让handler调用一下。
        immediate: false,
        // handler函数什么时候调用?当isHot被改变时
        // 不仅会发现isHot被修改了,还会得到isHot修改前和修改之后的值
        handler(newValue, oldValue) {
        }
    })
</script>

computed和watch之间的区别:

  1. computed能完成的功能,watch都可以完成
  2. watch能完成的功能,computed不一定能完成,例如watch可以进行异步操作

两个重要的原则:

  1. 所有被vue管理的函数,最好写成普通函数,这样this的指向才是vm或组件实例对象;
  2. 所有不被vue所管理的函数,最好写成箭头函数,这样this的指向才是vm或组件实例对象;

class与style绑定

绑定样式:

  1. class样式:

    写法::class="xxx",xxx可以是字符串、对象、数组

    字符串写法适用于:类名不确定,要动态获取

    对象写法适用于:要绑定多个样式,适用于要绑定的样式个数和名字都确定,但是要动态决定用不用

    数组写法适用于:适用于要绑定的样式个数和名字都不确定

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>绑定样式</title>
    <style>
        .basic {}

        .happy {}

        .sad {}

        .normal {}

        .test1 {}

        .test2 {}

        .test3 {}
    </style>
    <!-- 引入vue -->
    <script type="text/javascript" src="../JS/vue.js"></script>
</head>

<body>
    <!-- 准备好一个容器 -->
    <div id="root">
        <!-- 绑定class样式,字符串写法,适用于样式的类名不确定,需要动态指定 -->
        <div class="basic" :class="mood" @click="changeMood">{{name}}</div>
        <!-- 绑定class样式,数组写法,适用于要绑定的样式个数和名字都不确定 -->
        <div class="basic" :class="classArr"></div>
        <!-- 绑定class样式,对象写法,适用于要绑定的样式个数和名字都确定,但是要动态决定用不用 -->
        <div class="basic" :class="classObj"></div>
    </div>
</body>
<script type="text/javascript">
    Vue.config.productionTip = false;
    new Vue({
        el: '#root',
        data: {
            name: "dsadsa",
            mood: "normal",
            classArr: ['test1', 'test2', 'test3'],
            classObj: {
                test1: false,
                test2: false
            }
        },
        methods: {
            changeMood() {
                const arr = ['happy', 'sad', 'normal'];
                index = Math.floor(Math.random() * 3);
                this.mood = arr[index];
            }
        },
    })
</script>

</html>

条件渲染

v-if写法:

v-if="表达式"

v-else-if="表达式"

v-else="表达式"

适用于切换频率较低的场景

特点:不展示的DOM元素直接被移除

注意:v-if可以和v-else-if和v-else一起使用,但要求结构不能被打断;

v-show

写法:v-show="表达式"

适用于:切换频率较高的场景

特点:不展示的DOM不会被移除,仅仅是使用样式隐藏掉

列表渲染

key的内部原理:

  1. 虚拟DOM中key的作用:

    key是虚拟DOM对象的标识,当状态中的数据发生变化时,Vue会根据新数据生成新的虚拟DOM,随后vue进行新虚拟与旧虚拟DOM的差异比较。

  2. 比较规则:

    旧虚拟DOM中找到了与新虚拟DOM相同的key:

    • 若虚拟DOM中内容没变,直接使用之前的真实DOM

    • 若虚拟DOM中内容变了,则生成新的真实DOM,随后替换掉页面之前的真实DOM。

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

    创建新的真实DOM,随后渲染到页面。

  3. 开发中如何选择key?

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

    如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。

  4. 列表过滤

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <title>初识vue</title>
        <!-- 引入vue -->
        <script type="text/javascript" src="../JS/vue.js"></script>
    </head>
    
    <body>
        <!-- 准备好一个容器 -->
        <div id="root">
            <ul>
                <input type="text" placeholder="请输入名字" v-model="keyWord">
                <li v-for="(p, index) of filPersons" :key="index">
                    {{p.name}}-{{p.age}}--{{p.sex}}
                </li>
            </ul>
        </div>
    </body>
    
    <script type="text/javascript">
        Vue.config.productionTip = false
        //创建Vue实例,只传一个配置对象
        // 用watch实现
        /*
        new Vue({
            el: '#root', //el用于指定当前vue实例为哪个容器服务,值通常为css选择器
            data: { //data中用于存储数据,数据供el所指定的容器使用
                keyWord: '',
                persons: [
                    { id: 001, name: '马冬梅', age: 19, sex: 'female' },
                    { id: 002, name: '周冬雨', age: 20, sex: 'female' },
                    { id: 003, name: '周杰伦', age: 21, sex: 'male' },
                    { id: 004, name: '温兆伦', age: 22, sex: 'male' },
                ],
                filPersons: []
            },
            watch: {
                keyWord: {
                    // this.persons = this.persons.filter((p) => {
                    //     return p.name.indexOf(val) !== -1
                    // }) //这样写是错的,原数据不能修改
                    // this.filPersons = this.persons.filter((p) => {
                    //     return p.name.indexOf(val) !== -1
                    // })
                    immediate: true,
                    handler(val) {
                        this.filPersons = this.persons.filter((p) => {
                            return p.name.indexOf(val) !== -1
                        })
                    }
                }
            }
        })
        */
        // 用computed实现
        new Vue({
            el: '#root', //el用于指定当前vue实例为哪个容器服务,值通常为css选择器
            data: { //data中用于存储数据,数据供el所指定的容器使用
                keyWord: '',
                persons: [
                    { id: 001, name: '马冬梅', age: 19, sex: 'female' },
                    { id: 002, name: '周冬雨', age: 20, sex: 'female' },
                    { id: 003, name: '周杰伦', age: 21, sex: 'male' },
                    { id: 004, name: '温兆伦', age: 22, sex: 'male' },
                ]
            },
            computed: {
                filPersons() {
                    return this.persons.filter((p) => {
                        return p.name.indexOf(this.keyWord) !== -1
                    })
                }
            }
        })
    </script>
    
    </html>
    

数据监测

模拟vue的数据监测

<script type="text/javascript">
    Vue.config.productionTip = false
    let data = {
        name: '11',
        address: '22'
    }
    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) {
                    obj[k] = val
                }
            })
        })
    }
</script>

关于列表的各项联系:

<!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>学生信息</h1>
        <button @click="student.age++">年龄+1岁</button> <br />
        <button @click="addSex">添加性别属性,默认值:男</button> <br />
        <button @click="addFriends">在列表首位添加一个朋友</button> <br />
        <button @click="updateFirstFriendName">修改第一个朋友的名字为张三</button> <br />
        <button @click="addHobby">添加一个爱好</button> <br />
        <button @click="updateFirstHobby">修改第一个爱好为开车</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>
        <h3>朋友:</h3>
        <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: ['hobby1', 'hobby2', 'hobby3'],
                friends: [
                    { name: 'jerry', age: 25 },
                    { name: 'tony', age: 36 }
                ]
            }
        },
        methods: {
            addSex() {
                // Vue.set(this.student, "sex", "male")
                this.$set(this.student, "sex", "male")
            },
            addFriends() {
                this.student.friends.unshift({ name: 'jack', age: 12 })
            },
            updateFirstFriendName() {
                this.student.friends[0].name = 'zhangsan'
            },
            addHobby() {
                this.student.hobby.push('dsadsa')
            },
            updateFirstHobby() {
                // this.student.hobby.splice(0, 1, 'kaiche')
                // Vue.set(this.student.hobby, 0, 'kaiche')
                this.$set(this.student.hobby, 0, 'kaiche')
            }
        },
    })
</script>

</html>

总结:

vue监视数据的原理:

  1. vue会监视data中所有层次的数据

  2. 如何监测对象中的数据?

    通过setter实现监视,且要在new Vue时就传入要监测的数据。

    对象中后加的属性,Vue默认不做响应式处理。

    如需给后添加的属性做响应式,请使用如下API:

    • Vue.set(target, propertyName/index, value)
    • this.$set(target, propertyName/index, value)
  3. 如何监测数组中的数据

    通过包裹数组更新元素的方法实现,本质就是做了两件事:

    • 调用原生对应的方法对数组进行更新;
    • 重新解析模板,进而更新页面
  4. 在Vue修改数组中的某个元素一定要用如下方法:

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

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

收集表单数据

<!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="demo">
            账号:<input type="text" v-model="userInfo.account"> <br>
            密码:<input type="password" v-model="userInfo.password"> <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" name="hobby" v-model="userInfo.hobby" value="study">
            吃饭<input type="checkbox" name="hobby" v-model="userInfo.hobby" value="eat">
            打游戏<input type="checkbox" name="hobby" v-model="userInfo.hobby" value="game"> <br><br>
            所属校区:
            <select name="" id="" v-model="userInfo.city">
                <option value="">请选择校区</option>
                <option value="beijing">北京</option>
                <option value="shanghai">上海</option>
                <option value="shenzhen">深圳</option>
            </select><br><br>
            其他信息:
            <textarea name="" id="" cols="30" rows="10" v-model="userInfo.other"></textarea><br><br>
            <input type="checkbox" v-model="userInfo.agree">阅读并接收 <a href="https://www.baidu.com">《用户协议》</a>
            <button>提交</button>
        </form>
    </div>
</body>
<script type="text/javascript">
    Vue.config.productionTip = false
    new Vue({
        el: '#root',
        data: {
            userInfo: {
                account: '',
                password: '',
                sex: 'female',
                hobby: [],
                city: 'beijing',
                other: '',
                agree: ''
            }
        },
        methods: {
            demo() {
                console.log(JSON.stringify(this.userInfo))
            }
        },
    })

</script>

</html>

cookie简略图示

image-20230705144854542

cookie不允许跨浏览器

生命周期

<!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>
    </div>
</body>
<script type="text/javascript">
    Vue.config.productionTip = false
    new Vue({
        el: '#root',
        data: {
            opacity: 1
        },
        methods: {
        },
        // vue完成模板的解析并把初识的真实的dom元素放入页面后调用mounted
        mounted() {
            setInterval(() => {
                this.opacity -= 0.01;
                if (this.opacity <= 0) {
                    this.opacity = 1;
                }
            }, 16)
        },
    })

</script>

</html>

生命周期:

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

  2. 生命周期函数是什么?

    Vue在关键时候帮我们调用的一些特殊名称的函数

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

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

生命周期到mounted时,页面中呈现的是经过Vue编译的DOM。

至此初始化过程结束,一般在此进行:开启定时器、发送网络请求、订阅消息、绑定自定义事件等初始化操作。

8个生命周期函数:

  • beforeCreate

    此时无法通过vm访问到data中的数据,methods中的方法

  • created

    可以通过vm访问到data中的数据,methods中的方法

    beforeCreate和Created的创建是指数据监测、数据代理的创建

  • beforeMount

    页面呈现的是未经Vue编译的DOM结构

  • mounted

    页面中呈现的是经过Vue编译的DOM。

    这是常用的生命周期函数,发送ajax请求,启动定时器,绑定自定义事件,订阅消息等初始化操作。

  • beforeUpdate

    数据是新的,但是页面是旧的,即页面尚未和数据保持同步

  • updated

    数据是新的,页面也是新的,页面和数据保持同步。

  • beforeDestroy

    常用的生命周期函数,清除定时器,解绑自定义事件等收尾工作。

  • destroyed

Last Updated:
Contributors: 陈杨