十分钟带你学会 Vue-router

news2024/9/21 0:45:42

安装、配置 Router

Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。

了解路由之前,我们需要先理解一个概念:单页应用。

单页应用

SPA(single page application):单一页面应用程序,只有一个完整的页面;它在加载页面时,不会加载整个页面,而是只更新某个指定的容器中内容。单页面应用(SPA)的核心之一是: 更新视图而不重新请求页面。

路由

这里的路由指的是SPA(单页应用)的路径管理器。

vue的单页面应用将路径和组件映射起来,路由用于设定访问路径,由路径之间的切换,实现组件的切换。

路由模块的本质就是建立起 url 和页面之间的映射关系。

安装、配置 vue-router

安装路由

对于 vue 工程,我们通常用命令行的方式进行安装:

npm install vue-router
// 或者
yarn add vue-router
配置路由

在 main.js 中进行如下路由配置:

// 0. 导入 Vue 和 VueRouter,要调用 Vue.use(VueRouter)
import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

// 1. 定义 (路由) 组件。
// 可以从其他文件 import 进来
import Foo from "./views/Foo.vue";
import Bar from "./views/Bar.vue";

// 2. 定义路由
// 每个路由应该映射一个组件。 其中"component" 可以是
// 通过 Vue.extend() 创建的组件构造器,
// 或者,只是一个组件配置对象。
// 我们晚点再讨论嵌套路由。
const routes = [
  { path: '/foo', component: Foo },
  { path: '/bar', component: Bar }
]

// 3. 创建 router 实例,然后传 `routes` 配置
// 你还可以传别的配置参数, 不过先这么简单着吧。
const router = new VueRouter({
  routes // (缩写) 相当于 routes: routes
})

// 4. 创建和挂载根实例。
// 记得要通过 router 配置参数注入路由,
// 从而让整个应用都有路由功能
const app = new Vue({
  router
}).$mount('#app')

我们知道路由是路径和组件间的映射,所以在上面的代码中,路径 “/foo” 对应的是 Foo 组件,路径 “/bar” 对应的是 Bar 组件。

路由的使用

配置好路由之后,我们来看一下如何在 vue 文件中使用路由实现路径切换引起组件切换。

首先,在 App.vue 中我们使用 <router-link> 组件来导航:

<template>
  <div id="app">
    <h1>Hello App!</h1>
    <p>
      <!-- 使用 router-link 组件来导航. -->
      <!-- 通过传入 `to` 属性指定链接. -->
      <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
      <router-link to="/foo">Go to Foo</router-link>
      <router-link to="/bar">Go to Bar</router-link>
    </p>
    <!-- 路由出口 -->
    <!-- 路由匹配到的组件将渲染在这里 -->
    <!-- App.vue 中的 <router-view></router-view> 是路由的最高级出口 -->
    <router-view></router-view>
  </div>
</template>

页面显示效果:

img

  • 导航标签 <router-link> <router-link> 标签有一个 to 属性,这个属性指定路径(链接),根据我们配置的路由,路径 /foo 对应的组件是 Foo.vue 组件。

  • “插槽”标签 <router-view> <router-view> 标签相当于一个插槽,它所在的位置将渲染路由匹配到的组件。

比如,我们点击 “Go to Foo” 这个导航的时候,<router-view></router-view> 处将展示 Foo.vue 组件。

<router-link> 组件支持用户在具有路由功能的应用中 (点击) 导航。默认渲染成带有正确链接的 <a> 标签。

注意:Foo.vue 和 Bar.vue 文件在 src/views 文件夹里哦。

注意,在代码演示中,我们把 router 的配置从 main.js 中抽出来,放到了 src/router/index.js 中,当 router 的配置内容过多时,我们强烈建议大家这么做。

代码运行结束后,尝试点击“Go to Foo”、“Go to Bar”,查看页面变化。

添加路由

我们知道路由是路径和组件间的映射,而路径所对应的组件将在 <router-view> 标签处渲染。

现在我们给工程添加一些路由,即在 routes 中添加一些路径和组件的映射:

// 1. 将要用到的组件从其他文件 import 进来
import Foo from './views/Foo.vue';
import Bar from './views/Bar.vue';
import User from './views/User.vue';

