Vue3(三):生命周期、路由、自定义hooks

news2024/11/16 7:34:16

这里终于明白了为什么一直有这个语法报错,就是在提示你哪里错的地方上方注释一行/*eslint-disable*/,之前一直警告这个错误感谢老师! 

一、vue2和vue3生命周期 

还有一个问题就是父组件和子组件哪个先挂载完毕呢?答案是子组件先挂载完毕。因为首先解析入口文件index.html=>main.ts=>App.vue=>Person.vue,所以当然是Person.vue先挂载完毕,才能继续解析App.vue。 

  <template>
    <div class="person">
      <h2>当前求和为:{{ sum }}</h2>
      <button @click="changeSum">点我sum+1</button>
    </div>
  </template>
  
  <!-- vue3写法 -->
  <script lang="ts" setup name="Person">
    import { 
      ref, 
      onBeforeMount, 
      onMounted, 
      onBeforeUpdate, 
      onUpdated, 
      onBeforeUnmount, 
      onUnmounted 
    } from 'vue'
  
    // 数据
    let sum = ref(0)
    // 方法
    function changeSum() {
      sum.value += 1
    }
    console.log('setup')
    // 生命周期钩子
    onBeforeMount(()=>{
      console.log('挂载之前')
    })
    onMounted(()=>{
      console.log('挂载完毕')
    })
    onBeforeUpdate(()=>{
      console.log('更新之前')
    })
    onUpdated(()=>{
      console.log('更新完毕')
    })
    onBeforeUnmount(()=>{
      console.log('卸载之前')
    })
    onUnmounted(()=>{
      console.log('卸载完毕')
    })
  </script>

二、自定义hooks 

hook本质是一个函数,用use开头,把setup函数中使用的Composition API进行了封装。可以更方便我们去复用处理数据的逻辑.

有时候我们会写很多数据和方法,如果都写在Person.vue会很大很复杂也不好修改,所以我们可以在src下新建hooks文件夹 ,建立useDog.ts和useSum.ts,拆分Person.vue中的东西。

例如:

Person.vue

<template>
  <div class="person">
    <h2>当前求和为:{{ sum }},放大十倍{{ bigSum }}</h2>
    <button @click="add">点我sum+1</button>
    <hr>
    <img v-for="(dog,index) in dogList" :src="dog" :key="index">
    <hr>
    <button @click=" getDog">再来一只小狗</button>
  </div>
</template>

<script lang="ts" setup name="Person">
  import useSum from '@/hooks/useSum'
  import useDog from '@/hooks/useDog'
  
  let { sum,add,bigSum} = useSum()
  let { dogList, getDog } = useDog()
</script>

<style scoped>
.person {
  background-color: skyblue;
  border-radius: 0 0 10px;
  box-shadow: 10px;
  padding: 10px;
}
button {
  margin: 5px;
}
img{
  height: 100px;
}
</style>

useDog.ts

import { reactive, onMounted } from 'vue';
import axios from 'axios';

export default function () {
  //数据
  let dogList = reactive([
    'https://images.dog.ceo/breeds/pembroke/n02113023_4373.jpg',
  ]);
  //方法
  async function getDog() {
    try {
      let result = await axios.get(
        'https://dog.ceo/api/breed/pembroke/images/random'
      );
      dogList.push(result.data.message);
    } catch (error) {
      alert(error);
    }
  }
    //钩子
    onMounted(() => {
      getDog();//千万别忘了在上面引入onMounted
    });
    //向外部提供数据
    return { dogList, getDog };
}

useSum.ts

import { ref,onMounted,computed } from 'vue';

export default function () {
  //数据
  let sum = ref(0);
  let bigSum = computed(()=>{
    return sum.value*10
  })
  //方法
  function add() {
    sum.value += 1;
  }

  //钩子
  onMounted(()=>{
    add()
  })

  //向外传输
  return {sum,add,bigSum}
}

效果:

但是可能遇到如下报错,'xxx' is never reassigned.use 'const' instead prefer-const,解决办法如下: 

