Vue 组件及路由2

十三、idea 开发 vue

idea 中安装 Vue 插件 (2023 版本已经无需安装,自带就有)

然后使用 idea 打开之前创建的 vue 项目

启动项目

方案 1: 点击旁边按钮启动

方案 2: 下方终端输入命令 npm run serve

如上,如果脚本改成 dev, 那么就需要改成命令为 npm run dev
idea 中的终端无法执行 npm run serve 启动项目,提示 npm 不是内部或外部命令

解决方案 1: 以管理员身份启动 idea, 打开项目运行

解决方案 2: 不要使用 powershell, 也就是 ps 方式执行 cmd, 换成默认的 cmd

十四、单文件组件【重点】

14.1 介绍

以前

以前是创建了很多.html 的文件组成一个完整项目

现在

vue 项目中是只有一个页面,是一种 spa (单页面程序)

如何实现,一个页面实现整个项目?

就是使用各种组件组装成一个页面. ****

但是,昨天学的组件

使用 Vue.component 来定义全局组件,紧接着用 new Vue ({el: '#app'}) 在每个页面内指定一个容器元素。或者在 Vue 对象内本地注册组件

这种方式在很多中小规模的项目中运作的很好,在这些项目里 JavaScript 只被用来加强特定的视图。
但当在更复杂的项目中,或者你的前端完全由 JavaScript 驱动的时候,下面这些缺点将变得非常明显:

  • 全局定义 (Global definitions) 强制要求每个 component 中的命名不得重复
  • 字符串模板 (String templates) 缺乏语法高亮,在 HTML 有多行的时候,需要用到丑陋的 \
  • 不支持 CSS (No CSS support) 意味着当 HTML 和 JavaScript 组件化时,CSS 明显被遗漏
  • 没有构建步骤 (No build step) 限制只能使用 HTML 和 ES5 JavaScript,而不能使用预处理器,如 Pug (formerly Jade) 和 Babel
    现在

文件扩展名为 **.vue** 的 single-file components (单文件组件) 为以上所有问题提供了解决方法,并且还可以使用 webpack 或 Browserify 等构建工具。

单文件组件的组成结构:

  • template 组件的模块区域 (html)
  • script 业务逻辑区域 (js)
  • style 样式区域 (css)

14.2 使用

在工程的 src/components 下创建一个 Demo1 单文件 Demo1 就是自定义的组件


创建后好,组件内部结构


正常的写代码

html 复制代码
<template>
  <!-- 组件的模板,要求只能有一个根元素 -->
  <div>
    <h1>组件的模板</h1>
    <p>取出数据: {{ msg }}</p>
    <button @click="dianji">按钮</button>
    <p>计算属性: {{ reverseMsg }}</p>
  </div>
</template>

<script>
  export default {
    name: "Demo1", // 组件的名称
    data() {  // 组件的data数据,只能是函数,不能是对象,且必须返回一个对象,数据放在return的对象中
      return {
        msg: '组件的data数据'
      }
    },
    methods: {
      dianji() {
        alert("按钮被点击了")
      }
    },
    // 组件的计算属性
    computed: {
      reverseMsg() {
        return this.msg.split('').reverse().join('')
      }
    }
  }
</script>

<style scoped>
  div{
    color: red;
  }
</style>

组件定义完毕后,需要在其他页面使用
在 HomeView.vue 中使用

  • 哪里使用组件,哪里注册
  • 注册完,组件名当标签用

注意:

其中./ 是相对路径,@是从根路径

html 复制代码
// @是从根路径
import Demo1 from "@/components/Demo1.vue";

// ./ 是相对路径
import Demo2 from "./components/Demo2.vue";

十五、Vue 组件间的参数传递 [熟悉]


15.1 父传子 [熟悉]

父组件中使用子组件时,在标签内设置属性

传递是数字,布尔值需要 v-bind:【真实麻烦 】

传递是变量也需要 v-bind:


子组件中设置 props 接收传递过来的数据即可

15.2 子传父 [了解]

使用组件中的 props 属性是无法完成子组件向父组件传值的

那么,如果需要子组件向父组件传递值该如何做?

  • Vue 提供了方案: 在子组件中使用自定义事件向父组件传递数据.

