快速上手 vue3

news2024/11/30 8:33:42

快速上手 vue3

文章目录

  • 1. 组合式 api
  • 2. 路由
  • 3. 定义全局方法和变量
  • 4. 父子组件调用 --> 自定义事件
  • 5. 生命周期函数
  • 6. 状态管理 vuex

1. 组合式 api

  1. setup
  2. ref
  3. reactive
  4. computed
  5. 生命周期钩子 , onMounted …

2. 路由

安装路由: npm install vue-router

创建一个 router.js

import {createRouter, createWebHistory} from "vue-router";

const routes = [
    {
        path: '/',
        component: import("@/App.vue")
    }
]


const router = createRouter({
    // createWebHistory() 省略 * 号
    history: createWebHistory(),
    routes
})


export default router;

将 router 注册到 vue 应用中并使用

import './assets/main.css'

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

// 引入 router
import router from "@/router/router";

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

const app = createApp(App);

// 使用路由
app.use(router);
app.mount('#app')

使用 路由:

创建两个组件 home 和 login

home

<script setup>
// 使用路由 --> 需要引入两个对象
import {useRouter, useRoute} from "vue-router";

const router = useRouter();
const route = useRoute();

// 初始化
const init = () => {
  console.log("当前路由", route.path)

  console.log("过 5 秒 跳转到 Login 页面")

  setTimeout(() => {
    router.push("/login")
  }, 5000)
}

init();

</script>

<template>
  <div>我是头页面</div>
</template>

<style scoped>

</style>

login

<script setup>
// 使用路由 --> 需要引入两个对象
import {useRouter, useRoute} from "vue-router";

const router = useRouter();
const route = useRoute();

// 初始化
const init = () => {
  console.log("当前路由", route.path)

  console.log("过 5 秒 跳转到 home 页面")

  setTimeout(() => {
    router.push("/home")
  }, 5000)
}

init();
</script>

<template>
  <div>我是登陆页面</div>
</template>

<style scoped>

</style>

效果:

在这里插入图片描述

3. 定义全局方法和变量


定义一个 全局的方法 Utils

import './assets/main.css'

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

// 引入 router
import router from "@/router/router";


const Utils = {
    isEmpty: (value) => {
        if (value === null || value === undefined || value.trim() === '') {
            return true;
        }

        return false;
    }
}


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

const app = createApp(App);

// 通过 globalProperties 定义一个全局方法  , 这里就定义了一个 Utils 
app.config.globalProperties.Utils = Utils;

// 使用路由
app.use(router);
app.mount('#app')


在 App 组件中使用 , 这里需要通过 getCurrentInstance 获取一个 proxy 的代理对象,然后才能拿到 全局定义的方法.

getCurrentInstance 方法是 Vue 3 中的一个全局 API,它用于获取当前正在执行的组件实例。该方法可以用在任何 Vue 3 组件的方法中,

<script setup>

import {getCurrentInstance, onMounted} from "vue";

const {proxy} = getCurrentInstance();


onMounted(() => {
  let test = "no Null";
  console.log("调用全局为空判断", proxy.Utils.isEmpty(test));
})

</script>

<template>

  <div>
    <router-view></router-view>
  </div>

</template>

<style scoped>

</style>


效果:

在这里插入图片描述


watch 的使用

<script setup>

import {ref, watch} from "vue";

const msg = ref(100);

let updateMsg = () => {
  msg.value = msg.value - 1;
}

// 使用 watch 函数监视 msg 改变
watch(
    msg,
    (newValue, oldValue) => {
      console.log("我发现了 msg 被修改了 , 修改成: " + newValue + " 旧的的 msg 为: " + oldValue)
    },
    // immediate 在页面渲染之前执行一下 watch , deep 开启深度监视
    {immediate: true, deep: false}
)

</script>

<template>
  <div>用来展示 watch 的使用</div>
  <br/>
  <div>当前 msg 的值为: {{ msg }}</div>
  <button @click="updateMsg">点击改变 msg</button>
</template>

<style scoped>

</style>


页面效果:

在这里插入图片描述

4. 父子组件调用 --> 自定义事件

父组件通过 ref 对象调用子组件方法

子组件通过 emit 方法调用父组件方法

演示:创建两个 组件 一个是 son 一个是 parent

在这里插入图片描述


父组件往子组件传递参数

这里需要使用到 : defineProps 方法 用来接受父组件传递来的属性

parent 组件