三、路由 

1.理解:

2.路由的基本切换

其实大致和vue2是差不多的,

(1)首先要下载vue-router的依赖

(可能有些在创建项目的时候就已经选择了要配置router,那么这时候就不要下载了,可以去packge.json中查看自己的vue-router版本号如果有的话就不用下载了)

npm install vue-router@4(后面可以指定版本,或者不@直接下载就是最新版本)

 (2)在src目录下新建一个router目录,在router目录下新建一个index.ts文件

//创建一个路由器并暴露粗去

//第一步:引入
import { createRouter, createWebHistory } from 'vue-router';
//引入一个个要呈现的组件
import Home from '../pages/Home.vue';
import News from '../pages/News.vue';
import About from '../pages/About.vue';

//第二步:创建路由器
const router = createRouter({
  history: createWebHistory(),//路由器的工作模式
  routes: [//引入路由规则
    {
      path: '/home',
      component: Home,
    },
    {
      path: '/news',
      component: News,
    },
    {
      path: '/about',
      component: About,
    },
  ],
});
export default router;

createRouter函数,新建一个路由器;

createWebHistory函数可以创建一个 HTML5 History 路由实例,从而能够支持浏览器的前进和后退按钮。

routes:存放一个一个的路由;在这里每一个路由都是一个对象,必须要指定的由两个参数:

path:指定路由的路径

component:指定路由对应的组件

(3)在main.ts中引入路由

import { createApp } from "vue"
import APP from './App.vue'
//引入路由
import router from './router'
//创建一个应用
const app = createApp(APP)
// 使用路由器
app.use(router)
//挂载整个应用到app中
.mount('#app')

(4)实现路由的跳转

在App.vue中这样写,利用RouterLink导航 和to=""路径active-class=""实现点哪哪亮效果

RouterLink标签会被渲染成一个 <a> 标签,点击它时会触发路由切换。

RouterView 标签是展示区,会根据当前路由的路径自动加载对应的组件,并将其渲染到页面中。

<template>
    <div class="app">
        <h2 class="title">Vue路由测试</h2>
        <!-- 导航区 -->
        <div class="navigate">
            <RouterLink to="/home" active-class="xiaozhupeiqi">首页</RouterLink>
            <RouterLink to="/news" active-class="xiaozhupeiqi">新闻</RouterLink>
            <RouterLink to="/about" active-class="xiaozhupeiqi">关于</RouterLink>
        </div>
        <!-- 展示区 -->
        <div class="main-content">
            <RouterView></RouterView>
        </div>
    </div>
</template>

<script lang="ts" setup name="App">
import { RouterView, RouterLink } from 'vue-router'

</script>

<style>
/* App */
.title {
    text-align: center;
    word-spacing: 5px;
    margin: 30px 0;
    height: 70px;
    line-height: 70px;
    background-image: linear-gradient(45deg, gray, white);
    border-radius: 10px;
    box-shadow: 0 0 2px;
    font-size: 30px;
}

.navigate {
    display: flex;
    justify-content: space-around;
    margin: 0 100px;
}

.navigate a {
    display: block;
    text-align: center;
    width: 90px;
    height: 40px;
    line-height: 40px;
    border-radius: 10px;
    background-color: gray;
    text-decoration: none;
    color: white;
    font-size: 18px;
    letter-spacing: 5px;
}

.navigate a.xiaozhupeiqi {
    background-color: #64967E;
    color: #ffc268;
    font-weight: 900;
    text-shadow: 0 0 1px black;
    font-family: 微软雅黑;
}

.main-content {
    margin: 0 auto;
    margin-top: 30px;
    border-radius: 10px;
    width: 90%;
    height: 400px;
    border: 1px solid;
}</style>

(5)pages中的静态页面 

 分别有Home.vue,About.vue,News.vue 这里不再写明,可以去老师的笔记里面自取

(6)效果

3.两个注意点

4.两种工作模式

