Vue3 - 从 vue2 到 vue3 过渡,这一套就够了(案例 + 效果演示)(一)

目录

一、Vue3 从入门到进阶

1.1、Vue3 相比于 Vue2 好在哪里?

1.2、创建 vue-cli3 脚手架

1.3、Vue3 的使用

1.3.1、拉开序幕的 setup

1.3.2、ref 函数

什么是响应式数据

ref 响应式处理

1.3.3、reactive

1.3.4、reactive 对比 ref

1.3.5、setup 的参数(props、context)

1.3.6、computed 计算属性


一、Vue3 从入门到进阶


1.1、Vue3 相比于 Vue2 好在哪里?

Ps:以下数据来源于官网

a)性能提升:

  • 打包大小减少 41%.
  • 初次渲染快 55%,更新渲染快 133%.
  • 内存减少 54%.
  • ......

b )源码升级:

  • 使用 Proxy 代替 defineProperty 实现响应式.
  • 重写虚拟 DOM 的实现和 Tree-Shaking
  • ......

c)拥抱 TypeScript:

  • Vue3 可以更好的支持 TypeScript

d)新特性:

  • setup 配置
  • ref 与 reactive
  • watch 与 watchEffect
  • provide 与 inject

1.2、创建 vue-cli3 脚手架

Ps:具体怎么创建,可以看这篇 http://t.csdnimg.cn/rq4slicon-default.png?t=N7T8http://t.csdnimg.cn/rq4sl

a)查看当前 vue-cli 的版本,确保在 4.5.0 以上.

 b)安装或者升级 @vue/cli

npm install -g @vue/cli

c)创建

vue create vue_demo

d)启动

cd vue_demo
npm run serve

e)修改 vue.config.js 内容为如下内容,就是为了关闭语法检查

f)main.js 说明

//引入的不再是 vue 构造函数了, 引入的是一个名为 createApp 的工厂函数
import { createApp } from 'vue'
import App from './App.vue'//创建应用实例对象 —— app
const app = createApp(App)
//挂载
app.mount('#app')

g)新特性之一,vue3 的模板接口可以没有根标签

1.3、Vue3 的使用

1.3.1、拉开序幕的 setup

vue3 中有一个新的配置项,值是一个函数.  他是所有组合 API 的“舞台”,也就是说,之前 vue2 组件中使用到的 data、methods...... 都要配置在 setup 中.

a)setup 函数有三种返回值:

  • 若返回一个对象,那么对象的属性、方法,在模板种就可以使用了.
  • 若返回的是一个渲染函数,那么就可以自定义渲染内容(后面细讲,当前只做了解).

b)注意点(请忘掉 vue2 中的 data、methods... 现在是 vue3 的时代):

  • 尽量不要和 vue2.x 混用,原因如下:
    • vue2.x 配置的 data、methods、 computed....... 种可以访问到 setup 中的属性方法,但是 setup 中不能访问到 vue2.x 配置中的 data、methos、computed......
    • 如果有重名,setup 优先.
  • setup 不是一个 async 函数,因为返回值不再是 return 的对象,而是 promise ,模板看不到 return 对象中的属性.

c)案例如下:

<template><!-- vue3 中模板接口可以没有跟标签 --><div>你好</div><div>欢迎来到 vue3</div><div>{{ name }}</div><button @click="sayHi">点我,进行自我介绍~</button>
</template><script>
export default {name: "App",//这里暂时限不考虑响应式的问题setup() {//数据let name = "cyk";let age = 18;//方法function sayHi() {alert(`大家好啊,我是${name}, 今年 ${age} 了`);}return {//模板中需要什么数据,就返回什么name,age,sayHi,};},
};
</script>

点击按钮效果如下 

d)你会发现,当你定义的变量越多,需要 return 的就越多,代码可读性降低了不少.  我们实际上可以把一组关联的数据封装到对象中,这样直接返回这个对象就可以了(这样也要注意的是需要通过 对象.属性名 的方式获取属性). 

<template><div>name: {{ user.name }}</div><div>age: {{ user.age }}</div><div>weight: {{ user.weight }}</div>
</template><script>export default {name: "App",setup() {let user = {name: "cyk",age: 18,weight: "60kg",};return {user,};},
};
</script>