<script setup>

import Son from "@/views/Son.vue";
import {ref} from "vue";

const parentMsg = ref("我是父组件传递过来的参数");

</script>

<template>

  <div>
    <Son :parentMsg="parentMsg"></Son>
  </div>

</template>

<style scoped>

</style>

son 组件

<script setup>

// 使用 defineProps 接受父组件传递过来的属性
const props = defineProps({
  parentMsg: {
    type: String,
    default: ""
  }
})


</script>

<template>

  <div id="son">
    <div>
      我是父组件传入的参数: {{ parentMsg }}
    </div>

  </div>

</template>

<style scoped>

#son {
  border: 1px solid red;
  text-align: center;
}

</style>

父组件调用子组件的方法

子组件定义的方法需要通过 defineExpose 显示的暴露给 父组件 ,才能让父组件调用到.

son 组件

<script setup>

import {ref} from "vue";

const props = defineProps({
  parentMsg: {
    type: String,
    default: ""
  }
})

const parentMsgMethod = ref("");

const ParentOpSon = (msg) => {
  parentMsgMethod.value = msg;
}

// 想要让父组件调用 子组件的方法需要将 子组件提供的方法暴露出去
defineExpose({
  ParentOpSon
})

</script>

<template>

  <div id="son">
    <div>
      我是父组件传入的参数: {{ parentMsg }}
    </div>
    <br/>
    <hr/>
    <div>
      父组件调用子组件的方法传递的参数
    </div>
    <div>
      {{ parentMsgMethod }}
    </div>

  </div>

</template>

<style scoped>

#son {
  border: 1px solid red;
  text-align: center;
}

</style>

parent 组件

<script setup>

import Son from "@/views/Son.vue";
import {ref} from "vue";

const parentMsg = ref("我是父组件传递过来的参数");


// 定义一个 sonRef 引用对象去调用 子组件的方法
const sonRef = ref();
const opSon = () => {
  sonRef.value.ParentOpSon(parentMsg);
}

</script>

<template>

  <div>
    <Son :parentMsg="parentMsg" ref="sonRef"></Son>
    <button @click="opSon">调用子组件并传递参数</button>
  </div>

</template>

<style scoped>

</style>

效果:

在这里插入图片描述

子组件调用父组件的方法 : 使用场景 : 比如 通过 子组件新增加了一条数据,父组件展示的数据 就需要刷新 ,比如重新获取列表 , 在 子组件新增完数据 就需要 调用父组件的方法 , 或者说是通知 父组件更新列表(调用更新列表的方法).


使用到的方法: defineEmits , 因为 vue3 是没有 this 对象的 我们想要通过 emit 触发 自定义事件 就需要 通过 defineEmits 来获取到 emit 对象。

parent 组件:

<script setup>

import Son from "@/views/Son.vue";
import {ref} from "vue";

const parentMsg = ref("我是父组件传递过来的参数");


// 定义一个 sonRef 引用对象去调用 子组件的方法
const sonRef = ref();
const opSon = () => {
  sonRef.value.ParentOpSon(parentMsg);
}

// 提供给子组件调用的方法
const sonMsg = ref();
const ParentMethod = (e) => {
  console.log(e);
  sonMsg.value = e;
}

</script>

<template>

  <div>
   // @opParent 监听自定义事件 ,如果触发了自定义事件 就调用 parentMethod 函数
    <Son :parentMsg="parentMsg"
         @opParent="ParentMethod"
         ref="sonRef"></Son>
    <button @click="opSon">调用子组件并传递参数</button>
    <hr/>
    <br/>
    <div>子组件调用父组件的方法传递过来的参数: {{ sonMsg }}</div>
  </div>

</template>

<style scoped>

</style>

son组件

<script setup>

import {ref} from "vue";

const props = defineProps({
  parentMsg: {
    type: String,
    default: ""
  }
})

const parentMsgMethod = ref("");

const ParentOpSon = (msg) => {
  parentMsgMethod.value = msg;
}

// 想要让父组件调用 子组件的方法需要将 子组件提供的方法暴露出去
defineExpose({
  ParentOpSon
})


// 子组件调用父组件的方法

// 引入 emit
const emit = defineEmits();
const opParent = () => {
  emit("opParent", "我是子组件传给父组件的参数")
}

</script>

