vue3对比vue2

这篇具有很好参考价值的文章主要介绍了vue3对比vue2。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

使用vite创建vue项目
  • 什么是vite?
    • 新一代前端构建工具
  • 优势如下:
    • 开发环境中,无须打包操作,可快速的冷启动
    • 清亮快速的热重载
    • 真正的按需编译,不在等待整个应用编译完成
## 创建工程
npm init vite-app <project-name>
## 进入工程目录
cd <project-name>
## 安装依赖
npm install
## 运行
npm run dev
  • 注意,vite初始化后需要你手动安装一下node_modules
vue3中的根标签可以不止一个

vue2就不行

setup
  • vue3中一个新的配置项,值为一个函数
  • setup是所有Composition API(组合式API)表演的舞台
  • 组件中所用到的:数据,方法等等,均要配置在setup
  • setup函数的两种返回值
    • 若返回一个对象,则对象中的属性,方法在模板中均可以直接使用
    • 若返回一个渲染函数,则可以自定义熏染内容
  • 注意点:
    • 尽量不要与vue2.0配置混用
    • vue2.0配置(data,methos,computed…)中可以访问到setup中的属性,方法
    • 但在setpup中不能访问到vue2配置(data,methods,computed)
    • 如果有重名,setup优先
  • setup不能是一个async函数,因为返回值不再是return对象,而是promise,模板看不到return对象中的属性
vue3向下兼容

vue3中也可以按照vue2的方式来写,vue3是向下兼容的

<template>  
  <div class="index">  
    index页面  
    name:  
    {{ name }}  
    age:  
    {{ age }}  
    <br>  
    <router-link to="/test1">test1</router-link>  
  </div>  
</template>
<script>
export default {  
  name: "Index",  
  // 测试只是测试函数,并不考虑响应式  
  setup () {  
    let name = "张三"  
    let age = 18  
  
    // 方法  
    function sayHello () {  
  
    }  
    // 返回对象  
    return {  
      name,  
      age,  
      sayHello  
    }  
}  
}  
</script>  

这里面的returb也可以这样写:

<template>  
  <div class="index">  
    index页面  
    name:  
    {{ name }}  
    age:  
    {{ age }}  
    <br>  
    <router-link to="/test1">test1</router-link>  
  </div>  
</template>  
  
<script>  
import { h } from "vue"  
  
export default {  
  name: "Index",  
  // 测试只是测试函数,并不考虑响应式  
  setup () {  
    let name = "张三"  
    let age = 18  
  
    // 方法  
    function sayHello () {  
  
    } 
    // 返回渲染函数  
    // 此时你页面中写什么都不重要了,直接渲染下面这里写的东西  
    return () => {  
      return h('h1', '白马')  
    } 
}  
}  
</script>

而此时,页面中的内容只剩下return h('h1', '白马')这里指定渲染的内容了

关于你可以在vue3中按照vue2那样写
<template>  
  <div class="test2">  
    <button @click="test1">点击测试</button>  
  </div>  
</template>  
  
<script>  
export default {  
  name: "test2",  
  data () {  
    return {  
      name2:'ls'  
    }  
  },  
  created () {  
  },  
  methods: {  
    test1 () {  
      console.log(this.name)  
      console.log(this.name2)  
    }  
  },  
  setup () {  
    const name = 'zs'  
    return {  
      name  
    }  
  }  
}  
</script>  

像是上面的代码,可以访问到setup中的变量

  • 注意,setup不可以使用async修饰

因为如果被async修饰了,那么它的返回值就不再是对象了,而是一个被promise包裹的对象,而你的模板不认识这个返回值

ref

当初在使用vue2的时候,使用ref是为了给元素打标识之类的作用
在vue3中ref是个函数,原来的没有废掉

非响应式数据:

像是下面一样,定义了非响应式的数据:

<template>  
  <div class="ref">  
    <h5>一个人的信息:</h5>  
    <h5>姓名:{{ name }}</h5>  
    <h5>年龄:{{ age }}</h5>  
    <button @click="changeInfo">修改数据</button>  
  
  </div>  
</template>  
  
