vue2.0和3.0的区别

news/2024/7/10 3:17:04 标签: vue

1. vue2和vue3双向数据绑定原理发生了改变

  1. vue2 的双向数据绑定是利用ES5 的一个 API Object.definePropert()对数据进行劫持 结合 发布订阅模式的方式来实现的。
  2. vue3 中使用了 es6 的 ProxyAPI 对数据代理。

相比于vue2.x,使用proxy的优势如下
defineProperty只能监听某个属性,不能对全对象监听
可以省去for in、闭包等内容来提升效率(直接绑定整个对象即可)
可以监听数组,不用再去单独的对数组做特异性操作 vue3.x可以检测到数 组内部数据的变化

2.在Vue3.0,我们就需要使用一个新的setup()方法,此方法在组件初始化构造的时候触发。

  1. vue引入reactive
  2. 使用reactive()方法来声名我们的数据为反应性数据
  3. 使用setup()方法来返回我们的反应性数据,从而我们的template可以获取这些反应性数据
import { reactive } from 'vue'

export default {
  props: {
    title: String
  },
  setup () {
    const state = reactive({
      username: '',
      password: ''
    })

    return { state }
  }
}

3.默认项目目录结构也发生了变化:

  1. 移除了配置文件目录,config 和 build 文件夹
  2. 移除了 static 文件夹,新增 public 文件夹,并且 index.html 移动到 public 中
  3. 在 src 文件夹中新增了 views 文件夹,用于分类 视图组件 和 公共组件

4. 2.0和3.0的生命周期对比

2.0生命周期3.0生命周期
beforeCreate(组件创建之前)setup(组件创建之前)
created(组件创建完成)setup(组件创建完成)
beforeMount(组件挂载之前)onBeforeMount(组件挂载之前)
mounted(组件挂载完成)onMounted(组件挂载完成)
beforeUpdate(数据更新,虚拟DOM打补丁之前)onBeforeUpdate(数据更新,虚拟DOM打补丁之前)
updated(数据更新,虚拟DOM渲染完成)onUpdated(数据更新,虚拟DOM渲染完成)
-------------
beforeDestroy(组件销毁之前)onBeforeUnmount(组件销毁之前)
destroyed(组件销毁之后)onUnmounted(组件销毁之后)

5.vue3特点

Vue2与Vue3 最大的区别 — Vue2使用选项类型API(Options API)对比Vue3合成型API(Composition API)
作用: 聚合代码 & 逻辑重用

6.知识点

  1. 使用defineComponent 构建应用及绑定事件
  2. 使用setup(props,content)父子通信
  3. 使用 reactive 绑定数据
  4. 使用 ref ( torefs ) 绑定数据
  5. 使用 getCurrentInstance 获取当前实例化对象上下文信息
  6. watch、watchEffect 数据监听

1.使用 reactive 绑定数据

<template>
  <div>
    <h1>使用 reactive 绑定数据</h1>
    <p>{{state.msg}}</p>
    <p>{{info}}</p>
    <p>
      <button @click="changeMsg">changeMsg</button>
    </p>
  </div>
</template>
<script>

// Hooks 编程,在 vue 中导入对应的函数方法,面向函数式进行编程
// Vue-composition-API 这里就是Vue2与Vue3 最大的区别 — Vue2使用选项类型API(Options API)对比Vue3合成型API(Composition API)

import { defineComponent, reactive } from "vue";
export default defineComponent({
  name: 'test1',
  setup() {  // setup钩子函数
    // 使用响应式函数reactive构建proxy响应式对象state
    const state = reactive({
      msg: '时光'
    })
    console.log(state); // state对象是一个proxy拦截对象
    let info = 'hello'; // info是一个普通对象,修改后不会被proxy拦截,进而页面也不会动态更新
    const changeMsg = () => { // 在外边定义methods
      state.msg = '时光,你好'
      info = 'hello,你好'
    }
    return {  // 使用时,要把对象return出去,才能在template中使用
      state,
      info,
      changeMsg
    }
  }
})
</script>

————————————————
版权声明:本文为CSDN博主「星空之火@田兴」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_43638968/article/details/114260999

2. setup()函数 完成父子通信

setup(props)第一个参数props

setup函数接收props作为其第一个参数,props对象是响应式的(单向的父—>子),watchEffect或watch会观察和响应props的更新。不要对props对象进行解构,那样会失去响应性。在开发过程中,props对象对用户空间代码时不可变的,用户尝试修改props时会触发警告。
————————————————
版权声明:本文为CSDN博主「星空之火@田兴」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_43638968/article/details/114260999

案例1:props作为setup的第一个参数

// 父组件 Home.vue
<template>
  <div class="home">
    <About :name="sendData"/>
  </div>
</template>
<script>
  import {ref} from 'vue'; 
  import About from './About'
  export default{
    components:{
      About,
    },
    setup(){
      const sendData = ref('这世界很酷');
      return {
        sendData
      }
    }
  }
</script>