<template>

  <div id="son">
    <div>
      我是父组件传入的参数: {{ parentMsg }}
    </div>
    <br/>
    <hr/>
    <div>
      父组件调用子组件的方法传递的参数
    </div>
    <div>
      {{ parentMsgMethod }}
    </div>
    <br/>
    <hr/>
    <button @click="opParent">点击我调用父组件的方法</button>

  </div>

</template>

<style scoped>

#son {
  border: 1px solid red;
  text-align: center;
}

</style>

关于 自定义事件 ,vue3 和 vue2 写法差不多,只不过 vue2 可以直接通过 this 来调用 , 而 vue3 需要通过 几个方法来 获取 emit 对象 和 暴露方法等 .

5. 生命周期函数

在 vue3 生命周期函数 删除了 beforeCreate 和 create . beforeDestroy 和 destroyed 新增了 onBeforeUnmount 和 onUnmounted.


引用:

  1. onBeforeMount: 在挂载开始之前被调用。在此钩子函数中,模板已经编译完成,但尚未渲染到真实的 DOM 中。
  2. onMounted: 在挂载完成后被调用。此时,实例已经挂载到 DOM 上,可以进行 DOM 操作。
  3. onBeforeUpdate: 在响应式数据更新之前被调用。在这个阶段,虚拟 DOM 中的数据已经和实际 DOM 同步,但尚未应用到 DOM 上。
  4. onUpdated: 在响应式数据更新并应用到 DOM 后被调用。
  5. onBeforeUnmount: 在实例销毁之前被调用。在这个钩子函数内部,实例仍然完全可用。
  6. onUnmounted: 在实例销毁后被调用。此时,实例和其相关的指令、事件监听器等都被解绑,组件将不再被使用。


5 和 6 就类似与 vue2 的 beforeDestroy 和 destroyed


虽然 vue3 删除了 beforeCreate 和 created 生命周期 函数 ,但是我们可以自己 写一个 初始化方法 比如 init() 调用 ,效果就类似于 beforeCreate 和 create 函数

<script setup>

import {onBeforeMount, onMounted} from "vue";

const init = () => {
  console.log("我是 init 方法")
}

init();


onBeforeMount(() => {
  console.log("我是 onBeforeMount")
})
onMounted(() => {
  console.log("我是 onMounted")
})

</script>

<template>

</template>

<style scoped>

</style>

在这里插入图片描述

6. 状态管理 vuex

安装 vuex: npm install vuex --save

创建一个 stroe 目录 在 stroe 目录下 创建一个 index.js 或者 自己命名 , 在 main.js 中 引入时 正确引入即可.

main.js

import './assets/main.css'

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

// 引入 router
import router from "@/router/router";

// 引入 store
import store from "@/store";

const Utils = {
    isEmpty: (value) => {
        if (value === null || value === undefined || value.trim() === '') {
            return true;
        }

        return false;
    }
}


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

const app = createApp(App);

// 通过 globalProperties 定义一个全局变量 , 这里就定义了一个 Utils
app.config.globalProperties.Utils = Utils;

// 使用路由
app.use(router);
app.use(store);
app.mount('#app')


引用:

  1. State(状态):
  • 在 Vuex 中,State 用于存储应用程序的状态数据。它是仓库中的单一数据源。
  • State 对象通常包含多个属性,每个属性都代表一个特定的状态值。
  1. Getters(获取器):
  • Getters 类似于组件中的计算属性。它们允许你从仓库中派生出新的状态。
  • Getters 可以用于对仓库中的状态进行过滤、排序、映射等操作,返回衍生的值。
  1. Mutations(变化):
  • Mutations 是用于修改仓库中状态的函数。
  • Mutations 是同步的操作,用于响应并更新仓库中的状态。
  • 每个 Mutation 函数都会接收一个参数,即 state 对象,用于对状态进行修改。
  1. Actions(动作):
  • Actions 类似于 Mutations,但是 Actions 可以处理异步操作。
  • Actions 用于提交 Mutations,进而修改状态。
  • 在 Actions 中可以执行异步任务、调用 API、提交多个 Mutations 等操作。
  • Actions 不直接修改状态,而是通过调用 Mutations 来修改。

import {createStore} from "vuex";

const store = createStore({
    state: {},
    getters: {},
    mutations: {},
    actions: {},

});

export default store;


定义完 我们来使用一下 store

使用 store 和 使用路由很相识 都需要 通过一个方法引入 , store 需要使用 useStore 方法.

Stroe 组件

<script setup>

import {useStore} from "vuex";

const store = useStore();

