【前端Vue】社交信息头条项目完整笔记第2篇:二、登录注册,准备【附代码文档】

社交媒体-信息头条项目完整开发笔记完整教程(附代码资料)主要内容讲述:一、项目初始化使用 Vue CLI 创建项目,加入 Git 版本管理,调整初始目录结构,导入图标素材,引入 Vant 组件库,移动端 REM 适配,关于 , 配置文件,封装请求模块。十、用户关注 & 粉丝。十一、我的收藏/历史。十二、编辑用户资料创建组件并配置路由,页面布局,展示用户信息,修改昵称,修改性别,修改生日,修改头像。二、登录注册准备,实现基本登录功能,登录状态提示,表单验证,验证码处理,处理用户 Token,优化封装本地存储操作模块,关于 Token 过期问题。三、个人中心TabBar 处理,页面布局,处理已登录和未登录的页面展示,用户退出,展示登录用户信息,优化设置 Token。四、首页—文章列表页面布局,频道列表,文章列表,文章列表项。五、首页—频道编辑处理页面弹出层,创建频道编辑组件,页面布局,展示我的频道,展示推荐频道列表,添加频道,编辑频道,频道数据持久化,正确的获取首页频道列表数据。六、文章搜索创建组件并配置路由,页面布局,处理页面显示状态,搜索联想建议,搜索结果,搜索历史记录。七、文章详情创建组件并配置路由,页面布局,关于后端返回数据中的大数字问题,展示文章详情,处理内容加载状态,关于文章正文的样式,图片点击预览,关注用户,文章收藏,文章点赞。八、文章评论展示文章评论列表,评论点赞,发布文章评论,评论回复。九、用户页面创建组件并配置路由,页面布局,展示用户信息,用户关注,展示用户文章列表。

全套笔记资料代码移步: 前往gitee仓库查看

感兴趣的小伙伴可以自取哦,欢迎大家点赞转发~


全套教程部分目录:


部分文件图片:

二、登录注册

目标

  • 能实现登录页面的布局
  • 能实现基本登录功能
  • 能掌握 Vant 中 Toast 提示组件的使用
  • 能理解 API 请求模块的封装
  • 能理解发送验证码的实现思路
  • 能理解 Vant Form 实现表单验证的使用
image-20200228161041266

准备

创建组件并配置路由

1、创建 src/views/login/index.vue 并写入以下内容

<template><div class="login-container">登录页面</div>
</template><script>
export default {name: 'LoginPage',components: {},props: {},data () {return {}},computed: {},watch: {},created () {},mounted () {},methods: {}
}
</script><style scoped lang="less"></style>

2、然后在 src/router/index.js 中配置登录页的路由表

{path: '/login',name: 'login',component: () => import('@/views/login')
}

最后,访问 /login 查看是否能访问到登录页面。

image-20200229115109026

布局结构