具体步骤

    1. 子组件通过 **$emit** 函数将数据发给父组件

this.$emit (' 父组件中使用子组件时定义的事件名 ', 数据)

    1. 父组件在使用子组件的时候,定义一个 @事件,这个事件名是 $emit 中自定义的事件名
    1. 父组件中,需要设计这个 @事件的响应函数,函数中设计参数,这个参数就是子组件传递过来的数据
      需求:子组件中设置输入框,输入完,点击按钮,将数据传递给父组件
html 复制代码
<template>
<div>
    我是子组件Son,我收到了父组件的参数:
    姓名:{{name}}
    年龄:{{age}}
    老家:{{home}} <br>
  <input type="text" v-model="num">
  <button @click="sendNum">发送给父组件</button>
</div>
</template>

<script>
export default {
  name: "Son",
  props:["age","name","home"],
  data() {
    return {
      num:null
    }
  },
  methods: {
    sendNum(){
      // 1 子组件向父组件传递数据,使用事件触发
      // this.$emit("父组件中自定义的事件名",要传递的数据)
      this.$emit("receiveData",this.num)
    }
  }
}
</script>

<style scoped>

</style>

父组件中,在子组件标签定义自定义事件准备接收子组件发来的数据

html 复制代码
<template>
  <div>
    <h2>我是Father组件</h2>
    <span>从儿子组件传递过来的数据:{{num}}</span>

    <!--  这里是Father组件,使用子组件son-->
    <!-- 给组件传参,就是设置自定义属性 -->
    <!--@receiveData是自定义事件-->
    <Son :age="18" name="曹丕" :home="home"
         @receiveData="getSonNum"></Son>

  </div>
</template>

<script>
import Son from "@/views/Son.vue";

export default {
  name: "Father",
  components: {Son},
  data() {
    return {
      home:"魏国许都",
      num:null
    }
  },
  methods: {
    getSonNum(num){
      console.log("我是Father组件,我收到了子组件传递过来的数据:",num)
      this.num = num;
    }
  }
}
</script>

<style scoped>

</style>

执行流程解析

十六、Vue-router 路由【重点】

16.1 介绍

路由的本质就是一种对应关系,比如说我们在 url 地址中输入我们要访问的 url 地址之后,浏览器要去请求这个 url 地址对应的资源。

那么 url 地址和真实的资源之间就有一种对应的关系,就是路由。

根据不同的事件来显示不同的页面内容

16.2 Vue 的路由 (先了解,学过后再回头细看!!!)

Vue 默认属于单页面的程序,主要通过 URL 中的 hash 来实现不同页面之间的切换。这种切换方式称作前端路由。

Vue 中使用路由的方式,现在是通过使用 Vue 的核心插件 VueRouter 实现的
Vue Router的核心作用

  • 跳转/切换页面

    • 声明式 (写标签)

      • <router-link to="要跳转的组件名称">
    • 编程式 (写代码)

      • this.$router.push("要跳转的组件名称")
  • 跳转携带数据

    • 声明式导航传递参数通过路径拼接的

      • /about/1001

      • 在index.js的路径中 通过/about/:id 绑定数据

      • 接收 this.$router.params.参数名

    • 编程式导航实现传递参数

      • 传递 this.$router.push({path:'路径',query:{参数名:值,...}})

      • 接收 this.$router.query.参数名

  • 路由模式

    • hash模式:监听浏览器地址hash值变化,执行相应的js切换网页;

    • history模式:利用history API实现url地址改变,网页内容改变;

    • 它们最明显的区别就是hash会在浏览器地址后面增加#号

16.3 安装路由模块

介绍 | Vue Router (vuejs.org)

使用命令:

html 复制代码
npm install vue-router
# 如果报错,可能是npm版本过高,存在兼容性问题,那么使用如下命令
npm install --legacy-peer-deps vue-router@3.5.2
npm install --legacy-peer-deps vue-router@3.1.3

ps: 今天练习过一次以后,后续在创建项目时可以直接选择路由部分内容,创建出的项目直接就配置好了

16.4 解读 AboutView 和 HomeView 的路由

  • 路由入口/切入点

    • 声明式写标签开始路由

    • 或者是编程式写js开始路由

  • 路由匹配规则/映射表

    • src/router/index.js
  • 展现该页面(路由的出口)

    • <router-view>

