【Vue全家桶高仿小米商城】——(四)项目基础架构

news2024/11/25 7:04:54

第四章:项目基础架构

此章节全力讲解前端基本项目架构,通过此章节可搭建一个通用性的前端架构,内容涵盖跨域方案、路由封装、错误拦截等。

文章目录

    • 第四章:项目基础架构
      • 一、前端跨域解决
        • 什么是前端跨域?
        • 怎么解决前端跨域?
          • CORS跨域
          • JSONP跨域
          • jsonp与cors的区别:
          • 代理跨域
      • 二、项目准备
        • 需求梳理
        • 分析目录
        • 构建项目目录
        • 安装依赖
        • 路由封装
        • Storage封装
          • cookie,localStorage,sessionStorage三者区别(分六点)?
          • 为什么要封装Storage?本身不是有api吗?
          • 手写Storage封装
          • 封装Storage完整代码
        • 接口错误拦截
          • 使用[Axios拦截器](https://www.kancloud.cn/yunye/axios/234845)
          • 设置baseURL及接口环境
          • JSONP或CORS跨域接口的环境设置(不是接口代理的情况下统一管理baseURL)
          • 如何去做?
        • Mock设置(模拟数据)
          • 为什么要用Mock?
          • 如何创建Mock?
          • 使用JSON文件
          • 使用easy-mock
          • 使用本地集成Mockjs API
        • 总结接口代理,接口拦截,mock.js间的联系

一、前端跨域解决

什么是前端跨域?

  • 跨域是浏览器为了安全而做出的限制策略
  • 浏览器请求必须遵循同源策略:同域名同端口同协议

怎么解决前端跨域?

CORS跨域

CORS跨域 - 服务端设置,前端直接调用
说明:后台允许前端某个站点进行访问。如Easy Mock:开源的公共MOCK平台,公共接口。
在这里插入图片描述
控制台查看network信息
在这里插入图片描述

响应头中:
Access-Control-Allow-Credentials:允许前端将cookie带过去
Access-Control-Allow-Origin:表示允许指定的这个网址访问mock的接口

JSONP跨域

前端适配,后台配合
说明:需要前后端同时改造
安装jsonp

安装并添加到环境中
npm i jsonp --save-dev

jsonp不是请求在network中的XHR里面没有,JS里面有,是js的一段脚本。
在这里插入图片描述
在这里插入图片描述

jsonp与cors的区别:
let url2 = 'https://order.imooc.com/pay/cartorder'
    axios.get(url2).then((data)=>{
      console.log(data)
    })
    jsonp(url2,{},(err,res)=>{
      console.log(res)
    })

当使用axios时控制台输出信息,表示不是允许的网站,无Access-Control-Allow-Origin请求头。
在这里插入图片描述

当使用jsonp时,能正常访问。
在这里插入图片描述

代理跨域

实现:通过修改nginx服务器配置来实现;
说明:前端修改,后台不动;

具体操作:
1.在整个项目项目中新增vue.config.js的配置文件
2.文件中写入:

// 开发环境下的接口代理  访问/a代理到/b,则实际访问的/b
// webpack的配置表传送给nodejs服务器
// nodejs遵循commonjs规范抛出就不用import了
module.exports = {  
  // 自动加载devServer中的配置表
  devServer:{
      host:'localhost',
      port:8080,
      // 代理
      proxy:{
          // 访问/pay时实现拦截转发到target中
          '/api':{
              // 目标网址,内部访问到慕课网的接口
              target:'https://order.imooc.com',
              changeOrigin:true,
              pathRewrite:{
                  '/api':''
              }
          }
      }
  }
}

实现原理:

书写好config.js后重启项目,vue会自动加载此配置文件下的devServer配置表
针对proxy中做路由统一拦截(此处是统一拦截的/api),在.vue文件中定义url时都统一定义为如下:let url2 = ‘/api/pay/cartorder’,在拦截后进行访问目标地址时由**changeOrigin:true,pathRewrite:{’/api’:’ '}**自动去掉/api进行访问。
此时看似访问的localhost:8080/api/pay/cartorder实则访问的https://order.imooc.com/pay/cartorder
在这里插入图片描述

二、项目准备

需求梳理

  1. 熟悉文档、查看原型、读懂需求
  2. 了解前端设计稿 - 设计前端业务架构
  3. 了解后台接口文档 - 制定相关对接规范
  4. 协调资源
  5. 搭建前端架构

分析目录

  1. 查看原型图,分析哪些板块会封装为一个组件,进行复用。
  2. 综合分析后先搭建大的目录再去创建小的。
  3. 静态图片建议src下的assets放小的,public下放大的。
  4. src下的components就是组件

构建项目目录

  1. 初始化VScode内容:删除components文件夹下的最初的HelloWord组件,以及删除App.vue下对HelloWord组件的所有引用,并增加router-view的入口。

  2. 在src目录下新建api文件夹统一管理路由api

  3. src下创建util文件夹存放公共方法,如格式化,数组转换之类的方法等。

  4. src下创建storage文件夹存放对数据存值取值等的工具箱。

  5. src下创建store文件夹存放vuex的内容。

  6. src下创建router.js存放路由

  7. src下创建pages文件夹存放页面文件

  8. pages创建index.vue(首页)、home.vue(主结构、存放公共的头部和尾部),product.vue(产品栈)、detail.vue(商品详情)、orderList.vue(订单页)、order.vue(订单主结构)、orderConfirm.vue(订单确认)、cart.vue(购物车)、login.vue(登录)、orderPay.vue(支付)、alipay.vue(支付跳转中间页)

  9. components下创建NavHeader.vue公共头部NavFooter公共底部。
    在这里插入图片描述
    在这里插入图片描述

安装依赖

懒加载:vue-lazyload
ui库:element-ui
sass编译:node-sass sass-loader
轮播:vue-awesome-swiper
axios:vue-axios
cookie:vue-cookie

npm i vue-lazyload element-ui node-sass sass-loader vue-awesome-swiper vue-axios vue-cookie --save-dev

在这里插入图片描述

路由封装

由页面划分路由,找共性,拆分父子组件。
在router.js中封装所有的路由,并重定向到index

import Vue from 'vue'
import router from 'vue-router'
import Home from './pages/home.vue'
import Index from './pages/index.vue'
import Product from './pages/product.vue'
import Detail from './pages/detail.vue'
import Cart from './pages/cart.vue'
import Order from './pages/order.vue'
import OrderList from './pages/orderList.vue'
import OrderConfirm from './pages/orderConfirm.vue'
import OrderPay from './pages/orderPay.vue'
import AliPay from './pages/alipay.vue'

Vue.use(router);

export default new router({
    routes:[
        {
            path:'/',
            name:'home',
            component:Home,
            redirect:'/index',
            children:[
                {
                    path:'/index',
                    name:'index',
                    component:Index
                },
                {
                    path:'/product/:id',
                    name:'product',
                    component:Product
                },
                {
                    path:'/detail/:id',
                    name:'detail',
                    component:Detail
                }
            ]
        },
        {
            path:'/cart',
            name:'cart',
            component:Cart
        },
        {
            path:'/order',
            name:'order',
            component:Order,
            children:[
                {
                    path:'list',
                    name:'order-list',
                    component:OrderList
                },
                {
                    path:'confirm',
                    name:'order-confirm',
                    component:OrderConfirm
                },
                {
                    path:'pay',
                    name:'order-pay',
                    component:OrderPay
                },
                {
                    path:'alipay',
                    name:'alipay',
                    component:AliPay
                }
            ]
        }
    ]
})

在main.js中引入,并全局使用

import Vue from 'vue'
import router from './router'
import App from './App.vue'

Vue.config.productionTip = false;

new Vue({
    router,
    render: h => h(App),
}).$mount('#app')

定义index是home的子页面,在home中写入router-view用来显示子页面内容:
在这里插入图片描述

index.vue:
在这里插入图片描述

访问路由:http://localhost:8080/#/index
页面显示为:绿色框为公共组件,黑色为视图层,home相当于整个容器。
在这里插入图片描述

同理定义order页面,放置公共顶部尾部和视图:
在这里插入图片描述

访问路由:http://localhost:8080/#/order/list
在这里插入图片描述

Storage封装

cookie,localStorage,sessionStorage三者区别(分六点)?
  1. 大小:cookie 4k,storage 5m

  2. 有效期:cookie拥有有效期可以通过expires设置失效时间,不设置默认关闭浏览器即失效,localStorage永久存储需要手动清除,sessionStorage会话存储,关闭网页就清除了信息。

  3. http请求:cookie会携带在http头中,发送到服务器端,如果使用cookie保存过多数据会带来性能问题,存储在内存中,Storage只存储在浏览器端不参与和服务器的通信。

  4. 路径:Cookie有路径限制,Storage只存储在域名下。

  5. API:Cookie没有特定的API,Storage有对应的API

  • API:setItem,getItem,removeItem,clear

设置key,value
sessionStorage.setItem(“key”, “value”);
localStorage.setItem(“site”, “js8.in”);

通过key获取value
var value = sessionStorage.getItem(“key”);
var site = localStorage.getItem(“site”);

删除对应key
sessionStorage.removeItem(“key”); localStorage.removeItem(“site”);

清除所有的key/value
sessionStorage.clear();
localStorage.clear();

  1. 应用场景:
    cookie:登录
    localStorage:跨页面传递参数
    sessionStorage:保存临时数据,防止用户刷新页面后丢失参数。
为什么要封装Storage?本身不是有api吗?
  • Storage本身有API,但是只是简单地key/value形式。
  • Storage只存储字符串,需要人工转为json对象。
  • Storage只能一次性清空,不能单个清空。
手写Storage封装

在storage文件夹下的index.js中,抛出四个操控Storage的函数,存储值——setItem,获取值——getItem,获取整个浏览器的缓存信息——getStorage,清空某一个值——clear

  1. getStorage:
    运行项目,在Application中添加sessionStorage,注意Value中格式为JSON格式(“key”:“value”)类似于{“user”:{“username”:“jack”,“age”:21,“sex”:1}}(注意使用双引号)
    在这里插入图片描述

在控制台查看对应的sessionStorage的值类型:
在这里插入图片描述

转换为JSON:
在这里插入图片描述

函数中为:

getStorage(){
        return JSON.parse(window.sessionStorage.getItem(STORAGR_KEY) || '{}');
}
  1. setItem:
    往sessionStorage设置值,分两种情况:
  • 在对应Storage_Key下直接创建value值,如mail下直接创建data:{},id:‘001’
    在这里插入图片描述
//storage/index.js (第二种情况返回的值:'data','this.getStorage()['data']')
setItem(key,value){
    //此时的val为sessionStorage的JSON格式
        let val = this.getStorage();
        //往大的模块中覆盖旧的值 this.getStorage()['data']=this.getStorage()['data']
        val[key] = value;
        //存完之后转换为字符串写入Storage信息中覆盖原来的Storage_key
        window.sessionStorage.setItem(Storage_Key,JSON.stringify(val)); 
},
    
//App.vue中导入
import storage from './storage/index'
//App.vue中mounted中使用
storage.setItem('id','001')
storage.setItem('data',{})

val[key]相当于JSON.parse(window.sessionStorage.getItem(‘mail’))[‘id’] //打印001

在已有的模块中再添加内容,如往data中添加username,以及userblogs(包含blog1,blog2)
在这里插入图片描述

//App.vue
//参数:key,value,添加到哪里的模块
storage.setItem('username','DDDZ','data')
storage.setItem('userblogs',{
  'blog1':'name1',
  'blog2':'name2'
},'data')

//storage/index.js
setItem(key,value,module_name){   
	//拿到data下面的所有值引入getItem第一种情况返回为this.getStorage()['data']
    let val = this.getItem(module_name);
    //等同于this.getStorage()['data']['username']='DDDZ'
    val[key] = value;
   	//module_name成为key,val为value执行第一种情况 ('data','this.getStorage()['data']')
    this.setItem(module_name,val);
},
  1. getItem:
    分两种情况,一种类似于sessionStorage下获取data或者id的值,另一种类似于获取data里面userblogs的值。
  • 第一种:
getItem(key){
	return this.getStorage()[key]
}
  • 第二种:
//如传参:('username','data')
getItem(key,module_name){
	//递归获取 module_name变成key this.getItem('data');到第一种情况返回this.getStorage()['data'] 为val
    let val = this.getItem(module_name);
    //return this.getStorage()['data']['username']
    if(val) return val[key];
}
  1. claer:
    分两种情况,一种类似于直接删除sessionStorage下的id,一种删除data里面的userName。
  • 第一种:
//storage/index.js
clear(key){
	//获取
	let val = this.getStorage()
	//删除 this.getStorage()['id']
	delete val[key]
	//更新
	window.sessionStorage.setItem(Storage_Key, JSON.stringify(val))
}

第二种:

//storage/index.js
clear(key,module_name){
	//获取
	let val = this.getStorage()
	//this.getStorage()['data'] 判断如果没有值,返回
	if (!val[module_name]) return;
	//this.getStorage()['data']['username'] 删除
	delete val[module_name][key];
	//更新
	window.sessionStorage.setItem(Storage_Key, JSON.stringify(val))
}

//App.vue
storage.clear('id')
storage.clear('username','data')
封装Storage完整代码
//storage/index.js
//Storage封装 如:value为{"user":{"username":"jack","age":30,"sex":1}}
const Storage_Key = 'mail';
export default {
    //module_name是某个模块如user
    //存储值
    //storage/index.js (第二种情况返回的值:'data','this.getStorage()['data']')
    setItem(key, value, module_name) {
        //获取某个模块下面的属性user下面的username
        if (module_name) {
            //拿到data下面的所有值引入getItem  this.getStorage()['data']
            let val = this.getItem(module_name);
            //this.getStorage()['data']['username']='DDDZ'
            //val[key]相当于JSON.parse(window.sessionStorage.getItem('mail'))['id'] //打印001
            val[key] = value;
            //module_name成为key,val为value执行第一种情况 ('data','this.getStorage()['data']')
            this.setItem(module_name, val);
        }
        else {
            //此时的val为sessionStorage的JSON格式
            let val = this.getStorage();
            //往大的模块中覆盖旧的值 this.getStorage()['data']=this.getStorage()['data']
            val[key] = value;
            //存完之后转换为字符串写入Storage信息中覆盖原来的Storage_key
            window.sessionStorage.setItem(Storage_Key, JSON.stringify(val));
        }

    },


    getItem(key, module_name) {
        if (module_name) {
            //递归获取 module_name变成key this.getItem('data');到第一种情况返回this.getStorage()['data'] 为val
            let val = this.getItem(module_name);
            //return this.getStorage()['data']['username']
            if (val) return val[key];
        }
        //获取的user相当于(JSON.parse(window.sessionStorage.getItem("mall") || '{}'))["user"]
        return this.getStorage()[key];

    },
    //获取整个缓存信息
    getStorage() {
        return JSON.parse(window.sessionStorage.getItem(Storage_Key) || '{}');
    },

    clear(key, module_name) {
        //获取
        let val = this.getStorage();
        if (module_name) {
            //this.getStorage()['data'] 判断如果没有值,返回
            if (!val[module_name]) return;
            //this.getStorage()['data']['username'] 删除
            delete val[module_name][key];
        } else {
            //删除 this.getStorage()['id']
            delete val[key];
        }
        //更新
        window.sessionStorage.setItem(Storage_Key, JSON.stringify(val));
    }
}

接口错误拦截

统一报错、未登录统一拦截、请求值,返回值统一处理。

使用Axios拦截器
  1. 安装:npm install axios
  2. 在main.js引入Axios,导入vue-axios
    import axios from ‘axios’
    import VueAxios from ‘vue-axios’
  3. 挂载导入的vue-axios,方便项目中用this.axios直接使用axios不然每次使用前都要去import axios就很麻烦。
    Vue.use(VueAxios,axios)
  4. 添加拦截器interceptors,注意response.data,是响应拦截器的data,而res.data是前后端接口字段中自定义的data,state也是自定义的。
  5. 在设置status时应当做统一分类处理,比如订单一类的都是2001,2002之类的。
// 添加响应拦截器(返回值拦截)
axios.interceptors.response.use((response)=>{
	    //获取所有的接口数据
	    let res = response.data;
	    //检测已经登陆,返回数据
	    if(res.status == 0){
	      //返回接口里面data包含的值
	      return res.data;
	    }
	    //检测未登录,拦截跳转到登录页
	    else if(res.status == 10){
	      window.location.href = '/#/login';
	    }
	    //登录失败,错误的提示信息
	    else{
	      alert(res.msg);
	    }
	}, function (error) {
	    // 对响应错误做点什么
	    return Promise.reject(error);
  	}
)
设置baseURL及接口环境

使用JSONP或CORS跨域以及接口代理时的baseURL
设置请求默认地址baseURL和响应超时时间
baseURL根据前端的跨域方式做调整:

JSONP或CORS跨域:后端域名和前端不一样时用baseURL用’http://完整的url地址‘ 。

接口代理:后端与前端一样时,前端在这里定义了/api后端接口也要统一为/api,后端没有/api的话可以前端在转发时统一去掉/api。拦截时接口代理中用:changeOrigin:true,pathRewrite:{’/api’:’’}去掉/api。

//接口代理
axios.defaults.baseURL = '/api';

//CORS或JSONP跨域
axios.defaults.baseURL = 'https://order.imooc.com/pay/cartorder'

//设置超时时间
axios.defaults.timeout = 8000;
JSONP或CORS跨域接口的环境设置(不是接口代理的情况下统一管理baseURL)

为什么要去设置?

  1. 开发上线不同阶段,需要不同的配置。
  2. 不同的跨域方式,配置不同。
  3. 打包时候统一注入环境参数,统一管理环境,输出不同的版本包。
如何去做?
  1. src文件夹下创建env.js文件
  2. 在package.json中注入环境参数,通过–mode=环境参数的值,来赋值。
"scripts": {
    "serve": "vue-cli-service serve --mode=development",
    //自定义的环境变量prev
    "prev":"vue-cli-service serve --mode=prev",
    "build": "vue-cli-service build --mode=production",
    "lint": "vue-cli-service lint"
  },
  1. 在env.js中去拿到环境参数:node.js中的process进程通过process.env.NODE_ENV获取当前nodejs服务器下的环境变量。
  2. 自定义环境变量xxx时要在src下加一个文件.env.xxx,并且在里面配置NODE_ENV = ‘xxx’
let baseUrl;
//根据不同的环境输出不同的url地址
//在package.json中增加 --mode=XXX参数(环境变量传给参数)
//process.env取到当前nodejs服务器下的环境变量
switch (process.env.NODE_ENV) {
    //开发development,测试test,生产production
    case 'development':
        baseUrl = '  http://dev-mall-pre.springboot.cn/api'
        break;

    case 'test':
        baseUrl = 'http://test-mall-pre.springboot.cn/api'
        break;

    case 'production':
        baseUrl = 'http://mall-pre.springboot.cn/api'
        break;

        //自定义环境变量prev一定要在加一个文件.env.prev,并且在里面配置
    case 'prev':
        baseUrl = 'http://prev-mall-pre.springboot.cn/api'
        break;

    default:
        baseUrl = 'http://dev-mall-pre.springboot.cn/api'
        break;
}

export default{
    baseUrl
}

  1. 在main.js导入env,并使用由环境变量获取到的baseURL地址
import env from './env'
axios.defaults.baseURL = env.baseUrl;
  1. npm run serve/pre/build 就会使用不同的环境变量,从而使用不同的baseURL。

Mock设置(模拟数据)

为什么要用Mock?
  1. 开发阶段,为了高效率,需要提前Mock
  2. 减少代码冗余,灵活插拔
  3. 减少沟通,减少接口联调时间
如何创建Mock?
  1. 本地创建JSON(接口文档已经规定好)
  2. easy-mock平台
  3. 集成Mock AP
使用JSON文件

public文件夹下创建mock文件夹,创建一个user文件夹存放login.json文件作为mock。
在这里插入图片描述

在app.vue中发起axios请求,在main.js中注释掉baseURL
在这里插入图片描述

浏览器可以查看到拿到的JSON Mock数据
在这里插入图片描述

在这里插入图片描述

使用easy-mock

easy-mock官网

//App.vue
this.axios.get('/user/login').then((res)=>{
          this.res = res
})

//main.js
axios.defaults.baseURL = '换成自己在easy-mock的baseURL地址';

在这里插入图片描述

使用本地集成Mockjs API
  1. 搭建自己的mock平台
  2. 或者使用mockjs平台
  • 安装mockjs,在src下创建mock文件夹存放api.js,定义mock文件。
  • 使用mockjs,不会发请求但是会有数据。
    在这里插入图片描述
//安装mockjs
npm i mockjs --S

//main.js
//mockjs 开关,设置按需加载
const mock = true
if(mock){
  require('./mock/api')  //加载mock文件
}

axios.defaults.baseURL = '/api';

//App.vue
 this.axios.get('/user/login').then((res)=>{
           this.res = res
})

查看返回的数据:
在这里插入图片描述

总结接口代理,接口拦截,mock.js间的联系

接口代理:在vue.config.js中其实也是一种拦截,识别到url中的/api后拦截转发到真实的接口地址获取数据。

接口拦截:用axios,在main.js中添加baseURL统一接口地址的起始头为/api,添加interceptors拦截器对接口返回的数据进行判定处理,如识别到未登录、已登录、登录错误等。

mock.js:获取本地模拟数据,使用jsonp时mockjs拦截不到,访问接口返回在Network中的JS里。使用axios时,mock 开关,关闭拦截,则没有被拦截,访问接口返回真实接口数据,返回信息在Network的XHR中。mock 开关,打开拦截则URL被拦截访问本地数据。

举例:

//App.vue
let url2 = '/pay/cartorder'

this.axios.get(url2).then((res)=>{
    this.res2 = res
    console.log(res)
})

//main.js
axios.defaults.baseURL = '/api';
//mock开关打开,axios发url请求时被拦截去访问./mock/api文件里面的/api/pay/cartorder下的模拟接口数据而不会去访问vue.config.js内的真实接口地址
const mock = true
if(mock){
  require('./mock/api')
}

//vue.config.js
module.exports = {  
    // 自动加载devServer中的配置表
    devServer:{
        host:'localhost',
        port:8080,
        // 代理
        proxy:{
            // 访问/pay时实现拦截转发到target中
            '/api':{
                // 目标网址,内部访问到慕课网的接口
                target:'https://order.imooc.com',
                changeOrigin:true,
                pathRewrite:{
                    '/api':''
                }
            }
        }
    }
}

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

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

相关文章

将h5项目转成uniapp小程序

打开微信开发者工具&#xff0c;新建项目&#xff1b;pages下index文件中index.wxml文件打开内容全删除&#xff1b;写入<web-view srchttp://域名.com/></web-view>&#xff1b;编译&#xff0c;成功在小程序中展示&#xff1b;其后&#xff0c;正常按照小程序流程…

scp命令及后台运行

将项目从一个服务器迁移到另外一个服务器的时候 当项目很大的时候 可以用到如下 1、scp -r 本地项目路径 需要迁移服务器的IP:/存放路径 scp -r /u01/media/Disk1/ 192.168.1.31:/u01/media/ reverse mapping checking getaddrinfo for bogon failed - POSSIBLE BREAK-IN ATTEM…

算法篇——动态规划 01背包问题 (js版)——更新新题

416. 分割等和子集 给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集&#xff0c;使得两个子集的元素和相等。 链接&#xff1a;力扣 解题思路&#xff1a; 这道题看似是比较简单的背包问题&#xff1a; 首先可以通过判断数组和是否是…

【ZenUML】时序图之ZenUML详解

时序图 序列图是一种交互图&#xff0c;显示进程如何彼此操作以及顺序。 Mermaid可以使用ZenUML渲染序列图。请注意&#xff0c;ZenUML使用的语法与mermaid中的原始序列图不同。 目前&#xff0c;最新版本mermaid v10.2.3 暂时不单独支持zenuml语法,需要配合mermaid-zenuml一…

动态规划_可视化校园导航Floyd算法应用

目录 引言 图片展示 视频展示 针对校园导航问题的分析 关键技术和算法介绍 详细介绍&#xff1a;算法的实现 总结 代码 附件&#xff1a;Map.png 引言 本文主要通过详细的程序打印和作者的推理过程&#xff0c;描述作者对Floyd算法的理解&#xff0c;阐述其中的动态规划思想是如…

突然发现CSDN变得不一样了【建议】【活动】

突然发现CSDN变得不一样了【活动】 前言推荐突然发现CSDN变得不一样了关于上传代码包关于上传视频关于运行代码关于插入代码1关于插入代码2关于社区的建立关于社区的管理关于此次活动的评选关于排行突然发现说明一下关于我 最后 前言 2023-6-19 23:34:04 本文章仅用于参加 20…

【Python 随练】年龄计算问题

题目&#xff1a; 有 5 个人坐在一起&#xff0c;问第五个人多少岁&#xff1f;他说比第 4 个人大 2 岁。问第 4 个人岁数&#xff0c;他说比第3 个人大 2 岁。问第三个人&#xff0c;又说比第 2 人大两岁。问第 2 个人&#xff0c;说比第一个人大两岁。最后问第一个人&#x…

C++基础(8)——类和对象(6)

前言 本文主要介绍了C中多态的基本知识 4.7.1&#xff1a;多态的基本概念和原理剖析 1&#xff1a;基本概念 静态多态&#xff1a;函数重载、运算符重载 动态多态&#xff1a;派生类和虚函数实现运行时多态 静态多态在编译阶段确定函数地址&#xff1b;动态多态在运行阶段…

微信小程序uniapp+springboot实现小程序服务通知

微信小程序uniappspringboot实现小程序服务通知 1. 实现效果 2. 模板选用及字段类型判断 2.1 开通订阅消息,并选用模板 如果点击订阅消息让开启消息订阅开启后就可以出现以下页面,我本次使用的模板是月卡到期提醒模板,点击选用即可 2.2 查看模板字段类型 TemplateId后续会使用…

面试官问:Redis 分布式锁如何自动续期?

资深面试官&#xff1a;你们项目中的分布式锁是怎么实现的&#xff1f; 老任&#xff1a;基于redis的set命令&#xff0c;该命令有nx和ex选项。 资深面试官&#xff1a;那如果锁到期了&#xff0c;业务还没结束&#xff0c;如何进行自动续期呢&#xff1f; 老任&#xff1a;…

第九章 番外篇:TORCHSCRIPT

下文中的代码都使用参考教程中的例子。 会给出一点自己的解释。 参考教程&#xff1a; 文章目录 Introduction复习一下nn.Module()Torchscripttorch.jit.ScriptModule()torch.jit.script()torch.jit.trace()一个小区别 使用示例tracing Modulesscripting ModuleMixing scripti…

乐鑫线上研讨会|探索 LCD 屏在物联网中的发展趋势

LCD 屏通过显示实时信息并提供交互式体验&#xff0c;现已成为各类设备的重要组成部分。在当下的 AIoT 时代&#xff0c;随着物联网技术的快速发展和应用场景的不断拓展&#xff0c;LCD 作为人机交互的主要输入输出设备&#xff0c;在智能家居、智能安防、工业控制、智慧城市等…

C#开发的OpenRA游戏之建造物品的窗口5

C#开发的OpenRA游戏之建造物品的窗口5 前面分析了TAB窗口的建立和运行,现在关注它的子窗口,也就是ProductionPaletteWidget类实现的窗口,这个窗口主要用来显示所有可以创建物品的ICON图标。用户可以通过这个窗口实现物品创建,如下图所示: 比如要创建电厂,就是点击上面…

【好书精读】网络是怎样连接的 之 创建套接字

&#xff08;该图由AI制作 学习AI绘图 联系我&#xff09; 目录 协议栈的内部结构 套接字的实体就是通信控制信息 真正的套接字 调用 socket 时的操作 从应用程序收到委托后 &#xff0c; 协议栈通过 TCP 协议收发数据的操作可以分为 4 个阶段 。 首先是创 建套接字 &…

SothisAI创建容器和conda环境

1.创建容器&#xff08;设置torch版本&#xff0c;cuda&#xff0c;python版本等等&#xff09;后进入web shell 2.shell里输入ssh username&#xff08;你自己的用户名&#xff09; IP&#xff08;你创建的实例的ip地址&#xff09; 3.在web平台创建你自己的文件夹 4.shel…

小程序请求封装、使用

小程序请求封装 1、要了解方法 1.1、wx.request() wx.request 发起 HTTPS 网络请求。&#xff08;详情点击wx.request查看官方文档&#xff09; 1.2、wx.showModal() wx.showModal 显示模态对话框。&#xff08;详情点击wx.showModal查看官方文档&#xff09; 1.3、wx.sho…

Swift 周报 第三十一期

文章目录 前言新闻和社区注册 WWDC23 实验室和活动Apple Vision Pro 和 visionOS 撼世登场App Store 中新增的隐私功能 提案正在审查的提案 Swift论坛推荐博文话题讨论关于我们 前言 本期是 Swift 编辑组自主整理周报的第二十二期&#xff0c;每个模块已初步成型。各位读者如果…

奇数分频器电路设计

目录 奇数分频器电路设计 1、奇数分频器电路简介 2、实验任务 3、程序设计 3.1、7分频电路代码 3.2、仿真验证 3.2.1、编写 TB 文件 3.2.2、仿真验证 4、用状态机实现7分频电路设计 4.1、代码如下&#xff1a; 4.2、使用状态机的好处 奇数分频器电路设计 前面一节我…

前端JS限制绕过测试-业务安全测试实操(17)

前端JS限制绕过测试,请求重放测试 前端JS限制绕过测试 测试原理和方法 很多商品在限制用户购买数量时,服务器仅在页面通过JS脚本限制,未在服务器端校验用户提交的数量,通过抓取客户端发送的请求包修改JS端生成处理的交易数据,如将请求中的商品数量改为大于最大数限制的值…

Vue中使用分布式事务管理解决方案

文章目录 分布式事务管理是什么优点&#xff1a;缺点&#xff1a;弥补缺点的方法有&#xff1a; 解决方案 分布式事务管理是什么 分布式事务管理是指在分布式系统中对跨多个数据库或服务的操作进行协调和保证一致性的机制。在分布式环境下&#xff0c;由于涉及到多个独立的资源…