1. history模式

    优点:`URL`更加美观,不带有`#`,更接近传统的网站`URL`。

   缺点:后期项目上线,需要服务端配合处理路径问题,否则刷新会有`404`错误。

//创建一个路由器并暴露粗去

//第一步:引入
import { createRouter, createWebHistory } from 'vue-router';
//引入一个个要呈现的组件
import Home from '../pages/Home.vue';

//第二步:创建路由器
const router = createRouter({
  history: createWebHistory(),//路由器的工作模式history
  routes: [//引入路由规则
    {
      path: '/home',
      component: Home,
    }
  ],
});
//暴露出去
export default router;

2. hash模式

 优点:兼容性更好,因为不需要服务器端处理路径。

 缺点:`URL`带有`#`不太美观,且在`SEO`优化方面相对较差。

 const router = createRouter({

       history:createWebHashHistory(), //hash模式

       /******/

    })

 5.to的两种写法

 字符串写法和对象写法

<!-- 第一种:to的字符串写法 -->
<router-link active-class="active" to="/home">主页</router-link>

<!-- 第二种:to的对象写法 -->
<router-link active-class="active" :to="{path:'/home'}">Home</router-link>

其实对象写法也分为两种,在学完命名之后可以有name和path两种写法 

6.命名路由 

 作用:可以简化路由跳转及传参

写法:name:'xxx'

这样写的话就可以在跳转路由的时候这样写:

7.嵌套路由 

假如想在新闻的展示区再做一个导航区和显示区,如图所示,这时候就需要嵌套路由。 

(1) 首先我们编写`News`的子路由,在pages下新建Detail.vue

<template>
    <ul class="news-list">
        <li>编号:xxx</li>
        <li>标题:xxx</li>
        <li>内容:xxx</li>
    </ul>
</template>

<script setup lang="ts" name="About">

</script>

<style scoped>
.news-list {
    list-style: none;
    padding-left: 20px;
}

.news-list>li {
    line-height: 30px;
}
</style>

(2)配置路由规则,使用children配置项

用法:children:[{ path:'xxxx', componnent:xxxx}] 

{
      name: 'xinwen',
      path: '/news',
      component: News,
      children:[
        {
          path: 'detail',//嵌套路由路径不用加/
          component: Detail,
        }
      ]
    },

(3) news.vue中跳转路由(记得要加完整路径)

<template>
    <!-- 导航区 -->
    <div class="news">
        <ul>
            <li v-for="news in newsList" :key="news.id">
                <RouterLink to="/news/detail">{{ news.title }}</RouterLink>
            </li>
        </ul>
        <!-- 展示区 -->
        <div class="news-content">
            <RouterView></RouterView>
        </div>
    </div>
</template>

<script setup lang="ts" name="News">
import { reactive } from 'vue';
import { RouterView,RouterLink } from 'vue-router';

const newsList = reactive([
    {id:'cgp01',title:'今天周一',content:'嘻嘻'},
    {id:'cgp02',title:'今天周二',content:'不嘻嘻'},
    {id:'cgp03',title:'今天周三',content:'不不嘻嘻细'},
    {id:'cgp04',title:'今天周四',content:'不不不嘻嘻'}
])
</script>

8.query参数 

我们发现上方实现的效果newscontent的数据是写死的,那怎么把数据传过去呢?

(1)传递参数 

用to传参有两种写法:

   // News.vue  
         <ul>
            <li v-for="news in newsList" :key="news.id">
                <!-- 第一种写法 模板字符串写法 冗杂 -->
                <!-- <RouterLink :to="`/news/detail?id=${news.id}`">{{ news.title }}</RouterLink> -->
                <!-- 第二种写法 对象写法 -->
                <RouterLink 
                :to="{
                    // path:'/news/detail',
                    name:'xiangqing',
                    query:{
                        id:news.id,
                        title:news.title,
                        content:news.content
                    }
                }"
                >
                    {{ news.title }}
                </RouterLink>
            </li>
        </ul>

(2) 接收参数