16.5 演示:声明式路由 [重点]

需求:新增一个按钮 / 链接,点击实现切换个人信息页面

16.5.1 创建 MyInfo.vue

路由页面建议创建在 **src/views/** 下

components 文件夹下是公共组件

views 文件夹下是 路由组件

html 复制代码
<template>
<div>
  <h1>MyInfo</h1>
  <p>这是个人信息页面</p>
  <img src="../assets/James.png" alt="詹姆斯高斯林">
</div>
</template>

<script>
export default {
  name: "MyInfo",
  data() {
    return {}
  },
  methods: {}
}
</script>

<style scoped>

</style>

16.5.2 设置路由入口

在 App.vue 页面中设置声明式路由

16.5.3 设置映射规则

在 **/src/router/index.js** 文件

填充以下内容

javascript 复制代码
import Vue from 'vue';
import Router from 'vue-router';

import myInfo from "@/views/MyInfo.vue";

Vue.use(Router)//引入路由
export default new Router({
    // 路由规则
    routes: [
        {
            path: '/home',//路由地址
            name: 'Home',
            component: () => import('@/views/Home.vue') // 跳转到这个组件
        },
        {
            path: '/info',//路由地址
            name: 'MyInfo',
            component: myInfo // 跳转到这个组件
        },

    ]

})

注意写完 route 的 index.js 之后 没用 一定找到 main.js 将 router 进行挂载

16.5.4 设置路由填充位 (展现)

App.vue 中设置路由展示位<router-view>

在哪个页面设置展示位<router-view> , 组件就在哪个页面展示出来

16.6 演示:编程式路由 [重点]

刚才演示的是声明式路由,现在使用编程式路由

演示:公告页面切换

16.6.1 创建公告页 Note.vue

javascript 复制代码
<template>
<div>
  <h1>公告页面</h1>
  <ul>
    <li>"东风-5C烧饼 吸引范围覆盖全网"新</li>
    <li>空军航空开放活动最新剧透来了</li>
    <li>公安部公布10起网络违法犯罪案例</li>
  </ul>
</div>
</template>

16.6.2 设置路由入口 (编程式路由)

App.vue 设置标签,绑定事件,事件触发函数,函数内编写代码实现路由

this.$router.push ("/ 路径")

这个函数的作用类似 <router-link to="">

  • 这里写的是this.$router
  • 不是this.$route !!!!!!

16.6.3 src/router/index.js 设置路由规则

16.6.4 bug: 第一次点击跳转没事,再点一次报错

解决:

  • 方式 1: 设置异常捕获
javascript 复制代码
// 在router中的index.js中加上以下代码,注意加在use之前写
const routerPush = VueRouter.prototype.push;
VueRouter.prototype.push = function (location) {
  return routerPush.call(this, location).catch((err) => {});
};

方式 2:

在编程式是路由,即 this.$router.push () 修改成这样

javascript 复制代码
const currentRoute = this.$router.currentRoute;
if (currentRoute.path !== '/note') {
  this.$router.push({
    path:"/note"
  })
}

16.7 路由跳转时参数的传递

16.7.1 声明式路由传参 (路径里面拼数据)

演示 App.vue 中将数据传递给 MyInfo.vue

在路由跳转时路径中传参

javascript 复制代码
      <!--演示声明式路由传参数
        1) 路径中设置参数
        2) 路由映射规则中设置变量承载参数
        3) 可以在组件中通过$route.params获取参数
      -->
      <router-link to="/info/9527" tag="button">Info信息</router-link> |

在路由表的规则中设变量

在 MyInfo.vue 中接参

使用 this.$route.params.xxx 接收参数

html 复制代码
<template>
<div>
  <h1>MyInfo</h1>
  <p>这是个人信息页面</p>
  <!--获取路由参数,此处的id是路由映射规则中设置的变量-->
  <p>当前路由参数id: {{ this.$route.params.id }}</p>
  <p>当前路由参数id: {{ uid }}</p>
  <img src="../assets/James.png" alt="詹姆斯高斯林">
</div>
</template>

<script>
export default {
  name: "MyInfo",
  data() {
    return {
      uid: this.$route.params.id
    }
  },
  methods: {}
}
</script>