e)当然,有一天你发现自己定义的对象越来越多,最后 return 的东西越来越多,可读性又降低了,那么你可以借鉴 vue2 的方式这样定义数据(doge)

  setup() {let data = {student: {//...},teacher: {//...},//......};return {data,};},

1.3.2、ref 函数

什么是响应式数据

你可以简单的将响应式数据理解为动态数据,也就是说,你对响应式数据的修改,在页面是会得到及时的反馈.

例如通过点击按钮,对 name 进行修改操作,同时希望页面能得到及时的反馈.

非响应式:

<template><div>name: {{ name }}</div><button @click="changeName()">点我改变 name</button>
</template><script>
export default {name: "App",setup() {let name = "cyk";function changeName() {name = "lyj";alert("修改完成!");}return {name,changeName,};},
};
</script>

点击按钮之后,name 并没有修改,这就是非响应式,那么如果我们希望它是响应式就需要依靠 ref 函数了

ref 响应式处理

a)ref 就是用来处理一个响应式数据.

语法如下:

// 创建一个响应式数据的引用对象(reference 对象,简称 ref 对象)
const xxx = ref(initValue)// js 中操作数据
xxx.value// 模板中读取数据
<div>{{xxx}}</div>

使用步骤:

  1. 引入 ref 组件(这一步很容易忘记)
  2. 定义 响应式 对象
  3. 返回对象

通过 console.log(ref("lyj")),就可以观察到以下结果

ref 底层是通过 Object.defineProperty() 的 get 和 set 来实现响应式的 

b)例如通过点击按钮,对 name 进行修改操作,同时希望页面能得到及时的反馈.

<template><div>name: {{ name }}</div><button @click="changeName()">点我改变 name</button>
</template><script>
import { ref } from "vue"; //引入 ref 组件export default {name: "App",setup() {let name = ref("cyk"); //这里返回的是一个对象,通过 .value 就可以拿到值function changeName() {name.value = "lyj"; //必须通过 value 才能获取到对应的值alert("修改完成!");}return {name,changeName,};},
};
</script>

点击按钮前

点击按钮后

c)那么问题来了,如果 ref 中的值是一个嵌套对象,该怎么获取里面的值呢?难道每嵌套一层都需要使用 value 来获取一层么?

如果是嵌套对象,我们可以先这样理解,ref 就相当于对对象的一层封装嘛,通过 .value 的方式就可以拿到对象,此时对象无论怎么封装,原先 js 语法怎么获取,现在就怎么处理.

如下,怎么获取 name 和 c 呢?

    let user = ref({name: "cyk",a: {b: {c: 666,},},});

 name 就不多说了,首先 ref 是通过里面的值是一个 {...} 对象,因此通过 value 就可以拿到这个对象,那么接下来通过对象拿属性值的方式获取即可.

    function getUser() {console.log(user);console.log(user.value.name);console.log(user.value.a.b.c);}

 

对于对象的处理, ref 底层是 调用了 reactive 的 Proxy 来实现响应式的,并通过 Reflect 操作内部的数据.

1.3.3、reactive

a)通过上面讲述可以看出,ref 每次获取值都需要通过 .value 的方法获取,很麻烦.  那么接下来要将的 reactive 就是用来解决这个问题的.

b)reactive 就是用来定义个 对象类型 的响应式数据(基本类型不能用它,只能使用 ref 函数).

Ps:实在想用,你可以把基本类型封装成对象啊

c)reactive 内部是基于 ES6 的 Proxy 实现,通过代理对象操作源对象内部数据进行操作.

d)用法如下:

<template><div>{{ user.name }}</div><div>{{ user.age }}</div><div>{{ user.likes[2] }}</div><div>{{ user.a.b.c }}</div><button @click="changeInfo">点我改变信息</button>
</template><script>
import { ref, reactive } from "vue"; //引入 reactive
export default {name: "App",setup() {let tips = ref(1);let user = reactive({name: "cyk",age: 18,likes: ["唱歌", "弹琴", "谈情"],a: {b: {c: 666,},},});function changeInfo() {// ref 定义的响应式对象需要通过 .value 的方式获取tips.value = 2;// reactive 定义的响应式对象可以直接获取user.name = "lyj";user.age = 17;user.likes[2] = "谈锤子";user.a.b.c = 999;}return {tips,user,changeInfo,};},
};
</script>

1.3.4、reactive 对比 ref

a)定义数据的角度:

  • ref 可定义的数据:基本类型、对象(或数组)类型, 但是对于 对象(或数组)类型,内部是通过 reactive 转为 代理对象。
  • reactive 可定义的数据:对象(或数组)类型.

b)使用的角度:

  • ref:操作数据需要 .value   在模板中读取数据不需要 .value
  • reactive:操作和读取数据都不用 .value