// 子组件About.vue
<template>
  <div class="about">
  {{propContent}}
  </div>
</template>
<script>
  import {watchEffect} from 'vue';
  export default{
    props:{
      name:String
    },
    setup(props){
      let propContent;
      watchEffect(()=>{
        propContent = props.name
      })
      return {
        propContent
      }
    }
  }
</script>
————————————————
版权声明:本文为CSDN博主「星空之火@田兴」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_43638968/article/details/114260999

2. setup(props,context)第二个参数Context上下文对象

// 父组件 Home.vue
<template>
  <div class="home">
    <About :name="sendData.val" @name-changed=changeName>
      世界变化不停,人潮川流不息
    </About>
  </div>
</template>
<script>
  import {reactive} from 'vue';
  import About from './About';
  export default{
    components:{
      About,
    },
    setup(){
      const sendData = reactive({
        val:'sendData'
      })

      setTimeout(()=>{
        sendData.val+=1;
      },1000)

      function changeName(){
        console.log("事件传送出来了")
      }
      return {
        sendData,
        changeName,
      }
    }
  }
</script>

//子组件 About.vue
<template>
  <div class="about">
    
  </div>
</template>
<script>
  import {watch} from 'vue';
  export default {
    props:{
      name:String
    },
    setup(props, context) {
      console.log(context,"上下文");
      watch(()=>props.name,(newName,oldName)=>{
        console.log(newName,oldName);
        context.emit('name-changed');//相当于this.$emit()
      }
    );
    },
  }
</script>
————————————————
版权声明:本文为CSDN博主「星空之火@田兴」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_43638968/article/details/114260999

3.使用 ref(toRefs) 绑定数据

<template>
  <div>
    <p>使用v-model双向数据绑定的数据内容是:{{ msg }}</p>
    <p>
      <!-- 自己实现双向数据绑定,监听input事件,动态修改nmsg的值 -->
      <input type="text" ref="myInput" @input="input" :value="nmsg" />
    </p>
    <p>使用@input事件动态实现双向数据绑定的数据内容是:{{ nmsg }}</p>
    <p>
      <!-- 使用ref方法动态定义并双向绑定hmsg -->
      <input type="text" v-model="hmsg" @input="hmagInpu" />
    </p>
    <p>使用ref方法动态定义并双向数据绑定的数据hmsg是:{{ hmsg }}</p>
    <p>toRefs 来实现在模板中不需要追加 state 调用数据:{{ msg }}</p>
  </div>
</template>
<script>
import {
  defineComponent,
  reactive,
  getCurrentInstance,
  toRefs,
  ref,
  computed,
} from "vue";

export default defineComponent({
  setup() {
    const state = reactive({
      msg: "",
      nmsg: "",
      cmsg: computed(() => {
        // 1.计算属性
        return state.msg.length;
      }),
    });

    // 2.可以使用getCurrentInstance hook 来拿到当前实例化对象上下文信息,但是除非极其特殊的情况,否则不建议这样使用
    const { ctx } = getCurrentInstance();
    const input = () => {
      // 在vue3中,因为是面向hooks函数编程,所以,无法通过this拿到当前vue实例化对象
      console.log(ctx.$refs.myInput.value); // 像使用vue2中的this一样,使用ctx(上下文内容信息)
      state.nmsg = ctx.$refs.myInput.value;
    };

    // 3.使用ref方法来定义一个响应式监听的对象,在实际开发中我们都是用这种方法来构建响应式对象
    const hmsg = ref("abc");
    const hmagInpu = () => {
      // 在内部使用hmsg的值,需要使用value来获取对应的值
      console.log("获取到的hmsg值是:" + hmsg.value);
    };

    return {
      // 4.使用toRefs hook方法方便,访问msg不需要使用state.msg,直接msg就可以获取到
      ...toRefs(state),
      hmsg,
      input,
      hmagInpu,
    };
  },
});
</script>

————————————————
版权声明:本文为CSDN博主「星空之火@田兴」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_43638968/article/details/114260999

总结

1.reactive

1…reactive方法,直接传入一个对象 state ,这个对象就是 proxy 拦截的对象
2.然后再把这个 state 对象直接 return 出去就能被调用
3.在 temolate 中使用 state.msg 来访问
4.在 js 中也使用 state.msg 来访问

2.ref

1.使用 ref 直接声明一个 proxy 响应式对象 msg
2.然后把这个 msg 对象直接 return 出去
3.在 template 中直接使用 {{msg}}
4.注意:在 js 中需要使用 msg.value

4.watch、watchEffect 数据监听

<template>
  <div>
    <h1>watch、watchEffect 数据监听</h1>
    <p>{{ msg }}</p>
    <p>{{ msg2 }}</p>
    <p>{{ info }}</p>
    <p>
      <button @click="changeMsg">changeMsg</button>
    </p>
    <p>
      <button @click="changeMsg2">changeMsg2</button>
    </p>
  </div>
</template>
<script>
import { defineComponent, reactive, watchEffect, watch, toRefs } from "vue";