这里主要使用到三个 Vant 组件:

  • [NavBar 导航栏](
  • [Form 表单](
    • [Field 输入框](
    • [Button 按钮](

一个经验:使用组件库中的现有组件快速布局,再慢慢调整细节,效率更高(刚开始可能会感觉有点麻烦,越用越熟,慢慢的就有了自己的思想)。

布局样式

写样式的原则:将公共样式写到全局(src/styles/index.less),将局部样式写到组件内部。

1、src/styles/index.less

body {background-color: #f5f7f9;
}.page-nav-bar {background-color: #3296fa;.van-nav-bar__title {color: #fff;}
}

2、src/views/login/index.vue

<template><div class="login-container"><!-- 导航栏 --><van-nav-bar class="page-nav-bar" title="登录" /><!-- /导航栏 --><!-- 登录表单 --><van-form @submit="onSubmit"><van-fieldname="用户名"placeholder="请输入手机号"><i slot="left-icon" class="toutiao toutiao-shouji"></i></van-field><van-fieldtype="password"name="验证码"placeholder="请输入验证码"><i slot="left-icon" class="toutiao toutiao-yanzhengma"></i><template #button><van-button class="send-sms-btn" round size="small" type="default">发送验证码</van-button></template></van-field><div class="login-btn-wrap"><van-button class="login-btn" block type="info" native-type="submit">登录</van-button></div></van-form><!-- /登录表单 --></div>
</template><script>
export default {name: 'LoginIndex',components: {},props: {},data () {return {}},computed: {},watch: {},created () {},mounted () {},methods: {onSubmit (values) {console.log('submit', values)}}
}
</script><style scoped lang="less">
.login-container {.toutiao {font-size: 37px;}.send-sms-btn {width: 152px;height: 46px;line-height: 46px;background-color: #ededed;font-size: 22px;color: #666;}.login-btn-wrap {padding: 53px 33px;.login-btn {background-color: #6db4fb;border: none;}}
}
</style>

实现基本登录功能

思路:

  • 注册点击登录的事件
  • 获取表单数据(根据接口要求使用 v-model 绑定)
  • 表单验证
  • 发请求提交
  • 根据请求结果做下一步处理

一、根据接口要求绑定获取表单数据

1、在登录页面组件的实例选项 data 中添加 user 数据字段

...
data () {return {user: {mobile: '',code: ''}}
}

2、在表单中使用 v-model 绑定对应数据

<!-- van-cell-group 仅仅是提供了一个上下外边框,能看到包裹的区域 -->
<van-cell-group><van-fieldv-model="user.mobile"requiredclearablelabel="手机号"placeholder="请输入手机号"/><van-fieldv-model="user.code"type="number"label="验证码"placeholder="请输入验证码"required/>
</van-cell-group>

最后测试。

一个小技巧:使用 VueDevtools 调试工具查看是否绑定成功。

二、请求登录

1、创建 src/api/user.js 封装请求方法

/*** 用户相关的请求模块*/
import request from "@/utils/request"/*** 用户登录*/
export const login = data => {return request({method: 'POST',url: '/app/v1_0/authorizations',data})
}

2、给登录按钮注册点击事件

async onLogin () {try {const res = await login(this.user)console.log('登录成功', res)} catch (err) {if (err.response.status === 400) {console.log('登录失败', err)}}
}

最后测试。

登录状态提示

Vant 中内置了[Toast 轻提示](

// 简单文字提示
Toast("提示内容");// loading 转圈圈提示
Toast.loading({duration: 0, // 持续展示 toastmessage: "加载中...",forbidClick: true // 是否禁止背景点击
});// 成功提示
Ttoast.success("成功文案");// 失败提示
Toast.fail("失败文案");

提示:在组件中可以直接通过 this.$toast 调用。

另外需要注意的是:Toast 默认采用单例模式,即同一时间只会存在一个 Toast,如果需要在同一时间弹出多个 Toast,可以参考下面的示例

Toast.allowMultiple();const toast1 = Toast('第一个 Toast');
const toast2 = Toast.success('第二个 Toast');toast1.clear();
toast2.clear();

下面是为我们的登录功能增加 toast 交互提示。

async onLogin () {// 开始转圈圈this.$toast.loading({duration: 0, // 持续时间,0表示持续展示不停止forbidClick: true, // 是否禁止背景点击message: '登录中...' // 提示消息})try {const res = await request({method: 'POST',url: '/app/v1_0/authorizations',data: this.user})console.log('登录成功', res)// 提示 success 或者 fail 的时候,会先把其它的 toast 先清除this.$toast.success('登录成功')} catch (err) {console.log('登录失败', err)this.$toast.fail('登录失败,手机号或验证码错误')}
}

假如请求非常快的话就看不到 loading 效果了,这里可以手动将调试工具中的网络设置为慢速网络。

测试结束,再把网络设置恢复为 Online 正常网络。

表单验证

参考文档:[Form 表单验证](

<template><div class="login-container"><!-- 导航栏 --><van-nav-bar class="page-nav-bar" title="登录" /><!-- /导航栏 --><!-- 登录表单 --><!--表单验证:1、给 van-field 组件配置 rules 验证规则参考文档:2、当表单提交的时候会自动触发表单验证如果验证通过,会触发 submit 事件如果验证失败,不会触发 submit--><van-form @submit="onSubmit"><van-fieldv-model="user.mobile"name="手机号"placeholder="请输入手机号":rules="userFormRules.mobile"type="number"maxlength="11"><i slot="left-icon" class="toutiao toutiao-shouji"></i></van-field><van-fieldv-model="user.code"name="验证码"placeholder="请输入验证码":rules="userFormRules.code"type="number"maxlength="6"><i slot="left-icon" class="toutiao toutiao-yanzhengma"></i><template #button><van-button class="send-sms-btn" round size="small" type="default">发送验证码</van-button></template></van-field><div class="login-btn-wrap"><van-button class="login-btn" block type="info" native-type="submit">登录</van-button></div></van-form><!-- /登录表单 --></div>
</template><script>
import { login } from '@/api/user'export default {name: 'LoginIndex',components: {},props: {},data () {return {user: {mobile: '', // 手机号code: '' // 验证码},userFormRules: {mobile: [{required: true,message: '手机号不能为空'}, {pattern: /^1[3|5|7|8]\d{9}$/,message: '手机号格式错误'}],code: [{required: true,message: '验证码不能为空'}, {pattern: /^\d{6}$/,message: '验证码格式错误'}]}}},computed: {},watch: {},created () {},mounted () {},methods: {async onSubmit () {// 1. 获取表单数据const user = this.user// TODO: 2. 表单验证// 3. 提交表单请求登录this.$toast.loading({message: '登录中...',forbidClick: true, // 禁用背景点击duration: 0 // 持续时间,默认 2000,0 表示持续展示不关闭})try {const res = await login(user)console.log('登录成功', res)this.$toast.success('登录成功')} catch (err) {if (err.response.status === 400) {this.$toast.fail('手机号或验证码错误')} else {this.$toast.fail('登录失败,请稍后重试')}}// 4. 根据请求响应结果处理后续操作}}
}
</script><style scoped lang="less">
.login-container {.toutiao {font-size: 37px;}.send-sms-btn {width: 152px;height: 46px;line-height: 46px;background-color: #ededed;font-size: 22px;color: #666;}.login-btn-wrap {padding: 53px 33px;.login-btn {background-color: #6db4fb;border: none;}}
}
</style>

验证码处理

验证手机号

async onSendSms () {console.log('onSendSms')// 1. 校验手机号try {await this.$refs.loginForm.validate('mobile')} catch (err) {return console.log('验证失败', err)}// 2. 验证通过,显示倒计时// 3. 请求发送验证码
}

使用倒计时组件

1、在 data 中添加数据用来控制倒计时的显示和隐藏

data () {return {...isCountDownShow: false}
}

2、使用倒计时组件

<van-fieldv-model="user.code"placeholder="请输入验证码"
><i class="icon icon-mima" slot="left-icon"></i><van-count-downv-if="isCountDownShow"slot="button":time="1000 * 5"format="ss s"@finish="isCountDownShow = false"/><van-buttonv-elseslot="button"size="small"type="primary"round@click="onSendSmsCode">发送验证码</van-button>
</van-field>

发送验证码

1、在 api/user.js 中添加封装数据接口

export const getSmsCode = mobile => {return request({method: 'GET',url: `/app/v1_0/sms/codes/${mobile}`})
}

2、给发送验证码按钮注册点击事件

3、发送处理

async onSendSms () {// 1. 校验手机号try {await this.$refs.loginForm.validate('mobile')} catch (err) {return console.log('验证失败', err)}// 2. 验证通过,显示倒计时this.isCountDownShow = true// 3. 请求发送验证码try {await sendSms(this.user.mobile)this.$toast('发送成功')} catch (err) {// 发送失败,关闭倒计时this.isCountDownShow = falseif (err.response.status === 429) {this.$toast('发送太频繁了,请稍后重试')} else {this.$toast('发送失败,请稍后重试')}}
}

处理用户 Token

image-20200329121650635

Token 是用户登录成功之后服务端返回的一个身份令牌,在项目中的多个业务中需要使用到:

  • 访问需要授权的 API 接口
  • 校验页面的访问权限

但是我们只有在第一次用户登录成功之后才能拿到 Token。

所以为了能在其它模块中获取到 Token 数据,我们需要把它存储到一个公共的位置,方便随时取用。

往哪儿存?

  • 本地存储
    • 获取麻烦
    • 数据不是响应式
  • Vuex 容器(推荐)
    • 获取方便
    • 响应式的

使用容器存储 Token 的思路:

image-20200109192157006

  • 登录成功,将 Token 存储到 Vuex 容器中
    • 获取方便
    • 响应式
  • 为了持久化,还需要把 Token 放到本地存储
    • 持久化

下面是具体实现。

1、在 src/store/index.js

import Vue from 'vue'
import Vuex from 'vuex'Vue.use(Vuex)export default new Vuex.Store({state: {// 用户的登录状态信息user: JSON.parse(window.localStorage.getItem('TOUTIAO_USER'))// user: null},mutations: {setUser (state, user) {state.user = userwindow.localStorage.setItem('TOUTIAO_USER', JSON.stringify(user))}},actions: {},modules: {}
})

2、登录成功以后将后端返回的 token 相关数据存储到容器中

async onLogin () {// const loginToast = this.$toast.loading({this.$toast.loading({duration: 0, // 持续时间,0表示持续展示不停止forbidClick: true, // 是否禁止背景点击message: '登录中...' // 提示消息})try {const res = await login(this.user)// res.data.data => { token: 'xxx', refresh_token: 'xxx' }
+    this.$store.commit('setUser', res.data.data)// 提示 success 或者 fail 的时候,会先把其它的 toast 先清除this.$toast.success('登录成功')} catch (err) {console.log('登录失败', err)this.$toast.fail('登录失败,手机号或验证码错误')}// 停止 loading,它会把当前页面中所有的 toast 都给清除// loginToast.clear()
}

优化封装本地存储操作模块

创建 src/utils/storage.js 模块。

export const getItem = name => {const data = window.localStorage.getItem(name)try {return JSON.parse(data)} catch (err) {return data}
}export const setItem = (name, value) => {if (typeof value === 'object') {value = JSON.stringify(value)}window.localStorage.setItem(name, value)
}export const removeItem = name => {window.localStorage.removeItem(name)
}

关于 Token 过期问题

登录成功之后后端会返回两个 Token:

  • token:访问令牌,有效期2小时
  • refresh_token:刷新令牌,有效期14天,用于访问令牌过期之后重新获取新的访问令牌

我们的项目接口中设定的 Token 有效期是 2 小时,超过有效期服务端会返回 401 表示 Token 无效或过期了。

为什么过期时间这么短?

  • 为了安全,例如 Token 被别人盗用

过期了怎么办?

  • 让用户重新登录,用户体验太差了
  • 使用 refresh_token 解决 token 过期

如何使用 refresh_token 解决 token 过期?

到课程的后面我们开发的业务功能丰富起来之后,再给大家讲解 Token 过期处理。

大家需要注意的是在学习测试的时候如果收到 401 响应码,请重新登录再测试

img

概述:服务器生成token的过程中,会有两个时间,一个是token失效时间,一个是token刷新时间,刷新时间肯定比失效时间长,当用户的 token 过期时,你可以拿着过期的token去换取新的token,来保持用户的登陆状态,当然你这个过期token的过期时间必须在刷新时间之内,如果超出了刷新时间,那么返回的依旧是 401。

处理流程:

  1. 在axios的拦截器中加入token刷新逻辑
  2. 当用户token过期时,去向服务器请求新的 token
  3. 把旧的token替换为新的token
  4. 然后继续用户当前的请求

在请求的响应拦截器中统一处理 token 过期:

/*** 封装 axios 请求模块*/
import axios from "axios";
import jsonBig from "json-bigint";
import store from "@/store";
import router from "@/router";// axios.create 方法:复制一个 axios
const request = axios.create({baseURL: " // 基础路径
});/*** 配置处理后端返回数据中超出 js 安全整数范围问题*/
request.defaults.transformResponse = [function(data) {try {return jsonBig.parse(data);} catch (err) {return {};}}
];// 请求拦截器
request.interceptors.request.use(function(config) {const user = store.state.user;if (user) {config.headers.Authorization = `Bearer ${user.token}`;}// Do something before request is sentreturn config;},function(error) {// Do something with request errorreturn Promise.reject(error);}
);// 响应拦截器
request.interceptors.response.use(// 响应成功进入第1个函数// 该函数的参数是响应对象function(response) {// Any status code that lie within the range of 2xx cause this function to trigger// Do something with response datareturn response;},// 响应失败进入第2个函数,该函数的参数是错误对象async function(error) {// Any status codes that falls outside the range of 2xx cause this function to trigger// Do something with response error// 如果响应码是 401 ,则请求获取新的 token// 响应拦截器中的 error 就是那个响应的错误对象console.dir(error);if (error.response && error.response.status === 401) {// 校验是否有 refresh_tokenconst user = store.state.user;if (!user || !user.refresh_token) {router.push("/login");// 代码不要往后执行了return;}// 如果有refresh_token,则请求获取新的 tokentry {const res = await axios({method: "PUT",url: "headers: {Authorization: `Bearer ${user.refresh_token}`}});// 如果获取成功,则把新的 token 更新到容器中console.log("刷新 token  成功", res);store.commit("setUser", {token: res.data.data.token, // 最新获取的可用 tokenrefresh_token: user.refresh_token // 还是原来的 refresh_token});// 把之前失败的用户请求继续发出去// config 是一个对象,其中包含本次失败请求相关的那些配置信息,例如 url、method 都有// return 把 request 的请求结果继续返回给发请求的具体位置return request(error.config);} catch (err) {// 如果获取失败,直接跳转 登录页console.log("请求刷线 token 失败", err);router.push("/login");}}return Promise.reject(error);}
);export default request;

未完待续, 同学们请等待下一期

全套笔记资料代码移步: 前往gitee仓库查看

感兴趣的小伙伴可以自取哦,欢迎大家点赞转发~

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

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

相关文章

【自动化测试教程】Java+Selenium自动化测试环境搭建

本主要介绍以Java为基础&#xff0c;搭建Selenium自动化测试环境&#xff0c;并且实现代码编写的过程。 1.Selenium介绍 Selenium 1.0 包含 core、IDE、RC、grid 四部分&#xff0c;selenium 2.0 则是在两位大牛偶遇相互沟通决定把面向对象结构化&#xff08;OOPP&#xff09…

ADC12123

转换时间的参数一般不太敏感&#xff0c;一般AD转换都很快&#xff0c;如果不需要非常高速的转换频率&#xff0c;那转换时间就可以忽略了。AD转换的时候需要花小段时间&#xff0c; 在AD转换的步骤中&#xff0c;有4步分别是采样、保持、量化、编码&#xff0c;其中采样和保持…

Swift 结构化并发之全局 Actor 趣谈

概览 在 Swift 结构化并发构成的体系中,一个称为“演员”(Actor)的成员扮演了非常重要的角色,它被用来隔离和同步执行中的数据。 除了普通 Actor 以外,还有一个全局“演员”(Global Actor)的概念,它是做什么的?又有什么与众不同的长处呢? 在本篇博文中,您将学到如…

C#学习笔记4:PC串口发送数据

今日继续我的C#学习之路&#xff0c;今日学习制作PC串口发送数据的窗口程序 串口是单片机上位机开发的重点&#xff0c;本文围绕做一个通过PC端串口发送数据的程序进行实践学习&#xff0c; 文章提供源码与解释、整体工程文件 目录 1、控件的选择与摆放&#xff1a; 2、程序设…

Docker搭建LNMP环境实战(02):Win10下安装VMware

实战开始&#xff0c;先安装 VMware 虚拟机。话不多说&#xff0c;上手就干&#xff01; 1、基本环境检查 1.1、本机Bios是否支持虚拟化 进入&#xff1a;任务管理器- 性能&#xff0c;查看“虚拟化”是否启用&#xff0c;如果已启用&#xff0c;则满足要求&#xff0c;如果未…

MyBatis3源码深度解析(二十二)MyBatis拦截器的原理及应用(一)拦截器的实现原理与执行过程

文章目录 前言第九章 MyBatis拦截器的原理及应用9.1 拦截器的实现原理9.1.1 拦截器的注册9.1.2 自定义拦截器9.1.3 拦截器的实现原理9.1.3.1 拦截器支持的类和方法9.1.3.2 Interceptor9.1.3.3 Invocation9.1.3.4 Plugin9.1.3.4.1 getSignatureMap()9.1.3.4.2 getAllInterfaces(…

2024年大模型面试准备(四):大模型面试必会的位置编码(绝对位置编码sinusoidal,旋转位置编码RoPE,以及相对位置编码ALiBi)

节前&#xff0c;我们组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、参加社招和校招面试的同学&#xff0c;针对大模型技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何备战、面试常考点分享等热门话题进行了深入的讨论。 合集在这…

生成可读取配置文件的独立运行jar程序

前言: 周五刚躺下,前线打来语音要个下载文件的小程序,下载路径和下载码需要根据配置获取,程序需要在服务器执行。当然配置的设计是个人设计的,不然每次更新下载码都要重新出具jar包,太麻烦。多年没写独立运行的jar包了,翻阅了相关资料,最终还是功夫不负有心人。想着这种…

鸿蒙 HarmonyOS应用开发之API:Context

Context 是应用中对象的上下文&#xff0c;其提供了应用的一些基础信息&#xff0c;例如resourceManager&#xff08;资源管理&#xff09;、applicationInfo&#xff08;当前应用信息&#xff09;、dir&#xff08;应用文件路径&#xff09;、area&#xff08;文件分区&#x…

uni-app攻略:如何对接驰腾打印机

一.引言 在当前的移动开发生态中&#xff0c;跨平台框架如uni-app因其高效、灵活的特点受到了开发者们的青睐。同时&#xff0c;随着物联网技术的飞速发展&#xff0c;智能打印设备已成为许多业务场景中不可或缺的一环。今天&#xff0c;我们就来探讨如何使用uni-app轻松对接驰…

阿赵UE学习笔记——22、动画合成

阿赵UE学习笔记目录 大家好&#xff0c;我是阿赵。   继续学习虚幻引擎的使用。这次来看看动画合成功能。   所谓的动画合成&#xff0c;意思就是把多段已经存在的动画拼接在一起&#xff0c;成为一段新的动画。比如之前做的钢铁侠例子里面&#xff0c;钢铁侠的待机动作感觉…

零基础机器学习(3)之机器学习的一般过程

文章目录 一、机器学习一般过程1.数据获取2.特征提取3.数据预处理①去除唯一属性②缺失值处理A. 均值插补法B. 同类均值插补法 ③重复值处理④异常值⑤数据定量化 4.数据标准化①min-max标准化&#xff08;归一化&#xff09;②z-score标准化&#xff08;规范化&#xff09; 5.…

AI入侵游戏业:是颠覆者还是创新助手?揭秘未来游戏新趋势!

在科技日新月异的今天&#xff0c;人工智能&#xff08;AI&#xff09;已经成为各行各业的关注焦点。而在娱乐产业中&#xff0c;AI技术的引入也让人们对电子游戏的未来发展产生了无限遐想。那么&#xff0c;AI究竟会给电子游戏行业带来怎样的变革&#xff1f;它会成为行业的颠…

【嵌入式学习】Qtday03.26

一、思维导图 二、练习 头文件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTime> #include <QTextToSpeech>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Wi…

128天创作纪念日

分享的力量 hellohello~大家好✨✨我是大耳朵土土垚&#x1f973;&#x1f973;&#x1f973;今天是我创作128天的纪念日&#x1f389;&#x1f389;&#x1f389;&#xff0c;今天听到一句话——分享自己开心的事情就像有丝分裂一样会将快乐一直扩散&#x1f496;&#x1f496…

基于前端技术实现的全面预算编制系统

前言 在现代商业环境中&#xff0c;预测销售数据和实际成本是每个公司CEO和领导都极为重视的关键指标。然而&#xff0c;由于市场的不断变化&#xff0c;准确地预测和管理这些数据变得愈发具有挑战性。为了应对这一挑战&#xff0c;建立一个高效的系统来管理和审查销售数据的重…

机器人路径规划:基于斑翠鸟优化算法(Pied Kingfisher Optimizer ,PKO)的机器人路径规划(提供MATLAB代码)

一、机器人路径规划介绍 移动机器人&#xff08;Mobile robot&#xff0c;MR&#xff09;的路径规划是 移动机器人研究的重要分支之&#xff0c;是对其进行控制的基础。根据环境信息的已知程度不同&#xff0c;路径规划分为基于环境信息已知的全局路径规划和基于环境信息未知或…

【go从入门到精通】if else 条件控制

作者简介&#xff1a; 高科&#xff0c;先后在 IBM PlatformComputing从事网格计算&#xff0c;淘米网&#xff0c;网易从事游戏服务器开发&#xff0c;拥有丰富的C&#xff0c;go等语言开发经验&#xff0c;mysql&#xff0c;mongo&#xff0c;redis等数据库&#xff0c;设计模…

行业研究数据/报告网站 - 好用免费

前言 转眼进互联网 12 年了&#xff0c;先后在百度、汽车之家、某独角兽做业务和商业分析。与CEO、VP、业务owner等都对接过&#xff0c;1 个明显共性&#xff0c;就是大家都很关注外部行业数据&#xff0c;为决策提供参考。接下来&#xff0c;就和大家分享一下我收藏的 34 个…

迷宫(蓝桥杯)——DFS和BFS

迷宫 题目描述 下图给出了一个迷宫的平面图&#xff0c;其中标记为 1 的为障碍&#xff0c;标记为 0 的为可以通行的地方。 010000 000100 001001 110000迷宫的入口为左上角&#xff0c;出口为右下角&#xff0c;在迷宫中&#xff0c;只能从一个位置走到这 个它的上、下、左…