自动创建项目
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>
转载:https://blog.csdn.net/m0_52896752/article/details/128742827
查看评论