Vue3【创建项目、代码分析、响应式原理-代理、data详解、methods、computed】

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

文章目录


自动创建项目

npm init vue@latest


yarn create vue
yarn
yarn dev


代码分析

  • data是一个函数
  • 在data中this就是当前的组件实例vm
  • 如果使用箭头函数则无法通过this来访问组件实例
  • 使用vue时减少使用箭头函数

  • data会返回一个对象作为返回值vue会对该对象进行代理
  • 从而将其转换为响应式数据响应式数据可以直接通过组件实例访问

  • 直接向组件实例中添加的属性不会被vue所代理不是响应数据修改后页面不会发生变化

  • vm.$data 是实际的代理对象通过vm可以直接访问到$data中的属性
  • vm.$data.msg 等价于 vm.msg


<script>
// const obj = {
//     msg:"哈哈我是obj"
// }

// window.obj = obj

// 组件一个组件可以创建多个组件实例
// 组件就是一个普通的js对象
export default {
    // data是一个函数
    // 在data中this就是当前的组件实例vm
    // 如果使用箭头函数则无法通过this来访问组件实例
    // 使用vue时减少使用箭头函数
    // data: vm => {
    //     console.log("data", vm)

    //     return {
    //         msg: "我爱Vue"
    //     }
    // }

    data() {
        // console.log("data", this)

        // 直接向组件实例中添加的属性不会被vue所代理不是响应数据修改后页面不会发生变化
        // this.name = "孙悟空"

        // vm.$data 是实际的代理对象通过vm可以直接访问到$data中的属性
        // vm.$data.msg 等价于 vm.msg
        


        // data会返回一个对象作为返回值vue会对该对象进行代理
        //  从而将其转换为响应式数据响应式数据可以直接通过组件实例访问
        return {
            msg: "我爱Vue"
        }

        // return obj
    },

    created(){
        // 会在组件创建完毕后调用
        // 可以通过vm.$data动态的向组件中添加响应式数据但是不建议这么做
        this.$data.name = "孙悟空"

    }
}
</script>

<template>
    <h1>{{ msg }}</h1>
    <h2>{{ name }}</h2>
</template>