// 2. 定义路由,每个路由应该映射一个组件
// 添加路径即在 routes 数组中增加新的成员
const routes = [
  { path: '/foo', component: Foo },
  { path: '/bar', component: Bar },
  // 新增一项
  { path: '/user', component: User }
];

// 3. 创建 Router 实例,然后传 `routes` 配置
const router = new VueRouter({
  routes
});
导入组件的写法

导入组件不但可以像上面那样用 import 的方法导入,还可以像下面这样直接在 routes 中写:

const routes = [
  { path: '/foo', component: () => import('./views/Foo.vue') },
  { path: '/bar', component: () => import('./views/Bar.vue') },
  { path: '/user', component: () => import('./views/User.vue') }
];

命名路由

有时候,通过一个名称来标识一个路由显得更方便一些,特别是在链接一个路由,或者是执行一些跳转的时候。我们可以在创建 Router 实例的时候,在 routes 配置中给某个路由设置名称:

// 0. 导入 Album、List、Add、Empty 三个组件

// 1. 定义路由
const routes = [
  { path: '/foo',
    name: 'fooName',
    component: () => import('./views/Foo.vue')
  }
];

通过命名跳转:

<!-- to 的值是一个对象而不是字符串,所以要在 to 前加 : -->
<router-link :to="{name: 'fooName'}">Go to Foo</router-link>

路由布局管理

在实际开发中,工程比较复杂,应用界面通常由多层嵌套的组件组合而成,相应的,路由也会按某种结构对应嵌套的各层组件。

例如用户相册里有头部、功能区,功能区有相册列表和新建相册两个功能,切换路径时,“banner” 没变,只有功能区的组件发生了切换:

img

路径、组件的嵌套结构:

/album/list                           /album/add
+------------------+                  +-----------------+
| Album            |                  | Album           |
| +--------------+ |                  | +-------------+ |
| | List         | |  +------------>  | | Add         | |
| |              | |                  | |             | |
| +--------------+ |                  | +-------------+ |
+------------------+                  +-----------------+
1. 在组件中配合路由使用 <router-view>

App.vue 组件:

<template>
  <div id="app">
    <h1>Hello App!</h1>
    <p>
      <router-link to="/album/list">Go to Album List</router-link>
      |
      <router-link to="/album/add">Go to Album Add</router-link>
    </p>
    <!-- 路由匹配到的组件将渲染在这里 -->
    <!-- 在本例中为 Album.vue 组件 -->
    <router-view></router-view>
  </div>
</template>

Album.vue 组件:

<template>
  <div id="album">
    <div class="banner">banner</div>
    <!-- 路由匹配到的组件将渲染在这里 -->
    <!-- 在本例中为 List.vue 组件或 Add.vue 组件 -->
    <router-view></router-view>
  </div>
</template>

图示如下:img

2. 定义嵌套路由

路由的嵌套关系和组件嵌套关系一致:

// 0. 导入 Album、List、Add 三个组件
const routes = [
  {
    path: '/album',
    component: Album,
    // children 属性可以用来配置下一级路由(子路由)
    children: [
      { path: 'list', component: List },
      { path: 'add', component: Add }
    ]
  }
];

App.vue 中的 <router-view> 对应 routes 里的第一层路由,即:

{ path: '/album', component: Album }

Album.vue 组件中的 <router-view> 对应 routes 里的第二层路由,即:

{ path: 'list', component: List },
{ path: 'add', component: Add }
根路径 /

特别注意,在上例中如果希望用路径 “/album/list” 对应在 Album.vue 中渲染出相册列表,那么子路由中 path 的写法有两种:

path: 'list'
path: '/album/list'

但是 path: '/list' 这样的写法是不对的!因为/ 开头的嵌套路径会被当作根路径,那么 List.vue 这个组件会直接渲染到 App.vue 的 <router-view> 处。

当路径从 “/album/list” 切换到 “/album/add” 时,<router-view> 处渲染的组件也从 List.vue 切换成了 Add.vue。

空的子路由

基于上面的路由配置,如果在路径为 “/album” 时仍想在功能区渲染些什么,那么可以给 “/album” 添加一个空路由:

// 0. 导入 Album、List、Add、Empty 三个组件
const routes = [
  {
    path: '/album',
    component: Album,
    // children 属性可以用来配置下一级路由(子路由)
    children: [
      // 空的子路由
      { path: '', component: Empty },
      { path: 'list', component: List },
      { path: 'add', component: Add }
    ]
  }
];