const numIncrement = () => {
  // 通过 commit 调用 mutations 里定义的 increment 方法 改变 num 的值
  store.commit("increment", 1);
}

const asyncButton = () => {
  store.dispatch("testAsync");
}

</script>

<template>
  <div>获取 store 中的 state 的属性num: {{ store.state.num }}</div>
  <button @click="numIncrement">num++</button>
  <br/>
  <hr/>
  <div>获取 store 中的 getters 计算出全新的num: {{ store.getters.resetNum }}</div>
  <br/>
  <hr/>
  <div>通过 actions 方法 异步增加 num:{{store.state.num}}</div>
  <button @click="asyncButton">点击触发异步增加 num</button>
</template>

<style scoped>

</style>

store 目录下的 index.js

import {createStore} from "vuex";

const store = createStore({
    state: {
        num: 0,
    },
    getters: {
        resetNum: (state) => {
            return state.num * 5;
        }
    },
    mutations: {
        increment(state, value) {
            state.num += value;
        }
    },
    actions: {
        testAsync(context) {
            new Promise((resolve, reject) => {
                setTimeout(() => {
                    console.log("开启定时器")
                    resolve();
                }, 2000)
            }).then(res => {
                context.state.num += 1;
            })
        }
    },

});

export default store;

页面效果:

在这里插入图片描述

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

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

相关文章

欠拟合、过拟合及优化:岭回归

问题:训练数据训练的很好啊,误差也不大,为什么在测试集上面有问题呢? 当算法在某个数据集当中出现这种情况,可能就出现了过拟合现象。 1、 什么是过拟合与欠拟合 欠拟合 过拟合 分析 第一种情况:因为机器学习到的天鹅特征太少了,导致区分标准太粗糙,不能准确识别出天鹅…

基于SSM的摄影约拍系统

基于SSM的摄影约拍系统的设计与实现 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringSpringMVCMyBatisJSP工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 【主要功能】 前台系统&#xff1a;首页拍摄作品展示、摄影师展示、模特展示、文章信息、交流论…

【Java学习之道】线程的生命周期与状态转换

引言 多线程编程是Java程序员必备的技能之一&#xff0c;它可以让我们的程序更加高效地运行。在学习多线程编程时&#xff0c;我们需要了解线程的生命周期和状态转换。本篇文章将为你揭示线程的奥秘&#xff0c;让你轻松掌握多线程编程的基础知识。 一、线程的生命周期 线程…

解码自然语言处理之 Transformers

自 2017 年推出以来&#xff0c;Transformer 已成为机器学习领域的一支重要力量&#xff0c;彻底改变了翻译和自动完成服务的功能。 最近&#xff0c;随着 OpenAI 的 ChatGPT、GPT-4 和 Meta 的 LLama 等大型语言模型的出现&#xff0c;Transformer 的受欢迎程度进一步飙升。这…

【LeetCode刷题(数据结构与算法)】:平衡二叉树

给定一个二叉树&#xff0c;判断它是否是高度平衡的二叉树 本题中&#xff0c;一棵高度平衡二叉树定义为&#xff1a; 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;true 输入&#xff1a;roo…

SpringMVC全注解开发

在学习过程中&#xff0c;框架给我们最大的作用&#xff0c;就是想让开发人员尽可能地只将精力放在具体业务功能的实现之上&#xff0c;而对于各种映射关系的配置&#xff0c;统统由框架来进行完成&#xff0c;由此&#xff0c;注解就很好的将映射功能进行实现&#xff0c;并且…

CentOS-7网卡重启后关闭的解决方法

第一步查找网卡&#xff1a; ip addr 如下图&#xff1a; 于是发现网卡eth0。 第二步进入网卡配置目录并进行配置&#xff1a; cd /etc/sysconfig/network-scriptsvim ifcfg-eth0 第三步改配置如下图&#xff1a; 然后每次重启后网卡会自动启动。

网络基础2(1)

HTTP 1.应用层协议2.send和recv单独使用不安全3.URL4.urlencode和urldecode5.HTTP协议格式6.HTTP中的常见请求方法POST&&GET7.HTTP的状态码8.HTTP常见Header &#x1f31f;&#x1f31f;hello&#xff0c;各位读者大大们你们好呀&#x1f31f;&#x1f31f; &#x1f6…

【算法|前缀和系列No.1】牛客网 DP34 【模板】前缀和

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【牛客网刷题】 &#x1f354;本专栏旨在提高自己算法能力的同时&#xff0c;记录一下自己的学习过程&#xff0c;希…