<script>  
export default {  
  setup () {  
    let age = 24  
    let name = 'zs'  
    const changeInfo = () => {  
      name = '李四'  
      age = 50  
      console.log(name,age)  
    }  
    return {  
      age,  
      name,  
      changeInfo  
    }  
  
  }  
  
}  
</script>  

这里的按钮点击了,在控制台输出的值会更改,但是页面中的值并没有发生改变,因为此时他不是响应式数据

虽然这里不是响应式数据了,但是也没有一些多余的getter,setter,当你想要使用响应式数据的时候,可以进行按需引入ref来使用

例如下面的:

<template>  
  <div class="ref">  
    <h5>一个人的信息:</h5>  
    <h5>姓名:{{ name }}</h5>  
    <h5>年龄:{{ age }}</h5>  
    <h5>爱好:{{ hobby }}</h5>  
    <button @click="changeInfo">修改数据</button>  
    <button @click="changeHobby">修改爱好</button>  
  </div>  
</template>  
  
<script>  
import { ref } from 'vue'  
  
export default {  
  setup () {  
    let age = 24  
    let name = 'zs'  
    let hobby = ref('唱跳rap,篮球')  
    const changeInfo = () => {  
      name = '李四'  
      age = 50  
      console.log(name, age)  
    }  
    const changeHobby = () => {  
      hobby.value = '学习'  
    }  
    return {  
      age,  
      name,  
      changeInfo,  
      hobby,  
      changeHobby  
    }  
  }  
}  
</script>

此时如果你直接输出一下hobby这个响应式对象,可以发现它是:

{
    "__v_isShallow": false,
    "dep": {
        "w": 0,
        "n": 0
    },
    "__v_isRef": true,
    "_rawValue": "学习",
    "_value": "学习"
}

这样的
而这里的RefImpl的意思是引用的实现

标准的称呼为引用实现对象,或是引用对象,简称ref对象

在vue3的模板中,解析html部分的{{}}内容时,它会自动.value

ref中的对象会使用proxy来包装

例如下面的代码:

setup () {  
  let job = ref({  
    salary: 30,  
    work: 'black man'  
  })  
  const getObj = () => {  
    console.log(job.value)  
  }  
  getObj()
}

这里输出的对象是:
![[Pasted image 20230603141346.png]]
这里的对象包装方式不同了

像是refimpl的实例对象,是通过getter,setter实现响应式的

ref处理对象的时候,会将里面的对象使用proxy来包装

对象类型的数据,内部会求助vue3中的一个新函数:reactive

reactive函数

作用:定义一个对象类型的响应式数据(基本类型不要用它,要用ref函数)
语法:const 代理对象 = reactive(源对象)接收一个对象(或数据),返回一个代理对象(proxy对象)
reactive定义的响应式数据是深层次的
内部基于es6的proxy实现,通过代理对象操作源对象内部数据进行操作

reactive函数处理不了基本类型

用reactive处理对象要比ref简单,像是下面这个:

setup () { 
  let job = ref({  
    salary: 30,  
    work: 'black man'  
  })  
  let company=reactive({  
    name:'武汉轻工大学',  
    year:4,  
    numbers:9000  
  }) 
  const getObj = () => {  
    console.log(job.value)  
    console.log("company:")  
    console.log(company)  
    console.log(company.name)  
  }  
  getObj()
}

直接.属性名即可,不用在.value之后再.属性名

vue3中的响应式原理

vue2的响应式:
实现原理:

  • 对象类型:
    • 通过Object.defineProperty对属性的读取,修改进行拦截(数据劫持)
    • 数组类型:通过重写更新数组的一系列方法来实现拦截(对数组的变更方法进行了包裹)
Object.defineProperty(data,'count',{
get(){},
set(){}
})
  • 存在问题:
    • 新增属性,删除属性,界面不会更新
      像是下面的代码在vue2环境下跑:
<template>  
  <div class="index">  
    <h5>  
      测试vue2中为对象新增/删除属性是否能被监听到  
    </h5>  
    <div class="list-column">  
      <span>  
        name:{{ person.name }}  
      </span>  
      <span>        age:{{ person.age }}  
      </span>  
      <span>        gender:{{ person.gender }}  
      </span>  
      <span>        school:{{ person.school }}  
      </span>  
      <span v-if="person.sclary">  
        sclary:{{ person.sclary }}  
      </span>  
  
    </div>  
    <br>    <button @click="delAttr()">删除school属性</button>  
    <button @click="addAttr()">添加sclary属性</button>  
  </div>  