img

动态路由

之前我们遇到的都是一个路径对应一个组件的情况,但有时我们会遇到多个路径对应一个组件的情况。

比如个人中心对应一个 User 组件,学员登录个人中心时,由于大家的 id 各不相同,所以个人中心的路径可能会不同,像 /user/123/user/456 这样,但其实页面会使用同一个 User 组件来渲染。

这里的 123456 指的是用户 id,也就是在路径中添加的参数。

像这种多个路径都映射到一个组件这种情况就属于动态路由。

动态路由

动态路由即符合某种模式的多个路径映射到同一个组件,请看动态路由的写法:

import User from "./views/User.vue";

const routes = [
  // id 就是路径参数
  { path: '/user/:id', component: User }
]

id 为路径参数,一个“路径参数”前需要使用冒号 : 标记。当 url 匹配到路由中的一个路径时,参数值会被设置到 this.$route.params 里,可以在组件内读取到。

比如 /user/456 匹配的就是 /user/:id,那么这个用户的 id 就是 456,this.$route.params.id 的值就是 456。

现在我们在 User 的模板,输出当前用户的 id:

<template>
  <div>user id: {{ $route.params.id }}</div>
</template>

捕获 404 页面

当用户输入的 url 不属于我们注册的任何一个路由时,我们常需要将页面用 404 NotFound 组件渲染,这里我们可以用通配符(*)来匹配任意路径:

import NotFound from "./views/NotFound.vue";

const routes = [
  {
    // 会匹配所有路径
    path: '*',
    component: NotFound
  }
]

当使用通配符路由时,请确保含有通配符的路由应该放在最后。因为路由的匹配通常是根据注册的顺序匹配的,如果 path: '*' 路由放在最前面,那么所有的页面都会因为先匹配到通配符路由而由 NotFound 组件渲染。

如何读取匹配到的路径值

当使用一个通配符时,$route.params 内会自动添加一个名为 pathMatch 的参数。它包含了 URL 通过通配符被匹配的部分,比如用上面的路由 { path: '*' } 匹配 URL http://localhost:8081/non-existing/file

this.$route.params.pathMatch // '/non-existing/file'

页面跳转

编程式导航

除了使用 <router-link> 创建 a 标签来定义导航链接,我们还可以借助 Router 的实例方法,通过编写代码来实现:

声明式编程式
router.push(…)

注意,因为在 Vue 实例内部,我们可以通过 r o u t e r 访问 R o u t e r 的实例。所以 R o u t e r 的实例方法 p u s h 可以用 ‘ t h i s . router 访问 Router 的实例。所以 Router 的实例方法 push 可以用 `this. router访问Router的实例。所以Router的实例方法push可以用this.router.push(…)` 调用。

router.push 进行页面跳转及参数传递

一、router.push 的参数为字符串路径

router.push 方法的参数可以是一个字符串路径:

router.push('user')
router.push('/user')

下面详细说明上面两种写法的不同,主要是跳转后 url 的变化不同:

原 urllocalhost:8080localhost:8080/home
router.push(‘user’) 跳转后的 urllocalhost:8080/userlocalhost:8080/home/user
router.push(‘/user’) 跳转后的 urllocalhost:8080/userlocalhost:8080/user

因为 / 意味着匹配根路由,所以 '/user' 这样的写法不管原路径 localhost:8080/?? 中的 ?? 是什么,跳转后 url 都会变为 localhost:8080/user

二、router.push 的参数为描述地址的对象

router.push 方法的参数可以是一个描述地址的对象:

// 对象
// 这种写法和字符串类型的参数一样
router.push({ path: 'home' })

// 命名的路由
router.push({ name: 'user', params: { userId: '123' }})

// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})

只提供 path 值的参数和字符串类型的参数是一样的。这里就不再说了。我们主要看一下后两种写法。

  1. { name: 'user', params: { userId: '123' }}
  • 对应的命名路由为: { path:'user/:userId', name:'user' }

  • 跳转后 url:localhost:8080/user/123

  • 取参数:$route.params.userId

  1. { path: 'register', query: { plan: 'private' }}
  • 对应的路由为: { path:'register' }
  • 跳转后 url:localhost:8080/register?plan=private
  • 取参数:$route.query.plan