<template>
    <ul class="news-list">
        <li>编号:{{query.id }}</li>
        <li>标题:{{query.title}}</li>
        <li>内容:{{query.content}}</li>
    </ul>
</template>

<script setup lang="ts" name="About">
import { toRefs } from 'vue';
import { useRoute } from 'vue-router';
let route = useRoute()
// console.log(route);可以发现route上有我们需要的query参数
//解构让query参数等于route上面就不用写route.query.id
let { query } = toRefs(route) 
// 直接解构query一定丢失响应式,导致点两次导航区就不更新了
// 加上torefs是不让query丢失响应式
</script>

 需要注意的是 直接解构query一定会让其丢失响应式,导致点两次导航区就不更新了加上torefs是不让query丢失响应式。

9.params参数

第一种字符串:

<!-- params第一种 占位符+模板字符串 -->
<RouterLink :to="`/news/detail/${news.id}/${news.title}/${news.content}`">{{ news.title }}</RouterLink>

记得一定要占位符 

这里有个注意点,就是万一不想传content怎么办?就是在占位符后面加个?就好了 

 

第二种对象:

需要注意的是不能用path 

<!-- 第二种 对象 params -->
                <RouterLink 
                :to="{
                    name: 'xiangqing', //用name跳转
                    params: {
                        id: news.id,
                        title: news.title,
                        content: news.title
                    }
                }"
                >
                    {{ news.title }}
                </RouterLink>

备注1:传递`params`参数时,若使用`to`的对象写法,必须使用`name`配置项,不能用`path`。

备注2:传递`params`参数时,需要提前在规则中占位。

Detail.vue 

 10.路由的props配置

之前上面写的detail.vue很冗杂,我们可以利用props配置

(1)props布尔值写法 

 props的布尔值写法,作用:把收到了每一组params参数,作为props传给Detail组件(只能和params配合)

props:true

(2) props的函数写法(常用)

 作用:把返回的对象中每一组key-value作为props传给Detail组件

(3) 对象写法(少写)

作用:把对象中的每一组key-value作为props传给Detail组件

11.replace属性

1. 作用:控制路由跳转时操作浏览器历史记录的模式。

2. 浏览器的历史记录有两种写入方式:分别为push和replace:

push是追加历史记录(默认值)。

 replace是替换当前记录。

3. 开启`replace`模式:

<RouterLink replace .......>News</RouterLink>

添加replace之后不能前进后退 

 

12.编程式导航

先来实现一个效果,点击首页看三秒之后自动跳转到新闻页面。其实这就是实现了一个简单的编程式路由导航效果。

//home.vue
<script setup lang="ts" name="Home">
import { onMounted } from 'vue'
import { useRouter } from 'vue-router'
const router = useRouter()
onMounted(() => {
    setTimeout(() => {
        router.push('/news')
    }, 3000)
})
</script>

那么接下来做一个复杂一点的: 

 在新闻页面的导航区增加按钮,通过点击按钮实现跳转。其实这也是现实开发中常用的编程时路由导航,而且一般都比routerlink使用的多。而且在vue2中用这个点击次数多可能会报错,但是在vue3中并不会。

//news.vue
<template>
    <div class="news">
        <!-- 导航区 -->
        <ul>
            <li v-for="news in newsList" :key="news.id">
                <!-- 通过点击按钮实现路由跳转 -->
                <button @click="showNewsDetail(news)">查看新闻</button>
                <RouterLink :to="{
                    name: 'xiang',
                    query: {
                        id: news.id,
                        title: news.title,
                        content: news.content
                    }
                }">
                    {{ news.title }}
                </RouterLink>
            </li>
        </ul>
        <!-- 展示区 -->
        <div class="news-content">
            <RouterView></RouterView>
        </div>
    </div>
</template>

<script setup lang="ts" name="News">
import { reactive } from 'vue'
import { RouterView, RouterLink, useRouter } from 'vue-router'