export default defineComponent({
  name: "watch",
  // setup钩子函数
  setup() {
    // 使用响应式函数reactive构建proxy响应式对象state
    const state = reactive({
      msg: "时光",
      msg2: "kity",
      changeMsg2: () => {
        state.msg2 = "kity,你好";
      },
    });
    const changeMsg = () => {
      // 在外边定义methods
      state.msg = "时光,改变";
      info = "hello,改变";
    };
    let info = "hello";
    // watch监听只能是 getter/effect 函数、ref、reactive对象或数组
    // 简单监听
    watch(state, () => {
      console.log("观察整个state中属性变化", state.msg); // 只要state中的值有变化,就会打印
    });
    // 监听指定的信息
    watch(
      () => state.msg,
      (newVal, oldVal) => {
        console.log("01-msg的新值是:" + newVal + "-------旧值是:" + oldVal);
      }
    );
    // 监听多个属性(数组形式)
    watch([() => state.msg, () => state.msg2], (newVal, oldVal) => {
      console.log("02-msg的新值是:" + newVal + "-------旧值是:" + oldVal); // 02-msg的新值是:时光,你好,俞亮-------旧值是:时光,俞亮
    });
    // 不需要指定监听的属性
    watchEffect(() => {
      // 程序运行时,初始化就会执行一次,完成监听准备工作
      console.log("03-watchEffect监听 state 中数据变化:", state.msg); // 有点像computed计算属性,用到的数据发生改变才会执行
    });

    // 使用时,要把对象return出去,才能在template中使用
    return {
      ...toRefs(state),
      info,
      changeMsg,
    };
  },
});
</script>
————————————————
版权声明:本文为CSDN博主「星空之火@田兴」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_43638968/article/details/114260999

http://www.niftyadmin.cn/n/1836007.html

相关文章

Windows下硬盘快速转换成ntfs格式方法

首先要确保你想转换的分区硬盘内没有你的重要数据。 其次打开“开始”-”运行”,输入CMD&#xff0c;然后再跳出的命令行内输入convert *:/fs:ntfs回车即可&#xff0c;*代表你要转换的盘符。比如d盘就是convert d:/fs:ntfs&#xff0c;以此类推。 此方法运用在windows系统下&a…

[原创]HandlerSocket系列(一):由来

新的技术&#xff0c;几乎都是由需求驱动产生的。在仔细深入研究HandlerSocket之前&#xff0c;我觉得有必要先了解一下它所处的历史背景及其它想解决什么样的问题。我想这应该是最关键的&#xff0c;也是做这方面研究和技术选型时第一个应该关注的要点。 先来说一下它的作者Yo…

win7如何清理图标缓存

rem 关闭Windows外壳程序explorer taskkill /f /im explorer.exe rem 清理系统图标缓存数据库 attrib -h -s -r "%userprofile%\AppData\Local\IconCache.db" del /f "%userprofile%\AppData\Local\IconCache.db" attrib /s /d -h -s -r "%userprofil…

生病了。。。

中秋节那天陪妈妈去麦德龙采购&#xff0c;出门时候已经觉得有些天秋了&#xff0c;还说回来先要把长袖衣服找出来。 结果麦德龙卖场里卖蔬菜和肉类的地方空调打得特别冷&#xff0c;导致回来就生病了&#xff0c;伤风咳嗽一下好不了。 今天在家养病。。。 并歇笔几天看看闲书&…

VUE Form表单传参时,json格式转Form Data格式

VUE Form表单传参时&#xff0c;json格式转Form Data格式 最近做了一个项目&#xff0c;form表单传参&#xff0c;之前传参都是v-model双向绑定&#xff0c;然后在data里面定义&#xff0c;把绑定的属性名传过去就行啦&#xff0c;在做这个项目的时候&#xff0c;后台要求传递的…

由“Jasperrpeorts 4.1.2升级到5.1.2对flex项目的解析”到AS3 带命名空间的XML的操作...

原文同步至&#xff1a;http://www.waylau.com/from-jasperrpeorts-4-1-2-upgraded-to-5-1-2-parsing-of-flex-projects-to-the-as3-namespace-xml-operation/ 项目中&#xff0c;对Jasperrpeorts-4.1.2核心包进行了升级&#xff0c;发现&#xff0c;前端flex无法对Jasperrpeor…

发牌区代码-已经完成

本代码主要实现了纸牌的出牌动画。鼠标选中的牌前置&#xff0c;定义的牌可以任意指定大小&#xff0c;程序里面是5张&#xff0c;给每张牌定义了鼠标点击事件。 using System; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using S…

拥抱重构

惧怕重构 提到让你重构一个功能模块&#xff0c;提到让你去修改一个别人的bug,阅读别人的代码&#xff0c;你第一反应是什么&#xff1f;惧怕&#xff1f;想骂人&#xff1f;面对一个代码垃圾场&#xff0c;我想大家都会有些不安&#xff0c;尤其是面对测试团队&#xff0c;上线…