小结一下参数传递的对应规则:

  • name 对应 params,路径形式:user/123;
  • path 对应 query,路径形式:user?id=123;

如果使用 path 进行页面跳转的时候,写 params 进行传参会被忽略:

// params 会被忽
router.push({ path: 'user', params: { userId: '123' }})

可以换成下面的写法:

router.push({ path: 'user/123'})

同样的规则也适用于 router-link 组件的 to 属性。

页面跳转后如何获取参数

之前我们说可以通过 $route 访问当前路由,现在我们看看 $route 到底能给我们提供些什么信息。

现在我们访问本地启动的工程的一个地址 http://localhost:8080/user/123?name=userName#abc,对应的 $route 如下:

// $route
{
  // 路由名称
  name: "user",
  meta: {},
  // 路由path
  path: "/user/123",
  // 网页位置指定标识符
  hash: "#abc",
  // window.location.search
  query: {name: "userName"},
  // 路径参数 user/:userId
  params: {userId: "123"},
  fullPath: "/user/123?name=userName#abc"
}

页面跳转后获取参数可以很方便的通过 $route.query$route.params$route.hash获取

重定向和别名

上节课作业中我们开发了优课达官网的首页、全部课程页面和课程详情页,他们的路由关系是:

首页全部课程页课程详情页
/layout/home/layout/courseall/layout/coursedetail/:courseId

可以看到这三个路径中都有 layout,但实际我们遇到的情况是,官网首页一般是 https://www.xxx.com/。这时候我们就可以使用路由功能中的别名和重定向把 /layout/home 变成 /

首先我们使用别名。

别名

别名,顾名思义就是两个名字指向同一个路由:

const routes: [
  // 定义 alias 属性
  { path: '/a', alias: '/b', component: A }
];

当访问 /a 时,渲染的是 A;当访问 /b 时,就像访问 /a 一样,渲染的也是 A。

我们的目的是把 /layout/home 变成 /,所以要把 layout 去掉:

const routes: [
  {
    path: '/layout',
    // 别名定为 /
    alias: '/',
    component: ()=> import('@/pages/nest/Layout.vue'),
    children: [
      { path: 'home', component: Home },
      { path: 'courseall', component: CourseAll },
      { path: 'coursedetail/:courseId', component: CourseDetail }
    ]
  }
];

这时候 /layout/home 变成了 /home

img

接下来我们要用重定向把 /home 变成 /

路由重定向

先了解重定向的意思。

若路由 /a 重定向到 /b,即访问 /a 时, url 会自动跳到 /b,然后匹配路由 /b

const routes: [
  // 定义 redirect 属性,将 /a 重定向到 /b
  { path: '/a', redirect: '/b' }
]

现在我们希望 / 重定向到 /home,这样访问 / 时会自动跳到 /home

const routes: [
  {
    path: '/layout',
    alias: '/',
    // 重定向到 /home
    redirect: '/home',
    component: ()=> import('@/pages/nest/Layout.vue'),
    children: [
      { path: 'home', component: Home },
      { path: 'courseall', component: CourseAll },
      { path: 'coursedetail/:courseId', component: CourseDetail }
    ]
  }
];

现在的路由是这样的:

首页全部课程页课程详情页
/layout/home/layout/courseall/layout/coursedetail/:courseId
//courseall/coursedetail/:courseId

监听路由

有时我们需要对路由的变化进行监听,比如优课达官网展示所有课程的页面:

img

当页面头部的标签切换时,路径也会发生变化,我们需要监听路由变化来改变标签的样式,或者在页面中加载对应的内容。

那么怎么监听路由呢?

监听路由 $route 的变化

监听路由变化我们需要用到两个知识:vue 中的 watch 和 $route

watch 即之前讲过的数据变化监听,$route 即当前路由。

路由监听写法如下:

watch: {
  $route(to,from){
    console.log(to, from);
  }
}

// 或者
watch: {
  $route: {
    handler: function(to,from) {
      console.log(to,from);
    },
    // 深度观察监听
    deep: true
  }
},

to 是变化后的路由,from 是变化前的路由。一般我们用第一种写法就可以了。

监听路由的使用

现在我们来实现上面 gif 的例子,根据路径参数定位点击的标签:

1. 基础样式

tab 的样式分两种,被点击的和未被点击的:

img

被点击的 tab 会多个类名 “active”。