</template>  
  
<script>  
export default {  
  name: "Index",  
  data () {  
    return {  
      person: {  
        name: '椎间孔',  
        age: 22,  
        gender: '大三',  
        school: '武汉轻工大学'  
      }  
    }  
  },  
  methods: {  
    delAttr () {  
      delete this.person.school  
      console.log('删除之后的对象:')  
      console.log(this.person)  
    },  
    addAttr () {  
      this.person.sclary = 3000  
      console.log('添加之后的对象:')  
      console.log(this.person)  
    }  
  }  
}  
</script>  

依次点击删除和添加:
![[Pasted image 20230603170440.png]]
对象是发生了改变,但是页面中没有改变

  • 监听不到,那么你可以使用this.$set来设置:
this.$set(this.person,'sclary','3000')

那么此时添加属性,页面上也会有响应的

  • 实现同样的目的也可以使用vue.set:
import Vue from 'vue'
// 使用它之前要引入
Vue.set(this.person, 'sclary', '3000')
  • 实现响应式的对象删除属性:
Vue.set(this.person, 'sclary', '3000')
// 下面这个:
this.$delete(this.person, 'school')
// 或者:
Vue.delete(this.person,'school')
  • 对象中的数组实现响应式:
<script>  
import Vue from 'vue'  
  
export default {  
  name: "Index",  
  data () {  
    return {  
      person: {  
        name: '椎间孔',  
        age: 22,  
        gender: '大三',  
        school: '武汉轻工大学',  
        hobby: ['唱', '跳', 'tap', '篮球']  
      }  
    }  
  },  
  methods: {  
    change () {  
      // 下面两种方式都可以
      // this.$set(this.person.hobby, 0, '逛街')
	  // Vue.set(this.person.hobby, 0, '洗黑钱')  
      // 当然你也可以使用数组的方法来修改:
      this.person.hobby.splice(0,1,'洗钱')
    }  
  }  
}  
</script>

vue3的响应式:
实现原理:

  • 通过proxy(代理):拦截对象中任意属性的变化,包括:属性值的读写,属性的添加,属性的删除等
  • 通过Reflect(反射):对被代理对象的属性进行操作
  • MDN文档中描述的Proxy与Reflect:

实现一个proxy的响应式对象:

const person = {  
    name: 'zs',  
    age: 18  
}  
const p = new Proxy(person, {  
    get (target, propName) {  
        console.log('有人读取了')  
        return target[propName]  
    },  
    set (target, propName, value) {  
        console.log(`${ propName }修改为${ value }`)  
        return target[propName] = value  
    }  
})

在控制台尝试使用:
![[Pasted image 20230604000442.png]]

![[Pasted image 20230604000624.png]]

但是像上面的代码,捕获到了他的更新和读取,并没有捕获到它的删除和新增属性
其实proxy也可以监听删除:

const person = {  
    name: 'zs',  
    age: 18  
}  
const p = new Proxy(person, {  
    get (target, propName) {  
        console.log('有人读取了')  
        return target[propName]  
    },  
    set (target, propName, value) {  
        console.log(`${ propName }修改为${ value }`)  
        target[propName] = value  
    },  
    deleteProperty (target, p) {  
        console.log(`删除属性${p}`)  
        delete target[p]  
    }  
})

![[Pasted image 20230604002915.png]]
要注意,delete target[p]这里的删除是有返回值的,其实把这里的删除返回即可:

deleteProperty (target, p) {  
    console.log(`删除属性${p}`)  
    return delete target[p]  
}

关于proxy的增加属性:

  • get是有人读取某个属性时会被调用
  • set有人修改属性,或追加属性时会被调用
  • deleteProperty删除属性时调用

虽然proxy可以监听到增删改查,但是vue3不是这样做的
![[Pasted image 20230604003421.png]]