c)原理角度:

  • ref:通过 Object.defineProperty() 的 get 与 set 来实现响应式.
  • reactive:通过使用 Proxy 来实现响应式,并通过 Reflect 操作源对象内部的数据.

1.3.5、setup 的参数(props、context)

setup 的参数如下:

a)props:值为对象,包含:组件外部传递过来,且组件内部声明接收了的属性

例如父组件向 User 子组件传递数据

<template><User name="cyk" :age="age" />
</template><script>
import User from "./views/User.vue"; //引入自定义的组件 User
export default {name: "App",components: { User }, //声明setup() {let age = 18;return {age,};},
};
</script>

User 子组件中使用数据

<template><h1>我是一个学生</h1><div>name: {{ user.name }}</div><div>age: {{ user.age }}</div>
</template><script>
export default {name: "User",props: ["name", "age"],setup(props) {let user = {name: props.name,age: props.age,};return {user,};},
};
</script>

b)context:上下文对象

  • atts:值为对象,包含:组件外传递过来,但没有在 props 配置中声明的属性,相当于 this.$attrs.
  • slots:受到的插槽内容,相当于 this.$slots.
  • emit:分发自定义事件的函数,相当于 this.$emit.

父组件中定义 hello 事件,自定义名为 helloBtn 传递给子组件 User.

<template><!-- @自定义传递的事件名="当前组件 setup return 的函数" --><User @helloBtn="hello" name="cyk" :age="age" />
</template><script>
import User from "./views/User.vue"; //引入自定义的组件 User
export default {name: "App",components: { User }, //声明setup() {let age = 18;function hello() {alert("hello");}return {age,hello,};},
};
</script>

子组件中通过 emits 接收 helloBtn 事件

<template><h1>我是一个学生</h1><div>name: {{ user.name }}</div><div>age: {{ user.age }}</div><button @click="test">父组件传递的事件</button>
</template><script>
export default {name: "User",props: ["name", "age"],//拿到父组件传递的事件,他会交给 setup 中的 context 参数emits: ["helloBtn"],setup(props, context) {let user = {name: props.name,age: props.age,};function test() {//拿到父组件的事件context.emit("helloBtn");}return {user,test,};},
};
</script>

1.3.6、computed 计算属性

与 vue2.x 中的 computed 配置功能一样,凡是需要实时计算的地方就使用它即可

a)简写:没有考虑计算属性被修改的情况

<template><h1>求和</h1><div><input type="number" v-model="test.a" /></div><div><input type="number" v-model="test.b" /></div><div>结果: {{ result }}</div>
</template><script>
import { computed, reactive } from "vue";
export default {name: "App",setup() {let test = reactive({a: 0,b: 0,});let result = computed(() => {return test.a + test.b;});return {test,result,};},
};
</script>

 

b)完整写法:重写 get  set 方法(考虑读和写)

假设需求是:读取时要 a 和 b 的和,修改时要求得到  result 的均分到 a 和 b 