定义 tab 点击事件
<script>
export default {
  methods: {
    // 点击 tab 时会执行 changeTab 方法
    changeTab(type) {
      // 使用 Router 实例方法改变路径参数
      this.$router.push({ query: { type: type } });
    }
  }
};
</script>
3. 监听路由变化,更新 tab 样式
<script>
export default {
  watch: {
    $route(to, from) {
      // 路由变化了就执行更新样式的方法
      this.updateTab();
      console.log(to, from);
    }
  },
  methods: {
    changeTab(type) {
      this.$router.push({ query: { type: type } });
    },
    // 更新样式的方法
    updateTab() {
      this.tabList.map(menu => {
        menu.active = menu.type === this.$route.query.type;
      });
    }
  }
};
</script>
4. 处理特殊情况

如果页面路径一开始没有路径参数 type,那我们默认选择第一个 tab,如果页面路径一开始就有路径参数,那么需要马上更新 tab 样式:

<script>
export default {
  methods: {
    // ...
    updateTab() {
      if (!this.$route.query.type) {
        return;
      }
      this.tabList.map(tab => {
        tab.active = tab.type === this.$route.query.type;
      })
    }
  }
};
</script>

网络请求 async 与 await

本章我们会学习如何在 vue 中请求远程数据。

在 JavaScript 中我们曾学过用 fetch 请求数据,比如一个显示优课达公司信息的 API

https://www.done.kim/api/m/f4-11-1-1

把这个 URL 贴到浏览器,可以看到查询返回结果为:

img

文字内容如下:

{
  "company": "优课达",
  "slogan": "学的比别人好一点"
}

fetch 请求数据的代码如下:

fetch(
  'https://www.done.kim/api/m/f4-11-1-1'
)
  .then(function(response) {
    return response.json();
  })
  .then(function(myJson) {
    console.log(myJson);
  });

由于 fetch 返回的是一个 Promise 对象,所以我们在请求数据的时候用了 then 采用平铺式回调的方式,允许我们在数据返回之后再对数据进行 response.json() 处理。

这里就有一个问题,因为 Promise 对象的一个特点是无等待,所以想对返回的数据进行操作,就必须在 then 里处理。假设一个业务,分多个步骤完成,每个步骤都是异步的,而且依赖于上一个步骤的结果。那么 then 链就会很长

现在我们来学习异步编程终级解决方案 —— asyncawait

“异步” async

async 是“异步”的简写,用于申明一个异步 function,而这个 async 函数返回的是一个 Promise 对象。

async function asyncFn() {
  return {
    "company": "优课达",
    "slogan": "学的比别人好一点"
  };
}

const result = asyncFn();
console.log(result);

既然 async 返回的是一个 Promise 对象,那和普通的 fetch 方法有什么区别?着关键点就在于 await 关键字。

“等待异步” await

await 用于等待一个异步方法执行的完成,它会阻塞后面的代码,等着 Promise 对象 resolve *,然后得到 resolve 的值,作为 await 表达式的运算结果:

async function getAsyncFn() {
  const result = await asyncFn();
  console.log(result);
}

getAsyncFn();

要注意,await 只能出现在 async 函数中,如果用在普通函数里,就会报错,所以上面我们又定义了一个 async 函数 getAsyncFn

如果大家想要了解更多关于 Promise 对象的知识,可以点击查看这个文档

多个请求并发执行 Promise.all

如果要完成多个请求并发执行,可以使用 Promise.all

async function asyncFn1() {
  return "优课达";
}

async function asyncFn2() {
  return "学的比别人好一点";
}

async function getAsyncFn() {
  const result = await Promise.all([asyncFn1(), asyncFn2()]);
  console.log(result);
}

getAsyncFn();
在 vue 中运用 async 和 await 请求数据

之前我们在开发“全部课程页”和“课程详情页”时,课程数据是直接写在 data 里的,现在我们将运用 async 和 await 请求数据,完成后页面中的课程信息均为动态获取的:

img

已知我们 mock 的数据返回格式如下,其中的 data 是我们实际需要的数据:

{
  data: {...},
  isSuccess: true
}

在全部课程页 CourseAll.vue 组件里获取所有课程:

<script>
export default {
  data: function() {
    return {
      courseList: []
    };
  },
  async mounted() {
    // 在生命周期 mounted 中调用获取课程信息的方法
    await this.queryAllCourse();
  },
  methods: {
    // 在 methods 对象中定义一个 async 异步函数
    async queryAllCourse() {
      // 在 fetch 中传入接口地址
      const res = await fetch('https://www.done.kim/api/m/queryallcourse');
      // 将文本体解析为 JSON 格式的promise对象
      const myJson = await res.json();
      // 获取返回数据中的 data 赋值给 courseList
      this.courseList = myJson.data;
    }
  }
}
</script>
给 api 传参数

在课程详情页 CourseDetail.vue 组件,我们需要根据课程 id 获取课程信息,这时需要给获取课程信息的 api 传课程 id:

<script>
export default {
  data: function() {
    return {
      course: []
    };
  },
  async mounted() {
    await this.getCourse();
  },
  methods: {
    async getCourse() {
      // 从路径中获取课程 id
      const courseId = this.$route.params.courseId
      // 在接口地址后传入参数 id
      const res = await fetch('https://www.done.kim/api/m/getcourse?id=' + courseId);
      const myJson = await res.json();
      this.course = myJson.data;
    }
  }
}
</script>

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

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

相关文章

【微信小程序实战教程】之微信小程序中的 JavaScript

微信小程序中的 JavaScript 微信小程序的业务逻辑都是通过JavaScript语言来实现的&#xff0c;本章我们将详细的讲解JavaScript的基本概念&#xff0c;以及在小程序中如何使用JavaScript语言。JavaScript是一种轻量的、解释型的、面向对象的头等函数语言&#xff0c;是一种动态…

uniapp用自带的canvas做画板签字

如下图移动端经常需要做此功能,用户签字。用户填表啥的。 先用touch进行监听手指的触摸事件 获取所点击的坐标位置。 这里有很多要注意的地方。 初始化 uniapp里的canvas与原生的canvas有区别,渲染之后会多很多莫名其妙的div节点,并且还有个div直接就把原生的canvas覆盖…

仿真入门必看:怎么用CST软件自带宏提取材料的DK,Df值

我们知道如果在CST中要做精确的仿真&#xff0c;进行仿真测试对比&#xff0c;其中第一步就是要搞清楚仿真模型的参数&#xff0c;如果输入数据不对&#xff0c;那也避免不了垃圾进垃圾出的原则。和仿真相关的数据很多&#xff0c;其中PCB板的介质参数Dk, Df就是介电常数的实部…

吓傻!自有品牌社交电商靠AI 智能名片商城小程序逆天改命!

摘要&#xff1a;本文深入探讨了自有品牌型社交电商的发展历程、显著特点以及未来趋势&#xff0c;特别以微商品牌为典型案例进行了详细剖析。同时&#xff0c;重点阐述了在数字化时代的大背景下&#xff0c;自有品牌型社交电商如何通过与 AI 智能名片商城小程序的有机融合&…

VueRouter 相关信息

VueRouter 是Vue.js官方路由插件&#xff0c;与Vue.js深度集成&#xff0c;用于构建单页面应用。构建的单页面是基于路由和组件&#xff0c;路由设定访问路径&#xff0c;将路径与组件进行映射。VueRouter有两中模式 &#xff1a;hash 和 history &#xff0c;默认是hash模式。…

scikit-learn 算法选择决策树

介绍 下图帮助我们在使用 scikit-learn 库时选择合适的算法&#xff0c;可作为参考。

leetCode - - - 数组

1.移动0&#xff08;leetcode283&#xff09; 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。 class Solution {public void moveZeroes(i…

邮件API的API文档和技术支持资源如何获取?

邮件API如何集成到现有系统中&#xff1f;如何选邮件API服务&#xff1f; 对于开发者来说&#xff0c;理解和获取邮件API的API文档和技术支持资源至关重要。AokSend将详细介绍如何高效获取这些资源&#xff0c;帮助开发者顺利集成邮件API&#xff0c;并在项目中发挥其最大功效…

音频剪辑软件哪个好用?轻松处理音频的6款软件

在日常生活中&#xff0c;我们常常需要对音频进行编辑&#xff0c;无论是为了制作个性化的音乐铃声&#xff0c;还是剪辑重要的录音&#xff0c;或是创作音频片段。 面对这些音频剪辑的挑战&#xff0c;一款好用的在线音频剪辑免费版软件就显得尤为重要。 下面为大家推荐6个好…