const newsList = reactive([
    { id: 'asfdtrfay01', title: '很好的抗癌食物', content: '西蓝花' },
    { id: 'asfdtrfay02', title: '如何一夜暴富', content: '学IT' },
    { id: 'asfdtrfay03', title: '震惊,万万没想到', content: '明天是周一' },
    { id: 'asfdtrfay04', title: '好消息!好消息!', content: '快过年了' }
])

const router = useRouter()
//写一个接口限制类型防止news报错
interface NewsInter {
    id: string,
    title: string,
    content: string
}

function showNewsDetail(news: NewsInter) {
    router.replace({
        name: 'xiang',
        query: {
            id: news.id,
            title: news.title,
            content: news.content
        }
    })
}

效果:

 

13.重定向

1. 作用:将特定的路径,重新定向到已有路由。

2. 具体编码: 

 

这样默认显示的教师你redirect后的页面。 

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

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

相关文章

从零搭建部署最新AI系统源码ChatGPT网站AI绘画系统,图文详细搭建部署教程文档,Suno-AI音乐生成大模型

一、系统前言 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;那么如何搭建部署AI创作ChatGPT&#xff1f;小编这里写一个详细图文教程吧。已支持…

关于运行阿里云直播Demo报的错

flutter --version dart --version 如何使用Flutter框架推流_音视频终端 SDK(Apsara Video SDK)-阿里云帮助中心MediaBox音视频SDK下载指南_音视频终端 SDK(Apsara Video SDK)-阿里云帮助中心 终端输入 dart pub --trace get --no-precompile 打印详细报错信息 详细咨询…

网络篇04 | 应用层 mqtt(物联网)

网络篇04 | 应用层 mqtt&#xff08;物联网&#xff09; 1. MQTT协议介绍1.1 MQTT简介1.2 MQTT协议设计规范1.3 MQTT协议主要特性 2 MQTT协议原理2.1 MQTT协议实现方式2.2 发布/订阅、主题、会话2.3 MQTT协议中的方法 3. MQTT协议数据包结构3.1 固定头&#xff08;Fixed header…

c++中常用库函数

大小写转换 islower/isupper函数 char ch1 A; char ch2 b;//使用islower函数判断字符是否为小写字母 if(islower(ch1)){cout << ch1 << "is a lowercase letter." << end1; } else{cout << ch1 << "is not a lowercase lette…

MySQL 社区版 安装总结

很早就安装过MySQL&#xff0c;没有遇到过什么问题&#xff0c;直接next就行了&#xff0c;这次在新电脑上安装却遇到了一些问题&#xff0c;记录一下。 安装的是MySQL社区版&#xff0c;下载地址是www.mysql.com&#xff0c;进入后选择DOWNLOAD页面&#xff0c;选择MySQL Com…

【STL详解 —— stack和queue的介绍及使用】

STL详解 —— stack和queue的介绍及使用 stackstack的定义方式stack的使用 queuequeue的定义方式queue的使用 stack stack是一种容器适配器&#xff0c;专门用在具有后进先出操作的上下文环境中&#xff0c;其只能从容器的一端进行元素的插入与提取操作。 stack的定义方式 首…

flutter跑通腾讯云直播Demo

运行示例 前提条件 要求java jdk 11版本 并且配置到了环境变量 重要 要求flutter 版本 2.8.0 并且配置到了环境变量 重要 要求dart-sdk版本2.15 并且配置到了环境变量 重要 您已 注册腾讯云 账号&#xff0c;并完成 实名认证。 申请 SDKAPPID 和 SECRETKEY 登录实时音视频控…

Web前端 JavaScript笔记4

1、元素内容 属性名称说明元素名.innerText输出一个字符串&#xff0c;设置或返回元素中的内容&#xff0c;不识别html标签元素名.innerHTML输出一个字符串&#xff0c;设置或返回元素中的内容&#xff0c;识别html标签元素名.textContent设置或返回指定节点的文本内容&#x…

基于springboot实现购物推荐网站系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现购物推荐网站系统演示 摘要 随着信息互联网购物的飞速发展&#xff0c;一般企业都去创建属于自己的电商平台以及购物管理系统。本文介绍了东大每日推购物推荐网站的开发全过程。通过分析企业对于东大每日推购物推荐网站的需求&#xff0c;创建了一个计算机管…