使用两种方式实现对象的映射
let obj = { a: 1, b: 2 }  
/*  console.log('使用Object.defineProperties来实现映射:')  
  Object.defineProperties(obj, 'c', {    get () {      return 3    }  })  Object.defineProperties(obj, 'c', {    get () {      return 4    }  })*/  
console.log('使用reflect来实现映射')  
const x1 = Reflect.defineProperty(obj, 'c', {  
  get () {  
    return 3  
  }  
})  
console.log(x1)  
const x2 = Reflect.defineProperty(obj, 'c', {  
  get () {  
    return 4  
  }  
})  
console.log(x2)

第一种方式使用Object.defineProperties重复覆盖属性会报错,此时可以使用try,catrch来捕获,但是为了程序的壮行这样是否有些麻烦了
所以可以使用Reflect.defineProperty来进行映射,它重复覆盖并不会出错,而且在每一次覆盖是都会有一个为boolean的返回值

vue3中响应式对象的雏形:
let person = {  
    name: 'zs',  
    age: 24,  
    gender: '大三',  
    school: '武汉轻工大学'  
}  
const p = new Proxy(person, {  
    get (target, propName) {  
        console.log(`有人获取了${ propName }`)  
        return Reflect.get(target, propName)  
    },  
    set (target, propName, value) {  
        console.log(`有人修改了${ propName }`)  
        Reflect.set(target, propName, value)  
    },  
    deleteProperty (target, propName) {  
        console.log(`有人删除了p身上的${ propName }`)  
        return Reflect.deleteProperty(target, propName)  
    }})
reactive对比ref
  • 从定义数据角度对比:
    ref用来定义:基本类型数据
    reactive用来定义:对象(或数组)类型数据
    备注:ref也可以用来定义对象(或数组)类型数据,它内部会自动通过reactive转为代理对象

  • 从原理角度对比:
    ref通过Object.defineProperty()getset来实现响应式(数据劫持)
    reactive通过使用Proxy来实现响应式(数据劫持),并通过Reflect操作源对象内部的数据

  • 从使用角度对比:
    ref定义的数据:操作数据需要.value,读取数据时,模板中直接读取不需要.value
    reactive定义的数据:操作数据与读取数据:均不需要.value

关于vue2中的props

如果你像是在下面的子组件中不写props:
父组件:

<template>  
  <div class="index">  
    <chindren msg="你好" about="关于信息"></chindren>  
  </div>  
</template>  
  
<script>  
import Vue from 'vue'  
import Chindren from '@/components/chindren.vue'  
  
export default {  
  name: "Index",  
  components: { Chindren },  
  }  
}  
</script>  

子组件:

<template>  
  <div class="lim">  
  
  </div></template>  
  
<script>  
export default {  
  name: "chindren",  
  mounted () {  
    console.log(this)  
  }  
}  
</script>  

注意,此时在子组件的props中是没有定义的
,但是在页面的控制台可以看到输出的this:
![[Pasted image 20230605234406.png]]
在vm的$attrs上挂载了传入的值

到这里你可能想着,不定义props,直接传过来多方便,
但是,如果不定义props的话,你是无法限制传入的类型

关于vue2的slot

在子组件中不去定义slot:
父组件:

<chindren msg="你好" about="关于信息">  
  <h5>这是一个slot的内容</h5>  
</chindren>

子组件:

<template>  
  <div class="lim">  
  </div>
</template>
<script>  
export default {  
  name: "chindren",  
  mounted () {  
    console.log(this)  
  }  
}  
</script>

控制台中:
![[Pasted image 20230605234843.png]]

slot是存在的
使用多个插槽:
父组件:

<chindren msg="你好" about="关于信息">  
  <template slot="name">  
    <h5>张三</h5>  
  </template>  
  <template slot="gender">  
    <h5>gender:5</h5>  
  </template>  
</chindren>

子组件:

<template>  
  <div class="lim">  
    <slot name="name"></slot>  
    <slot name="gender"></slot>  
  </div>  
</template>  
  