打音游(补全程序)

首先最外层循环枚举的是总共的得分次数&#xff0c;包括x1,x,x/2&#xff0c;那么n-i就是没得分的情况。 里层循环j代表得x/2的情况&#xff0c;要么没有&#xff0c;要么最多1次&#xff0c;如果两次会变成x那么之前的循环已经枚举过了。 lower代表的是得x1分的下限那就是总…

六通道CAN(FD) 集线器

一 、功能概述 1.1 设备简介 CANFD 完全向下兼容 CAN&#xff0c; 以下统称 CAN(FD) 。本产品是CAN(FD)集线器&#xff0c; 支持名义 波特率 5k-1M&#xff0c; 数据波特率5k-5M&#xff0c; 开启位速率转换最低数据波特率100k。 支持每路单独设置接收帧类型&#xff08;软…

Apache Camel Karavan -理解一

Apache Camel 开始接触是在ETL数据&#xff0c;数据处理成为了现代企业必须面对的一个挑战。在数据处理中&#xff0c;etl&#xff08;提取-转换-加载&#xff09;的概念被广泛采用&#xff0c;其中提取指从源数据中收集数据&#xff0c;转换指将数据与所需数据配对&#xff0c…

uniapp创建一个新项目并导入uview-plus框架

近年来&#xff0c;随着技术的发展&#xff0c;人们越来越意识到跨平台和统一的重要性。对于同一款应用来说&#xff0c;一般都会有移动端、PC端、甚至小程序端。这是由于设备的不同&#xff0c;我们必须要做很多的客户端来满足不同的用户需求。但是由于硬件设施的不同&#xf…

谷粒商城实战笔记-131~132-商城业务-商品上架-构造sku检索属性和库存查询

文章目录 一&#xff0c;131-商城业务-商品上架-构造sku检索属性1&#xff0c;开发目标2&#xff0c;详细设计2.1&#xff0c;根据spu_id获取所有的规格参数2.2&#xff0c;根据上一步中查询结果进一步确认是否可搜索2.3&#xff0c;将可搜索的属性封装到Java模型中 二&#xf…

MySQL命令行工具的配置和使用

一、Windows启动命令行工具 1.打开Windows的开始菜单&#xff0c;找到安装好的MySQL&#xff0c;点击MySQL 8.0 Command Line Client - Unicode&#xff0c;这个带有Unicode的&#xff0c;是支持中文的&#xff0c;允许在命令行中敲中文。 然后从打开的窗口输入安装MySQL时设置…

【探索Linux】P.45(NAT技术 | NAPT技术)

阅读导航 引言一、NAT技术1. NAT技术引入2. NAT技术简介&#xff08;1&#xff09;基本原理&#xff08;2&#xff09;主要类型&#xff08;3&#xff09;技术优点&#xff08;4&#xff09;技术挑战&#xff08;5&#xff09;应用场景 二、NAPT温馨提示 引言 在上一篇文章中&…

NC 没有重复项数字的全排列

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 描述 给出一组数字…

【网络安全入门】学习网络安全必须知道的100 个网络基础知识_网络安全知识入门基础

什么是链接? 链接是指两个设备之间的连接。它包括用于一个设备能够与另一个设备通信的电缆类型和协议。 2 OSI 参考模型的层次是什么? 有 7 个 OSI 层&#xff1a;物理层&#xff0c;数据链路层&#xff0c;网络层&#xff0c;传输层&#xff0c;会话层&#xff0c;表示层…

接口测试之python+rquest+unittest分层自动化框架

接口测试之接口po框架 一、新建一个项目 接口自动化框架设计实战&#xff1a; 第一包&#xff1a;config 案例&#xff1a; #登录接口 dl_url http://cms.duoceshi.cn/cms/manage/loginJump.do dl_d {userAccount: admin, loginPwd: 123456} dl_h "Content-Type:app…

IP地址申请SSL证书的详细流程(ip地址实现https访问)

IP地址SSL证书是一种特殊的SSL/TLS证书&#xff0c;它被设计用于保护直接通过IP地址访问的服务。这种证书可以为IP地址提供HTTPS加密和身份验证。 IP地址申请SSL证书的详细流程如下&#xff1a; IP SSL证书-JoySSLhttps://www.joyssl.com/certificate/select/ip_certificate.…