Opencv——颜色模型+通道分离与合并

视频加载/摄像头调用 VideoCapture允许一开始定义一个空的对象 VideoCapture video VideoCapture(const String &filename,int apiPreferenceCAP_ANY) filename:读取的视频文件或者图像序列名称 apiPreference:读取数据时设置的属性&#xff0c;例如编码格式、是否调用Op…

罗技鼠标接收器丢失或损坏后用另一个接收器配对的方法

本文介绍罗技鼠标在丢失、损坏其自身原有的接收器后&#xff0c;将另一个新的接收器与原有鼠标相互配对的方法。 在开始之前&#xff0c;大家需要首先查看两个内容&#xff1a;首先是原有的鼠标——大家需要查看自己的鼠标&#xff08;罗技键盘也是同样的操作&#xff09;底部&…

【动态规划】309. 买卖股票的最佳时机含冷冻期、 714. 买卖股票的最佳时机含手续费

提示&#xff1a;努力生活&#xff0c;开心、快乐的一天 文章目录 309. 买卖股票的最佳时机含冷冻期&#x1f4a1;解题思路&#x1f914;遇到的问题&#x1f4bb;代码实现&#x1f3af;题目总结 714. 买卖股票的最佳时机含手续费&#x1f4a1;解题思路&#x1f914;遇到的问题&…

MybatisPlus 从零开始 全面学习!

引入 本文以下将mybatisPlus简称为mp 首先注意: mybatisPlus不是mybatis 的替代品,而是增强mybatis的技术. 只做增强不做改变, 引入他不会对现有工程产生影响. 快速入门 基本步骤 以下为mapper例子: 要继承这个BaseMapper类, 并在泛型括号中 标注好要操作的类 public interf…

【题解】[NOIP2015]扫雷游戏(Java C++)

题目描述 见 P2670 [NOIP2015 普及组] 扫雷游戏 - 洛谷。 前置知识 无。 题目分析 只需要统计每一个格子周围 8 个格子的地雷数量即可。 重点是处理边界情况&#xff0c;比如左上角&#xff0c;有五个格子不在数组范围内&#xff0c;需要特殊处理。 为了避免思路混乱&a…

div盒子放在页面正中间,添加旋转动画的时候,盒子向右下偏移

一、问题代码&#xff08;核心部分&#xff09; //盒子定位在页面正中心 #spinner { position: absolute; left: 50%; top: 50%; border: #2ecc71 solid 1px; transform: translate(-50%, -50%); animation: rotate 5s linear 2s forwards; transform-origin: 50% 50%; } keyfr…

hadoop组成

在hadoop1.x时代,Hadoop中的MapReduce同时处理业务逻辑运算和资源调度,耦合性较大; 在hadoop2.x时代,新增了yarn,主要负责资源的调度,MapReduce仅负责运算; 在hadoop3.x时代,在组成上没有变化;

【Vue面试题二十八】、vue要做权限管理该怎么做?如果控制到按钮级别的权限怎么做?

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 面试官&#xff1a;vue要做权限管理该怎么做…

社区活动|Apollo开发者城市活动·长沙站来啦!

Apollo开发者城市活动长沙站 2023/10/22 &#x1f64b;想亲身乘坐无人车&#xff0c;感受自动驾驶技术的魅力吗&#xff1f; &#x1f64b;想与技术大咖面对面&#xff0c;了解自动驾驶的历史与原理吗&#xff1f; &#x1f64b;想与本地开发者交流心得&#xff0c;实现自动…

springboot自动配置原理面试题(自用)

springboot自动装配主要是基于注解编程和约定大于配置的思想设计 核心步骤&#xff1a; 1 组件必须包含configuration并声明为bean注解返回注入到IOC容器中 2 第三方jar包&#xff0c;根据/meta-inf/目录下增加spring.factories文件加载配置文件中的内容 3 springboot获取到…

游戏开发这么久没见过github-lfs-居然不能下载图片的,这就让你见到了解决方法

以前很少见到github上有游戏的整体仓库&#xff0c;还觉得是游戏人都不爱分享 git 是很好的分布式代码管理&#xff0c;但对于大部分的“”云资源“”管理&#xff0c;git的很多原生功能并不擅长 现在想想&#xff0c;其实也合理&#xff0c;基本只要是手游换皮游戏&#xff…