vue快速入门(二十三)侦听器的简单写法与完整写法

注释很详细&#xff0c;直接上代码 上一篇 新增内容 侦听器简单写法侦听对象或属性侦听器完整写法侦听对象&#xff08;可选深度侦听&#xff09; 源码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name…

基于单片机和安卓平台的移动物联网应用开发实训系统设计

摘要:文章介绍了一种采用单片机和安卓移动设备构建移动物联网应用开发实训系统的方法。并基于该系统完成了实训的项目设计,实现了通过手机远程获取单片机上的传感器数据以及远程控制单片机上的开关设备等典型的物联网应用。 关键词:单片机;传感器;安卓应用开发 1 物联网应…

【MATLAB源码-第189期】基于matlab的人工蜂群优化算法(ABC)无人机三维路径规划,输出做短路径图和适应度曲线

操作环境&#xff1a; MATLAB 2022a 1、算法描述 Artificial Bee Colony&#xff08;ABC&#xff09;算法是一种模仿蜜蜂觅食行为的优化算法&#xff0c;它通过模拟蜜蜂群体的社会结构和行为来解决数学优化问题。本文将详细介绍ABC算法的基本原理、算法流程、以及在实际应用…

第十五届蓝桥杯省赛C/C++大学B组真题及赛后总结

目录 个人总结 C/C 组真题 握手问题 小球反弹 好数 R 格式 宝石组合 数字接龙 爬山 拔河 ​编辑 再总结及后续规划 个人总结 第一次参加蓝桥杯&#xff0c;大二&#xff0c;以前都在在学技术&#xff0c;没有系统的学过算法。所以&#xff0c;还是花了挺多时间去备…

政安晨:【深度学习神经网络基础】(七)—— 神经网络评估分类

目录 简述 评估分类概述 二值分类 多类分类 对数损失 多类对数损失 政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: 政安晨的机器学习笔记 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指…

深入了解数据结构第四弹——排序(1)——插入排序和希尔排序

前言&#xff1a; 从本篇开始&#xff0c;我们就开始进入排序的学习&#xff0c;在结束完二叉树的学习之后&#xff0c;相信我们对数据在内存中的存储结构有了新的认识&#xff0c;今天开始&#xff0c;我们将进入排序的学习&#xff0c;今天来学习第一篇——插入排序 目录 什…

Python | Leetcode Python题解之第30题串联所有单词的子串

题目&#xff1a; 题解&#xff1a; class Solution:def findSubstring(self, s: str, words: List[str]) -> List[int]:res []m, n, ls len(words), len(words[0]), len(s)for i in range(n):if i m * n > ls:breakdiffer Counter()for j in range(m):word s[i j…

Oracle-实例重启导致其他实例不可访问!

问题背景&#xff1a; 用户报障生产一套11G的RAC集群&#xff0c;每个节点有5个数据库实例&#xff0c;其中一个实例由于ORA-00600错误引发实例异常重启&#xff0c;在该实例重启之后&#xff0c;同服务器上的其他4个实例均出现无法访问的情况&#xff0c;应用反馈出现ORA-1253…

C++初识

这里会对一些内容进行简单的提起&#xff0c;后面会详细讲解 一、注释 作用&#xff1a;在代码中加入一些说明和解释&#xff0c;方便自己或其他人阅读代码 两种格式&#xff1a; 1、单行注释&#xff1a; // 描述信息 通常放在一行代码的上方&#xff0c;或者一条语句的末…

Java代码基础算法练习-删除空格-2024.04.15

任务描述&#xff1a; 请从键盘获取一串字符&#xff0c;然后实现删除字符串空格的操作。 任务要求&#xff1a; 代码示例&#xff1a; 这里提供两种方法 1.使用正则表达式&#xff08;推荐&#xff09; // 用正则表达式的方法 System.out.println("删除空格后的的字符…