<script>  
export default {  
  name: "chindren",  
  mounted () {  
    console.log(this)  
  }  
}  
</script>
setup的两个注意点:
  • setup的执行时机:
    在beforeCreate之前执行一次,this是undefined

  • setup的参数
    props:值为对象,包含:组件外部传递过来,且组件内部声明接收了的属性
    context:上下文对象

    attrs:值为对象,包含:组件外部传递过来,但没有在props配置中声明的属性,相当于this. a t t r s s l o t s : 收到的插槽内容 , 相当于 t h i s . attrs slots:收到的插槽内容,相当于this. attrsslots:收到的插槽内容,相当于this.slota
    emit:分发自定义事件的函数,相当于this.$emit

例如在下面的例子中,父组件向子组件传值,但是子组件并没有定义props:
父组件:

<template>  
  <div class="lim">  
    你好  
    <demo msg="来自setup的信息" index="20"></demo>  
  </div>  
</template>  
  
<script>  
import Demo from './demo.vue'  
  
export default {  
  name: "setup",  
  components: { Demo }  
}  
</script>  

子组件:

<template>  
  <div>  
    子组件的内容  
  </div>  
</template>  
  
<script>  
export default {  
  name: "demo",  
  setup (props) {  
    console.log('setup props:')  
    console.log(props)  
  }  
}  
</script>

控制台输出:
![[Pasted image 20230611142633.png]]
如果此时在子组件中定义了props:

<template>  
  <div>  
    子组件的内容  
  </div>  
</template>  
  
<script>  
export default {  
  name: "demo",  
  props:['msg','index'],  
  setup (props) {  
    console.log('setup props:')  
    console.log(props)  
  }  
}  
</script>  

此时setup中接收的第一个参数输出:
![[Pasted image 20230611143321.png]]
注意,此时它也是响应式对象

那么关于传入的其他形参:
父组件:

<template>  
  <div class="lim">  
    你好  
    <demo @click="hello" msg="来自setup的信息" index="20">  
      <slot>这是第一个slot</slot>  
      <template slot="qwe">  
        自定义插槽  
      </template>  
      <template v-slot:two>  
        自定义插槽的第二个插槽  
      </template>  
    </demo>  
  </div>  
</template>  
  
<script>  
import Demo from './demo.vue'  
  
export default {  
  name: "setup",  
  components: { Demo },  
  setup () {  
    const hello = () => {  
      console.log('hello world')  
    }  
    return {  
      hello  
    }  
  }  
}  
</script>

子组件:

<template>  
  <div>  
    子组件的内容  
    <button @click="log">测试触发子组件事件</button>  
  </div>  
</template>  
  
<script>  
export default {  
  name: "demo",  
  props: ['msg', 'index'],  
  emits: ['hello'],  
  setup (props, context) {  
    console.log('setup props:')  
    console.log(props)  
    console.log('context.attrs:')  
    // vue2中的$attrs  
    console.log(context.attrs)  
    console.log('context.emit:')  
    // 插槽  
    console.log('context.slots:')  
    console.log(context.slots)  
  
    const log = () => {  
      console.log('触发了子组件的click')  
    }  
    return {  
      log  
    }  
  },  
}  
</script>

在控制台中查看:

![[Pasted image 20230611144611.png]]

计算属性
<template>  
  <div class="computed">  
    <div class="inputLim">  
      性:  
      <el-input v-model="lastName" placeholder="Please input"/>  
    </div>  
    <br>    <div class="inputLim">  
      名:  
      <el-input v-model="firstName" placeholder="Please input"/>  
    </div>  
    <br>  
    <div class="inputLim">  
      名字:  
      <el-input v-model="fullName" placeholder="Please input"/>  
    </div>  
  </div>  
</template>  
  
<script setup>  
import { computed, ref } from 'vue'  
  
const lastName = ref('')  
const firstName = ref('')  
  
// 简写,没有考虑计算属性被修改的情况  
/*const fullName = computed(() => {  
  return lastName.value + ' ' + firstName.value})*/  
  
// 完整写法  
const fullName = computed({  
  get () {  
    return lastName.value + ' ' + firstName.value  
  },  
  set (val) {  
    console.log(val)  
  }})  
  
</script>  
  
<style scoped lang="less">  
  
.computed {  
  display: flex;  
  flex-direction: row;  
  .inputLim {  
    display: flex;  
    flex-direction: row; 
  }  
}  
</style>

![[Pasted image 20230611162743.png]]

watch属性

一个简单的使用:

<template>  
  <div class="watch">  
    <h2>sum:{{ sum }}</h2>  
    <button @click="sum++">add</button>  
    <br>    <h2>当前的信息为:{{ msg }}</h2>  
    <button @click="msg+='!'">msg改变</button>  
    <br>    <h2>      姓名:{{ person.name }}  
      年龄:{{ person.age }}  
      学校:{{ person.school }}  
      薪资:{{ person.job.salary }}  
    </h2>  
    <el-text>      注意在vue3中只要对象使用active包裹,那么不管多深,都是可以监听到的  
    </el-text>  
    <div class="btns">  
      <el-button @click="person.name+='~'">修改名字</el-button>  
      <el-button @click="person.age++">修改年龄</el-button>  
      <el-button @click="person.school+='school'">修改学校</el-button>  
      <el-button @click="person.job.salary++">薪资增加</el-button>  
    </div>  
  </div>  
</template>  
  
<script setup>  
import { reactive, ref, watch } from 'vue'  
  
let sum = ref(0)  
let msg = ref("你好")  
let person = reactive({  
  name: 'zs',  
  age: 24,  
  school: '武汉',  
  job: {  
    salary: '3000'  
  }  
})  
// 监视ref所定义的数据  
watch(sum, (newVal) => {  
  console.log('sum发生改变')  
})  
// 监视ref所定义的多个数据  
watch([sum, msg], (newVal, oldVal) => {  
  console.log(newVal, oldVal)  
})  
  
// 配置一上来就监听  
watch(sum, (newVal) => {  
  console.log(newVal)  
}, { immediate: true })  
  
// 监听reactive 定义的数据,  
// 如果监听使用reactive 定义的数据,那么在获取oldVal上会有问题,无法正确地获取oldVal,目前无法解决  
// 但如果你使用ref来定义一个对象,它走的还是reactive的逻辑,也是行不通的  
watch(person, (newVal, oldVal) => {  
  console.log("newVal:")  
  console.log(newVal)  
  console.log("oldVal:")  
  console.log(oldVal)  
})  
</script>
vue3中无法正确监听到对象中watch函数中的oldVal

像是上面代码中,监听persojn的修改中,修改学校字段,此时在控制台查看:
![[Pasted image 20230612232234.png]]
注意,不论你是用ref还是reactive包裹对象,他都是无法监听到oldVal的,这是目前vue3中的问题
当你使用ref包裹对象时,它会自动使用reactive来包裹对象的

监听多个
let sum = ref(0)  
let msg = ref("你好")
watch([sum, msg], (newVal, oldVal) => {  
  console.log(newVal, oldVal)  
})

在vue2中watch为配置对象,只能调用一次,而vue3中 ,watch为函数,可以调用多次

监听中的配置项

一上来就监听一次:

watch(sum, (newVal) => {  
  console.log(newVal)  
}, { immediate: true })
vue3中可以监听嵌套很深的对象

强制开启了deep,你关闭了也没用

监听对象中的某一属性
let person = reactive({  
  name: 'zs',  
  age: 24,  
  school: '武汉',  
  job: {  
    salary: '3000'  
  }  
})
watch(() => person.name, (newVal, oldVal) => {  
  console.log('值发生改变了')  
  console.log(newVal)  
})

![[Pasted image 20230612235713.png]]
此时你修改其它字段是不会被监听到文章来源地址https://www.toymoban.com/news/detail-480886.html