App.vue是根组件

  • createApp(App) 将根组件关联到应用上
    • 会返回一个应用的实例
  • app.mount(“#app”) 将应用挂载到页面中
    • 会返回一个根组件的实例组件的实例通常可以命名为vm
    • 组件实例是一个Proxy对象(代理对象)

main.js

import { createApp } from 'vue'
import App from './App.vue'

/* 
    App.vue是根组件
        - createApp(App) 将根组件关联到应用上
            - 会返回一个应用的实例
        - app.mount("#app") 将应用挂载到页面中
            - 会返回一个根组件的实例组件的实例通常可以命名为vm
            - 组件实例是一个Proxy对象(代理对象)

*/
const app = createApp(App)

const vm = app.mount("#app")

// 将vm设置为全局变量
window.vm = vm
window.app = app

// createApp(App).mount('#app')

// console.log(vm)

响应式原理-代理

/* 
    如果直接修改对象的属性那么就是仅仅修改了属性没有去做其他的事情
        这种操作只会影响对象自身不会导致元素的重新的渲染
    
    希望在修改一个属性的同时可以进行一些其他的操作比如触发元素重新渲染

    要实现这个目的必须要对对象进行改造vue3中使用的是的代理模式来完成对象的改造

    设置代理时不会对原对象产生影响
*/
// obj.name = "猪八戒"

// 创建一个对象
const obj = {
    name: "孙悟空",
    age: 18
}

// 来为对象创建一个代理
const handler = {
    // get用来指定读取数据时的行为它的返回值就是最终读取到的值
    // 指定get后在通过代理读取对象属性时就会调用get方法来获取值
    get(target, prop, receiver) {

        // 返回值之前做一些其他的操作...
        // 在vue中data()返回的对象会被vue所代理
        // vue代理后当我们通过代理去读取属性时返回值之前它会先做一个跟踪的操作
        //      当我们通过代理去修改属性时修改后会通知之前所有用到该值的位置进行更新

        // track() 追踪谁用了我这个属性
        /* 
            三个参数:
                target 被代理的对象
                prop 读取的属性
                receiver 代理对象
        */
        return target[prop]
    },

    // set会在通过代理修改对象时调用
    set(target, prop, value, receiver){

        target[prop] = value

        // trigger() 触发所有的使用该值的位置进行更新
        // 值修改之后做一些其他的操作
    }
} // handler 用来指定代理的行为

// 创建代理
const proxy = new Proxy(obj, handler)

// 修改代理的属性
proxy.age = 28

console.log(proxy.age)


data详解

  • vue在构建响应式对象时会同时将对象中的属性也做成响应式属性。即深层响应式对象
  • 有些场景下可以通过shallowReactive()来创建一个浅层的响应式对象。只能响应式修改第一层的值
  • 建议将那些暂时没有使用到的属性也添加到data返回的对象中值可以设置为null
  • /数组也是响应式数据
<script>
import MyButton from "./components/MyButton.vue"
import { shallowReactive } from "vue"

export default {
    data() {
        // data返回的对象最终会被Vue所代理
        // this.$data.xxx = "xxx" 动态添加响应数据(不建议这么做)
        // 建议将那些暂时没有使用到的属性也添加到data返回的对象中值可以设置为null
        return {
            msg: "今天天气真不错",
            // vue在构建响应式对象时会同时将对象中的属性也做成响应式属性
            // 深层响应式对象
            stu: {
                name: "孙悟空",
                age: 18,
                gender: "男",
                friend: {
                    name: "猪八戒"
                }
            },
            hello: null
                        // 数组也是响应式数据
            arr: ["孙悟空", "猪八戒", "沙和尚"]
        }

        // 有些场景下可以通过shallowReactive()来创建一个浅层的响应式对象
        // 只能响应式修改第一层的值
        // return shallowReactive({
        //     msg: "大闸蟹今天没去玩游戏",
        //     stu: {
        //         name: "孙悟空",
        //         age: 18,
        //         gender: "男",
        //         friend: {
        //             name: "猪八戒"
        //         }
        //     }
        // })
    },

    components: {
        MyButton
    }
}
</script>
<template>
    <h1>{{ msg }}</h1>

    <h2>{{ stu.name }} -- {{ stu.age }} -- {{ stu.gender }}</h2>
    <h3>{{ stu.friend.name }}</h3>
    <hr />
    <h2>{{ hello }}</h2>
    <hr />
    <MyButton></MyButton>
    <MyButton></MyButton>
    <MyButton></MyButton>
    <MyButton></MyButton>
</template>

methods

  • methods 用来指定实例对象中的方法
    • 它是一个对象可以在它里边定义多个方法
    • 这些方法最终将会被挂载到组件实例上
    • 可以直接通过组件实例来调用这些方法
    • 所有组件实例上的属性都可以在模板中直接访问
    • methods中函数的this会被自动绑定为组件实例
<script>
import MyButton from "./components/MyButton.vue"
import { shallowReactive } from "vue"

export default {
    // data用来指定实例对象中的响应式属性
    data() {
        return {
            msg: "今天天气真不错"
        }
    },

    /* 
        methods 用来指定实例对象中的方法 
            - 它是一个对象可以在它里边定义多个方法
            - 这些方法最终将会被挂载到组件实例上
            - 可以直接通过组件实例来调用这些方法    
            - 所有组件实例上的属性都可以在模板中直接访问
            - methods中函数的this会被自动绑定为组件实例
    */
    methods: {
        sum(a, b){
            // console.log(this) // 组件实例 vm
            return a + b
        },

        changeMsg(){
            this.msg = "新的消息"
        }
    }
}
</script>
<template>
    <h1>{{ msg }}</h1>
    <h2>{{ sum(2, 5) }}</h2>
    <button @click="changeMsg">点我一下</button>
</template>

computed

  • 计算属性只在其依赖的数据发生变化时才会重新执行
    • 对比:methods中的方法每次组件重新渲染都会调用
  • 会对数据进行缓存
  • 会被挂载到组件实例上
  • 在计算属性的getter中尽量只做读取相关的逻辑。 不要执行那些会产生(副)作用的代码即不修改
  • 计算属性的简写(只有getter时)
        name(){
             return this.lastName + this.firstName
        }
  • 可以为计算属性设置setter使得计算属性可写但是不建议这么做
<script>
import MyButton from "./components/MyButton.vue"
import { shallowReactive } from "vue"

export default {
    // data用来指定实例对象中的响应式属性
    data() {
        return {
            msg: "今天天气真不错",
            stu: {
                name: "孙悟空",
                age: 18,
                gender: "男"
            },
            firstName: "悟空",
            lastName: "孙",

        }
    },

    methods: {
        updateAge() {
            if (this.stu.age === 18) {
                this.stu.age = 17
            } else {
                this.stu.age = 18
            }
        },

        // methods中的方法每次组件重新渲染都会调用
        getInfo() {
            console.log("getInfo调用了")
            return this.stu.age >= 18
                ? "你是一个成年人。"
                : "你是一个未成年人。"
        }
    },

    /* 
        computed 用来指定计算属性
        {
            属性名:getter
        }
        - 计算属性只在其依赖的数据发生变化时才会重新执行
        - 会对数据进行缓存
        - 会被挂载到组件实例上
    */
    computed: {
        info() {
            // 在计算属性的getter中尽量只做读取相关的逻辑
            // 不要执行那些会产生(副)作用的代码即不修改
            console.log("---> , info调用了")

            return this.stu.age >= 18
                ? "你是一个成年人"
                : "你是一个未成年人"
        },

        // 计算属性的简写(只有getter时)
        // name(){
        //     return this.lastName + this.firstName
        // }
        // 可以为计算属性设置setter使得计算属性可写但是不建议这么做
        name: {
            get() {
                return this.lastName + this.firstName
            },

            set(value) {
                // set在计算属性被修改时调用
                this.lastName = value[0]
                this.firstName = value.slice(1)
            }
        }
    }
}
</script>
<template>
    <p>{{ msg }}</p>
    <h1>{{ stu.name }} -- {{ stu.age }} -- {{ stu.gender }}</h1>
    <h2>评语:{{ info }}</h2>
    <h2>methods:{{ getInfo() }}</h2> <!--与上边info的效果一样区别在于computed不会每次都调用,也不需要加括号-->
    <button @click="updateAge">减龄</button>
    <hr />
    <!-- <h3>{{ info }}</h3> -->
    <h3>{{ name }}</h3>
    <hr />
    <h2>{{ arr[0] }} -- {{ arr[1] }} -- {{ arr[2] }}</h2>
</template>

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: vue

“Vue3【创建项目、代码分析、响应式原理-代理、data详解、methods、computed】” 的相关文章