<style scoped>

</style>

16.7.2 编程式路由传参

演示 App.vue 中将数据传递给 Note.vue

App.vue 的编程跳转 js 中设置要传递的数据

javascript 复制代码
methods:{
  toNote(){
    this.$router.push({
      path:"/note",
      query: {  //通过query携带数据,最终url /note?username=老王&password
        username:"曹植"
      }
    })
    // 详情看路由官方文档说明https://v3.router.vuejs.org/zh/guide/essentials/navigation.html
  }
}

Note.vue 中接收参数

javascript 复制代码
<template>
<div>
  <h1>网站公告</h1>
  <span>username --> {{username}}</span>
</div>
</template>
<script>
export default {
  name: "Note",
  data:function(){
    return {
      username:this.$route.query.username  
        // 注意是query,因为是按照路径方式发送,注意查看浏览器url
    }
  }
}
</script>

16.7.3 总结两种传参方式

16.8 嵌套路由 [重点]

嵌套路由 | Vue Router (vuejs.org)

多层多级组件嵌套时的路由

需求:在个人中心组件中,再设置三个链接,可以点击切换 [头像 | 家庭信息 | 学校信息]

代码:

创建三个组件页面 Touxiang.vue,Family.vue,School.vue

.... 省略过程
在 MyInfo 组件中设置路由链接发出请求路径,并且设置路由填充位

javascript 复制代码
<p>这是个人信息页面</p>
<hr>
<nav>
  <!-- 导航链接,设置子路由,
  /info/8888 , 是为了匹配路由规则中定义的变量:id
  -->
  <router-link to="/info/8888/school">学校信息</router-link> |
  <router-link to="/info/8888/family">家庭信息</router-link> |
  <router-link to="/info/8888/avatar">头像信息</router-link> |
</nav>
<router-view></router-view>

在 router/index.js 中设置 myinfo 组件的子路由 children

设置路由填充 router-view

如果有路径中有数据的话,子组件一样可以取值

16.9 路由重定向 [了解]

官网资料: 重定向 | Vue Router (vuejs.org)

16.10 路由守卫 (导航守卫) [重要 | 读懂作用]

官方资料: 导航守卫 | Vue Router (vuejs.org)

自己理解:很像 java 拦截器,这里拦截的路由的进程

路由守卫又分为

  • 前置路由守卫 router.beforeEach (to,form,next)
  • 后置路由守卫 router.afterEach
javascript 复制代码
// 创建VueRouter对象,其中配置路由信息
const router = new VueRouter({...})

// 前置路由守卫,即跳转页面前生效,一般都是验证身份/权限
router.beforeEach((to, from, next) => {
    console.log("to,要路由取的目的页面",to)
    console.log("from,从哪个路由出的",from)

    // 相当于放行
    next()
    // 让这次路由去/login路径
    // next("/login")
})

router.afterEach((to, from) => {
    console.log("后置守卫")
})


// 导出该对象
export default router

16.11 路由元信息 [了解]

官方资料: 路由元信息 | Vue Router (vuejs.org)

个人理解:路由元信息,就是在路由设置中,定义了一个数据,在路由过程带上这个数据,做一些逻辑上的处理
定义路由元信息

在路由守卫中取出

相关推荐
奋斗吧程序媛1 小时前
Vue2 + ECharts 实战:动态一个关键词或动态多关键词筛选折线图,告别数据重叠难题
前端·javascript·echarts
San301 小时前
JavaScript 底层探秘:从执行上下文看 `this` 的设计哲学与箭头函数的救赎
javascript·面试·ecmascript 6
黛色正浓1 小时前
【React】极客园案例实践-项目搭建和登录模块
前端·react.js·rust
Healer9181 小时前
js请求的并发控制
前端
是你的小橘呀1 小时前
从 "渣男" 到 "深情男":Promise 如何让 JS 变得代码变得专一又靠谱
前端·javascript·html
mangnel1 小时前
vue3 的预编译模板
vue.js
baozj1 小时前
告别截断与卡顿:我的前端PDF导出优化实践
前端·javascript·vue.js
傲文博一1 小时前
为什么我的产品尽量不用「外置」动态链接库
前端·后端
Healer9181 小时前
Promise限制重复请求
前端