到了这里,关于vue3对比vue2的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 使用Vue3和Vite升级你的Vue2+Webpack项目

    🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页 ——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文并茂🦖生动形象🐅简单易学!欢迎大家来踩踩~🌺 🌊 《IDEA开发秘籍专栏》 🐾 学会IDEA常用操作,工作效率翻倍~💐 🌊 《100天精通Golang(基础

    2024年02月09日
    浏览(67)
  • vue2、vue3、react响应式原理、组件声明周期阐述与对比

    响应式原理: Vue.js 的响应式原理是通过使用 Object.defineProperty 函数来实现的。在 Vue.js 中,当一个对象被传入 Vue 实例的 data 选项中时,Vue.js 会将这个对象的属性转换为 getter 和 setter,以便在属性被访问或修改时能够触发相应的更新。 具体来说,Vue.js 会在实例化过程中递归

    2024年02月06日
    浏览(52)
  • Vue3.0 所采用的 Composition Api 与 Vue2.x 使用的 Options Api 有什么不同?

    Composition API 可以说是Vue3的最大特点,那么为什么要推出Composition Api,解决了什么问题? 通常使用Vue2开发的项目,普遍会存在以下问题: 1、代码的可读性随着组件变大而变差 2、每一种代码复用的方式,都存在缺点 3、TypeScript支持有限 一、Options Api Options API,即大家常说的

    2024年02月12日
    浏览(42)
  • 【前端Vue】Vue3+Pinia小兔鲜电商项目第2篇:什么是pinia,1. 创建空Vue项目【附代码文档】

    Pinia 是 Vue 的专属状态管理库,可以实现跨组件或页面共享状态,是 vuex 状态管理工具的替代品,和 Vuex相比,具备以下优势 提供更加简单的API (去掉了 mutation ) 提供符合组合式API风格的API (和 Vue3 新语法统一) 去掉了modules的概念,每一个store都是一个独立的模块 搭配

    2024年03月21日
    浏览(46)
  • 从Vue2到Vue3【零】——Vue3简介及创建

    内容 链接 从Vue2到Vue3【零】 Vue3简介 从Vue2到Vue3【一】 Composition API(第一章) 从Vue2到Vue3【二】 Composition API(第二章) 从Vue2到Vue3【三】 Composition API(第三章) 从Vue2到Vue3【四】 Composition API(第四章) Vue.js作为一种流行的JavaScript框架已经被广泛应用于前端开发中。随着

    2024年02月16日
    浏览(40)
  • vue2与vue3项目中,分别使用element组件的message消息提示只出现一次的实现

    比如出现以上现象,想要让上一次提示没有结束,下一次提示不会出现就可以用以下方法解决 解决后的现象一:上一次提示框显示后,提示框出现的提示时间没有结束,再次点击,提示框不会有反应,在该提示的时间内一只显示,下一次提示不会出现,直到该提示的时间过了

    2024年02月02日
    浏览(39)
  • Vue3和Vue2有什么区别?

    先来说说Vue3相对于Vue2的优点吧: 更快的渲染速度 更小的体积 更少的内存占用 更丰富的功能 听起来好像Vue3比Vue2强很多啊,但是具体强在哪里呢?我们来看几个代码例子: 首先是安装Vue3和Vue2: 在Vue3中,如果你想注册一个组件,你可以这样做: 而在Vue2中,你需要这样做:

    2024年02月08日
    浏览(89)
  • 使用vite创建vue3的Cesium基础项目

    使用vite创建vue3项目:可以参考官方文档Vite官方中文文档 1.1 在指定文件夹路径下使用npm(前提是已经安装好了node): 1.2 cd到创建的项目文件夹: 安装并使用Cesium; 2.1 找到插件:vue插件, 找到社区插件, ctrl+F搜索“Cesium”,找到Cesium的插件使用教程:Cesium插件 就能找到C

    2024年02月13日
    浏览(55)
  • 如何使用Vite创建Vue3的uniapp项目

    Vue3/Vite 版要求 node 版本^14.18.0 || =16.0.0 如果使用 HBuilderX(3.6.7 以下版本)运行 Vue3/Vite 创建的最新的 cli 工程,需要在 HBuilderX 运行配置最底部设置 node 路径 为自己本机高版本 node 路径(注意需要重启 HBuilderX 才可以生效) HBuilderX Mac 版本菜单栏左上角 HBuilderX-偏好设置-运行配

    2024年02月09日
    浏览(124)
  • rouyi-vue-pro+vue3+vite4+Element Plus项目中使用生成Vue2+Element UI标准模板

    运行一个pro-vue3的前端项目,以及后端服务 在基础设施-代码生成模块中选择某张数据库表导入,并编辑生成信息,前端类型:Vue2+Element UI标准模板 在vue3项目中创建一个vue文件 1.4 srcapitest.js Vue2+Element UI标准模板生成的前端封装好的request请求接口对象 1.5 报错 问题 :在 更新

    2024年02月03日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包