<template><h1>求和</h1><div><input type="number" v-model="test.a" /></div><div><input type="number" v-model="test.b" /></div><div><span>结果: </span><input type="number" v-model="result" /></div>
</template><script>
import { computed, reactive } from "vue";
export default {name: "App",setup() {let test = reactive({a: 0,b: 0,});//简写:没有考虑计算属性被修改的情况// let result = computed(() => {//   return test.a + test.b;// });//完整写法:重写 get set 方法let result = computed({get() {return test.a + test.b;},set(value) {test.a = value / 2;test.b = value / 2;},});return {test,result,};},
};
</script>

当 a  = 5、b  = 9 ,读取如下:

当 result = 15,a 和 b 被修改的情况如下:

Ps:下一篇 “ Vue3 - 从入门到进阶,这一套就够了(案例 + 效果演示)(二)”

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/665449.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【全网独创】2024美赛E题33页成品论文+1-4问完整代码数据助攻

E题社区抗灾能力综合评估与决策模型研究 摘要&#xff1a;社区抗灾能力的提升对于灾害风险管理至关重要。本研究基于机器学 习方法&#xff0c;构建了社区抗灾能力预测模型&#xff0c;以评估社区在灾害事件中的表现。首先&#xff0c; 我们采用梯度提升树模型对社区基础设施、…

Python学习03 -- 函数相关内容

1.def --- 这个是定义函数的关键字 \n --- 这个在print()函数中是换行符号 1.注意是x, 加个空格之后再y 1.形式参数数量是不受限制的&#xff08;参数间用&#xff0c;隔开&#xff09;&#xff0c;传实参给形参的时候要一一对应 返回值 --- 函数返还的结果捏 1.写None的时…

C++ 动态规划 线性DP 最长上升子序列

给定一个长度为 N 的数列&#xff0c;求数值严格单调递增的子序列的长度最长是多少。 输入格式 第一行包含整数 N 。 第二行包含 N 个整数&#xff0c;表示完整序列。 输出格式 输出一个整数&#xff0c;表示最大长度。 数据范围 1≤N≤1000 &#xff0c; −109≤数列中的数…

算法学习——华为机考题库2(HJ11 - HJ20)

算法学习——华为机考题库2&#xff08;HJ11 - HJ20&#xff09; HJ11 数字颠倒 描述 输入一个整数&#xff0c;将这个整数以字符串的形式逆序输出 程序不考虑负数的情况&#xff0c;若数字含有0&#xff0c;则逆序形式也含有0&#xff0c;如输入为100&#xff0c;则输出为0…

Map和Set的封装

目录 一、底层原理 二、红黑树的节点 三、仿函数 四、迭代器 4.1、迭代器的定义&#xff1a; 4.2、*:解引用操作 4.3、->:成员访问操作符 4.4、!、 4.5、迭代器的&#xff1a; 4.6、迭代器的-- 五、Map 六、Set 七、红黑树源码 一、底层原理 我们要知道&#…

机器学习_14_多分类及多标签分类算法

文章目录 1 单标签二分类问题1.1 单标签二分类算法原理1.2 Logistic算法原理 2 单标签多分类问题2.1 单标签多分类算法原理2.2 Softmax算法原理2.3 ovo2.4 ovr2.5 OvO和OvR的区别2.6 Error Correcting 3 多标签算法问题3.1 Problem Transformation Methods3.1.1 Binary Relevan…

kubernetes基本概念和操作

基本概念和操作 1.Namespace1.1概述1.2应用示例 2.Pod2.1概述2.2语法及应用示例 3.Label3.1概述3.2语法及应用示例 4.Deployment4.1概述4.2语法及应用示例 5.Service5.1概述5.2语法及应用示例5.2.1创建集群内部可访问的Service5.2.2创建集群外部可访问的Service5.2.3删除服务5.…

Deepin如何开启与配置SSH实现无公网ip远程连接

文章目录 前言1. 开启SSH服务2. Deppin安装Cpolar3. 配置ssh公网地址4. 公网远程SSH连接5. 固定连接SSH公网地址6. SSH固定地址连接测试 前言 Deepin操作系统是一个基于Debian的Linux操作系统&#xff0c;专注于使用者对日常办公、学习、生活和娱乐的操作体验的极致&#xff0…

【JavaScript】前端攻击

前端攻击 1. CSRF的基本概念、缩写、全称 CSRF&#xff08;Cross-site request forgery&#xff09;&#xff1a;跨站请求伪造。 从上图可以看出&#xff0c;要完成一次CSRF攻击&#xff0c;受害者必须满足两个必要的条件&#xff1a; 登录受信任网站A&#xff0c;并在本地生…

09.领域驱动设计:深入学习6本经典推荐书籍

目录 前言 1、《领域驱动设计&#xff1a;软件核心复杂性应对之道》 1.作者简介 2.内容简介 3.推荐理由 4.豆瓣链接 ​编辑 2、《实现领域驱动设计》 1.作者简介 2.内容简介 3.推荐理由 4.豆瓣链接 ​编辑 3、《领域驱动设计精粹》 1.作者简介 2.内容简介 3.推…

深度学习和大数据技术的进步在自然语言处理领域的应用

文章目录 每日一句正能量前言一、深度学习在NLP中的应用二、大数据技术在NLP中的应用三、深度学习和大数据技术的影响四、应用场景后记 每日一句正能量 努力学习&#xff0c;勤奋工作&#xff0c;让青春更加光彩。 前言 随着深度学习和大数据技术的迅猛发展&#xff0c;自然语…

Qt加载网页崩溃 ASSERT:“m_adapterClient“ in file ...

1、软件启动后加载网页无异常&#xff0c;点击按钮&#xff0c;加载新网页时崩溃 崩溃代码&#xff1a; QWebEngineView *createWindow(QWebEnginePage::WebWindowType type) { Q_UNUSED(type); return this; } 2、原因 Qt只是调用谷歌的浏览器引擎&#xff…

iPad“粘贴自”字样不消失解决办法

iPad“粘贴自”字样不消失解决办法 好无语&#xff0c;写论文主要就靠iPad看资料&#xff0c;复制粘帖的时候卡死搞得我无敌焦躁&#xff0c;问了&#x1f34e;支持的客服才解决&#xff0c;方法如下&#xff1a;1.音量上键按一下 2.音量下键按一下 3.一直按开关机键直到出现苹…

031 递归

何为递归 示例 public static void main(String[] args) {System.out.println(fn(5)); }static int fn(int a){return a 1 ? 1 : a * fn(a - 1); }

浅析Redis③:命令处理之数据返回Client(下)

写在前面 Redis作为我们日常工作中最常使用的缓存数据库&#xff0c;其重要性不言而喻&#xff0c;作为普通开发者&#xff0c;我们在日常开发中使用Redis&#xff0c;主要聚焦于Redis的基层数据结构的命令使用&#xff0c;很少会有人对Redis的内部实现机制进行了解&#xff0c…

华为鸿蒙系统第三方桌面手机管家版本号12.0.1.330

起因 放假在家&#xff0c;准备把自己的旧手机给家里老人看小视频&#xff0c;但是老人不懂智能手机的复杂操作&#xff0c;就想换成《极简桌面》这个软件&#xff0c;在“设置->默认应用->桌面”&#xff0c;但是华为为了“保护用户的隐私以及合法权益”禁用了第三方启…

202417读书笔记|《画•大师 阿尔丰斯•穆夏》——在明亮大胆的色调中熠熠生辉

202417读书笔记|《画•大师 阿尔丰斯•穆夏》——在明亮大胆的色调中熠熠生辉 这是读完的第二本或者第三本穆夏的画集。很赞&#xff0c;他的绘画风格&#xff0c;构图&#xff0c;元素&#xff0c;取大自然的月桂树&#xff0c;常青藤&#xff0c;&#x1f319;的不同形态&…

链表与二叉树-数据结构

链表与二叉树-数据结构 创建叶子node节点建立二叉树三元组&#xff1a;只考虑稀疏矩阵中非0的元素&#xff0c;并且存储到一个类&#xff08;三元组&#xff09;的数组中。 创建叶子node节点 class Node{int no;Node next;public Node(int no){this.nono;} } public class Lb…

Fink CDC数据同步(三)Flink集成Hive

1 目的 持久化元数据 Flink利用Hive的MetaStore作为持久化的Catalog&#xff0c;我们可通过HiveCatalog将不同会话中的 Flink元数据存储到Hive Metastore 中。 利用 Flink 来读写 Hive 的表 Flink打通了与Hive的集成&#xff0c;如同使用SparkSQL或者Impala操作Hive中的数据…

流畅的Python(七)-函数装饰器和闭包

一、核心要义 主要解释函数装饰器的工作原理&#xff0c;包括最简单的注册装饰器和较复杂的参数化装饰器。同时&#xff0c;因为装饰器的实现依赖于闭包&#xff0c;因此会首先介绍闭包存在的原因和工作原理。 二、代码示例 1、变量作用域规则 #!/usr/bin/env python # -*-…