uview2.0 u-number-box 无法输入小数,以及弹起键盘没有小数点 的问题 !! 非常简单的解决!!-CSDN博客

mikel阅读(326)

来源: uview2.0 u-number-box 无法输入小数,以及弹起键盘没有小数点 的问题 !! 非常简单的解决!!-CSDN博客

当使用该组件的时候发现integer设置为false后,只有step点击+ 或者 – 按钮才会小数的增长,但是真机调试 弹出的键盘时没有小数点的,突然灵光乍现,查看源码发现,input 的type属性一直都是number,所以适当的修改组件库,根据integer的值来动态改变type的值就好啦。!!!

 

上面只是开启了带小数点的键盘,但是你会发现至此,还是无法在input里面输入,仿佛你一输入就会被格式化数据。所以带着疑问查看源码,发现在input事件中有这么一行代码,所以我为了不破坏组件源码的前提下,在外面加了一个是否执行的判断条件,自己加了一个props,

 

至于如何添加的props 太简单了就不用再过多赘述了,如果对此有疑问,欢迎评论区留言
————————————————

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/m0_57033755/article/details/131259667

uniapp uview u-number-box防抖(商城添加商品有起购)-CSDN博客

mikel阅读(142)

来源: uniapp uview u-number-box防抖(商城添加商品有起购)-CSDN博客

使用uview做防抖,判断小于规定最小值重置为zuixiaozhi
<view class=”goodsSku__bottom__num__car__num”>
<u-number-box :longPress=”false” :disabled-input=”type === 0″ v-if=”show_num” input-height=”70″
input-width=”60″ :min=”1″ size=”25″ v-model=”number” @change=”valChange”></u-number-box>
</view>
 直接改变number.value时,u-number-box在页面上不会直接改变,用一个show_num变量强制刷新组件
function valChange(e) {
let fun = () => {
if (props.data?.min_number && e.value < parseInt(props.data.min_number)) {
show_num.value = false
uni.showToast({
icon: “none”,
title: props.data.min_number + “件起购哦 ~”
})
number.value = props.data.min_number
setTimeout(() => {
show_num.value = true
})
}
}
number.value = e.value
console.log(‘步进器值’, number.value)
globalProperties.$u.debounce(fun, 1000)
}
————————————————
                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/m0_49083276/article/details/132543544

UNIAPP实战项目笔记38 购物车的添加商品到购物车功能_uniapp加入购物车数量-CSDN博客

mikel阅读(182)

来源: UNIAPP实战项目笔记38 购物车的添加商品到购物车功能_uniapp加入购物车数量-CSDN博客

UNIAPP实战项目笔记38 购物车的加入购物车功能
通过mapGetters实现此功能
在 shopcart.vue中
使用mapGetters中的 addShopCart方法实现商品数量的增加

核心代码 detail.vue
<template>
<view class=”details”>
<!– 商品图 –>
<swiper :indicator-dots=”true” :autoplay=”true” :interval=”3000″ :duration=”1000″>
<swiper-item>
<view class=”swiper-item”>
<image class=”swiper-img” :src=”goodsContent.imgUrl” mode=””></image>
</view>
</swiper-item>
</swiper>
<!– 价格和名称 –>
<view class=”details-goods”>
<view class=”goods-pprice”>¥{{goodsContent.pprice}} </view>
<view class=”goods-oprice”>¥{{goodsContent.oprice}} </view>
<view class=”goods-name”>{{goodsContent.name}} </view>
</view>
<!– 商品详情图 –>
<view class=””>
<view class=””><image class=”details-img” src=”../../static/img/b3.jpg” mode=””></image></view>
<view class=””><image class=”details-img” src=”../../static/img/b3.jpg” mode=””></image></view>
<view class=””><image class=”details-img” src=”../../static/img/b3.jpg” mode=””></image></view>
<view class=””><image class=”details-img” src=”../../static/img/b3.jpg” mode=””></image></view>
<view class=””><image class=”details-img” src=”../../static/img/b3.jpg” mode=””></image></view>
<view class=””><image class=”details-img” src=”../../static/img/b3.jpg” mode=””></image></view>
</view>

<!– 商品列表 –>
<Card cardTitle=”看了又看”></Card>
<CommodityList :dataList=”dataList”></CommodityList>

<!– 底部 –>
<view class=”details-foot”>
<view class=”iconfont icon-xiaoxi”></view>
<view class=”iconfont icon-31gouwuche” @tap=”goShopCart”></view>
<view class=”add-shopcart” @tap=”showPop”>加入购物车</view>
<view class=”purchase” @tap=”showPop”>立刻购买</view>
</view>

<!– 底部弹出层 –>
<view class=”pop” v-show=”isShow” @touchmove.stop=””>
<!– 蒙层 –>
<view class=”pop-mask” @tap=”hidePop”> </view>
<!– 内容块 –>
<view class=”pop-box” :animation=”animationData”>
<view class=””>
<image class=”pop-img” :src=”goodsContent.imgUrl” mode=””></image>
</view>
<view class=”pop-num”>
<view class=””>购买数量</view>
<UniNumberBox
:min=1
:value=”num”
@change=”changeNumber”
></UniNumberBox>
</view>
<view class=”pop-sub” @tap=”addCart”>确定</view>
</view>
</view>
</view>
</template>

<script>
import $http from ‘@/common/api/request.js’
import Card from ‘@/components/common/Card.vue’;
import CommodityList from ‘@/components/common/CommodityList.vue’;
import UniNumberBox from ‘@/components/uni/uni-number-box/uni-number-box.vue’;
import {mapMutations} from ‘vuex’
export default {
data() {
return {
isShow:false,
goodsContent:{},
animationData:{},
num:1,
swiperList:[
{imgUrl:”../../static/img/b3.jpg”},
{imgUrl:”../../static/img/b3.jpg”},
{imgUrl:”../../static/img/b3.jpg”}
],
dataList:[{
id:1,
imgUrl:”../../static/logo.png”,
name:”迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售”,
pprice:”299″,
oprice:”659″,
discount:”5.2″
},
{
id:2,
imgUrl:”../../static/logo.png”,
name:”迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售”,
pprice:”299″,
oprice:”659″,
discount:”5.2″
},{
id:3,
imgUrl:”../../static/logo.png”,
name:”迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售”,
pprice:”299″,
oprice:”659″,
discount:”5.2″
}]
};
},
components:{
Card,
CommodityList,
UniNumberBox
},
onLoad(e) {
// console.log(e.id);
// 设置默认id=1
if(!e.id)
e.id = 1;
this.getData(e.id);
},
// 修改返回默认行为
onBackPress(){
if (this.isShow) {
this.hidePop();
return true;
}

},
// 点击分享
onNavigationBarButtonTap(e) {
if(e.type===’share’){
uni.share({
provider:”weixin”,
type:0,
scene:”WXSceneSession”,
title:this.goodsContent.name,
href:”http://127.0.0.1:8080/#/pages/details/details?id=”+this.goodsContent.id,
imageUrl:this.goodsContent.imageUrl,
success:function(res){
uni.showTabBar({
title:”分享成功”
})
},
fail: (err) => {
console.log(“fail:”+ JSON.stringify(err));
}
})
}
},
methods:{
…mapMutations([‘addShopCart’]),
// 改变商品数量
changeNumber(value){
this.num = value;
},
// 请求商品
getData(id){
$http.request({
url:”/goods/id”,
data:{
id:id
}
}).then((res)=>{
this.goodsContent = res[0];
}).catch(()=>{
uni.showToast({
title:’请求失败’,
icon:’none’
})
})
},
showPop(){
// 初始化一个动画
var animation = uni.createAnimation({
duration:200 // 动画时间
});
// 定义动画内容
animation.translateY(600).step();
// 导出动画数据传递给data层
this.animationData = animation.export();
this.isShow = true;
setTimeout(()=>{
animation.translateY(0).step();
this.animationData = animation.export();
},200)
},
hidePop(){
var animation = uni.createAnimation({
duration:200
});
animation.translateY(600).step();
this.animationData = animation.export();
this.isShow = true;
setTimeout(()=>{
animation.translateY(0).step();
this.isShow = false;
},200)
},
// 跳转到购物车页面
goShopCart(){
uni.switchTab({
url:’../shopcart/shopcart’
})
},
// 加入购物车
addCart(){
let goods = this.goodsContent;
this.goodsContent[‘checked’] = false;
this.goodsContent[‘num’] = this.num;
// 加入购物车
this.addShopCart(goods);
// 隐藏弹出框
this.hidePop();
// 提示信息
uni.showToast({
title:”成功加入购物车”,
icon:”none”
})
},
}
}
</script>

<style lang=”scss”>
swiper{
width: 100%;
height: 700rpx;
}
.swiper-img{
width: 100%;
height: 700rpx;
}
.details{
padding-bottom: 90rpx;
}
.details-goods{
text-align: center;
font-weight: bold;
font-size: 36rpx;
padding: 10rpx 0;
}
.details-img{
width: 100%;
}
.details-foot{
position: fixed;
left: 0;
bottom: 0;
width: 100%;
height: 90rpx;
display: flex;
align-items: center;
justify-content: center;
background-color: #FFFFFF;
}
.details-foot .iconfont{
width: 60rpx;
height: 60rpx;
border-radius: 100%;
background-color: #000000;
color: #FFFFFF;
text-align: center;
margin: 0 10rpx;
line-height: 60rpx;
}
.add-shopcart{
margin: 0 40rpx;
padding: 6rpx 30rpx;
background-color: #000000;
color: #FFFFFF;
border-radius: 40rpx;

}
.purchase{
margin: 0 40rpx;
padding: 6rpx 30rpx;
background-color: #49BDFB;
color: #FFFFFF;
border-radius: 40rpx;
}
.pop{
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 9999;
}
.pop-mask{
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.3);
}
.pop-box{
position: absolute;
left: 0;
bottom: 0;
width: 100%;
background-color: #FFFFFF;
}
.pop-img{
width: 260rpx;
height: 260rpx;
top:-130rpx;
border-radius:20rpx 20rpx 0 0;
margin: 30rpx;
}
.pop-sub{
line-height: 80rpx;
background-color: #49BDFB;
color: #FFFFFF;
text-align: center;
}
.pop-num{
padding: 20rpx;
display: flex;
justify-content: space-between;
}

</style>

核心代码 cart.js部分
export default{
state:{
list:[
/* {
id:1,
name:”332经济法能聚聚会技能大赛 经济法能聚聚会技能大赛”,
color:”颜色:嘿嘿嘿激活”,
imgUrl:”../../static/logo.png”,
pprice:”27″,
num:1,
checked:false
},{
id:2,
name:”032经济法能聚聚会技能大赛 经济法能聚聚会技能大赛”,
color:”颜色:嘿嘿嘿激活”,
imgUrl:”../../static/logo.png”,
pprice:”48″,
num:6,
checked:false
} */
],
selectedList:[]

},
getters:{
// 判断是否 全选
checkedAll(state){
return state.list.length === state.selectedList.length;
},
// 合计 结算数量
totalCount(state){
let total = {
pprice:0,
num:0
}
state.list.forEach(v=>{
// 是否选中
if(state.selectedList.indexOf(v.id) > -1){
// 合计
total.pprice += v.pprice*v.num;
// 结算数量
total.num = state.selectedList.length;
}
})

return total;
}
},
mutations:{
// 全选
checkAll(state){
state.selectedList = state.list.map(v=>{
v.checked = true;
return v.id;
})
},
// 全不选
unCheckAll(state){
state.list.forEach(v=>{
v.checked = false;
})
state.selectedList = [];
},
// 单选
selectedItem(state,index){
let id = state.list[index].id;
let i = state.selectedList.indexOf(id);
// 如果selectList已经存在就代表他之前的选中状态,checked=false,并且在selectedList删除
if (i>-1) {
state.list[index].checked = false;
return state.selectedList.splice(i,1);
}
// 如果之前没有选中,checked=true,把当前的id添加到selectedList
state.list[index].checked = true;
state.selectedList.push(id);
},
//
delGoods(state){
state.list = state.list.filter(v=>{
return state.selectedList.indexOf(v.id) === -1;
})
},
// 加入购物车
addShopCart(state, goods){
state.list.push(goods);
}
},
actions:{
checkedAllFn({commit,getters}){
getters.checkedAll ? commit(“unCheckAll”) : commit(“checkAll”)
},
delGoodsFn({commit}){
commit(‘delGoods’);
commit(“unCheckAll”);
uni.showToast({
title:’删除成功’,
icon:”none”
})
}
}
}

实际案例图片 购物车的添加商品功能

目录结构
前端目录结构
manifest.json 配置文件: appid、logo…

pages.json 配置文件: 导航、 tabbar、 路由

main.js vue初始化入口文件

App.vue 全局配置:样式、全局监视

static 静态资源:图片、字体图标

page 页面

index
index.vue
list
list.vue
my
my.vue
search
search.vue
search-list
search-list.vue
shopcart
shopcart.vue
details
details.vue
components 组件

index
Banner.vue
Hot.vue
Icons.vue
indexSwiper.vue
Recommend.vue
Shop.vue
common
Card.vue
Commondity.vue
CommondityList.vue
Line.vue
ShopList.vue
uni
uni-number-box
uni-number-box.vue
uni-icons
uni-icons.vue
uni-nav-bar
uni-nav-bar.vue
common 公共文件:全局css文件 || 全局js文件

api
request.js
common.css
uni.css
store vuex状态机文件

modules
cart.js
index.js
————————————————

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/gixome/article/details/127867852

uniapp 实现保持登录状态_uniapp保持登录状态-CSDN博客

mikel阅读(127)

来源: uniapp 实现保持登录状态_uniapp保持登录状态-CSDN博客

主要思路:在项目启动时判断是否存在token(根据不同的业务需求有不同的判断条件),如果存在则直接进入首页,不存在则先登录,登录成功进入首页。
于是,在app的生命周期函数中操作:
       onLaunch: function() {
let token= uni.getStorageSync(‘token’);
let base_login_name = uni.getStorageSync(‘base_login_name’);
if (token && base_login_name) {
    //存在则关闭启动页进入首页
// #ifdef APP-PLUS
plus.navigator.closeSplashscreen();
// #endif
    } else {
//不存在则跳转至登录页
        uni.reLaunch({
            url: “/pages/index/login”,
    success: () => {
// #ifdef APP-PLUS
        plus.navigator.closeSplashscreen();
// #endif
    }
    })
    }
},
运行时发现会从登录页面闪一下才会进入首页,是因为app默认进入第一个页面(我开始设置的第一个页面是登录页),即使存在token也会从第一个页面闪一下再进入首页,这样的用户体验非常不好。
于是添加了plus.navigator.closeSplashscreen();并且设置了以下参数:
 如果不理解可以参考官方文档说明 https://uniapp.dcloud.io/collocation/manifest.html#splashscreen
 除此之外,还需要将app应用的第一个页面设置为首页(pages数组的第一项即为第一个页面)
 此时,启动app就可以实现我们想要的效果了。
如有问题,欢迎留言!!
————————————————
                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_50606255/article/details/123555667

import qs from ‘qs‘ qs库的使用_import qs from 'qs-CSDN博客

mikel阅读(124)

来源: import qs from ‘qs‘ qs库的使用_import qs from ‘qs-CSDN博客

1.npm地址

https://www.npmjs.com/package/qs

2、概述

将url中的参数转为对象;

将对象转为url参数形式

3、示例

  1. import qs from ‘qs’;
  2. const url = ‘method=query_SQL_dataset_data&projectId=85&appToken=7d22e38e-5717-11e7-907b-a6006ad3dba0’;
  3. // 转为对象
  4. console.log(qs.parse(url));
  5. const a = {name:‘hehe’,age:10};
  6. // 转为url参数形式
  7. console.log(qs.stringify(a))
// 控制台输出

参考:https://www.cnblogs.com/mengfangui/p/9081753.html

一套.NetCore+Vue+Uniapp前后端分离的低代码快速开发框架_c# 网站后端 低代码框架-CSDN博客

mikel阅读(207)

来源: 一套.NetCore+Vue+Uniapp前后端分离的低代码快速开发框架_c# 网站后端 低代码框架-CSDN博客

今天给大家推荐一个后端基于.NetCore+Vue前后端分离,移动端基于Uniap可发布IOS、Android、小程序、H5框架系统。

项目简介
这是一个基于.Net Core构建的简单、跨平台快速开发框架。前后端封装了上千个常用类,方便扩展;集成了代码生成器,支持前后端业务代码生成,实现快速开发,提升工作效率;框架集成了表单、表格、图表等各种常用的Demo方便直接使用;后端框架支持Vue2、Vue3。

技术架构
1、跨平台:这是基于.Net Core开发的系统,可以部署在Docker, Windows, Linux, Mac。

2、数据库支持:Microsoft SQL Server, PostgreSQL, MySQL, SQLite。

3、系统分为三端:后台管理系统、API、移动端Uniapp。

4、后端基于.Net Core + EFCore + Jwt +Dapper+signalR 开发。

5、前端基于Vue + iView + Element-ui开发。

项目结构

**后台管理系统
**
系统功能

1、低代码设计器:低代码设计器、表单配置、数据收集

2、消息推送:消息推送

3、流程管理:审批流程列表、可视化编辑流程

4、用户信息:用户管理、权限管理、角色管理、角色管理(Tree)

5、代码生成器:用户基础信息、表单设计、测试完整示例、配置管理、日志管理

6、系统设置:菜单设置、下拉框绑定设置

7、日志管理:系统日志

组件Demo

1、表单数据:基础只读表单、自动绑定下拉框、多弹出框上传、导入导出表单、编辑器表格换行、多列合并显示、在线表格编辑

2、一对多:主从一对一多个Demo、主从一对多弹出框、 从表图片上传

3、多页签/多表头:多页签、多表头

4、表单布局:单列表单、两列表单、多列表单自动数据源、Table+表单、表单只读

5、表单一对多:表单一对多table、混合表单一对多、表单+图表

6、图表表单:图表、图表表单、数字排版

7、table编辑:table编辑、api加载table数据

8、树形菜单:tree与代码生成页面、tree与自定义table数据、treetable

9、后台校验:后台参数校验

10、文件上传:文件上传、表单与上传下载

11、内容发布:编辑器、静态页面发布、静态页面列表

后台功能截图
低代码设计器

 

审批流程列表

 

可视化编辑流程

 

用户管理

 

权限管理

 

角色管理

 

代码生成器

 

菜单设置

 

下拉框绑定设置

 

基础只读表单

 

多列合并显示

 

在线表格编辑

 

主从一对一多个Demo

 

多页签

 

多表头

 

表单布局

 

表单一对多

 

图表表单

 

table编辑

 

树形菜单

 

后台校验

 

文件上传

 

编辑器

 

项目地址:https://github.com/cq-panda/Vue.NetCore
————————————————

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/daremeself/article/details/127522233

ASP.NET Core 中 HttpContext 详解与使用 | Microsoft.AspNetCore.Http 详解 - 痴者工良 - 博客园

mikel阅读(158)

来源: ASP.NET Core 中 HttpContext 详解与使用 | Microsoft.AspNetCore.Http 详解 – 痴者工良 – 博客园

笔者没有学 ASP.NET,直接学 ASP.NET Core ,学完 ASP.NET Core MVC 基础后,开始学习 ASP.NET Core 的运行原理。发现应用程序有一个非常主要的 “传导体” HttpContext 。

赶忙写一下笔记先。

目录

“传导体” HttpContext

操作 HttpContext 前期准备

HttpContext 类型的属性和方法

HttpContext 对象实践与测试


“传导体” HttpContext

要理解 HttpContext 是干嘛的,首先,看图

  图一 内网访问程序

图二 反向代理访问程序

 

ASP.NET Core 程序中,Kestrel 是一个基于 libuv 的跨平台 ASP.NET Core web 服务器。不清楚 Kerstrel 没关系,以后慢慢了解。

我们可以理解成,外部访问我们的程序,通过 Http 或者 Https 访问,例如 https://localhost:44337/Home/Index,需要通过一个网址,来寻向访问特定的页面。

访问页面时,会产生 Cookie、Seesion、提交表单、上传数据、身份认证等,外部与应用程序之间传导的导体就是 HttpContext

总之,客户端跟 Web应用程序交互 是通过 HttpContext 传导的。

 

原理

ASP.NET Core 本质是一个控制台程序!ASP.NET Core 程序并不直接监听请求,而是通过依赖 HTTP Server ,来实现把各自请求转发到应用程序中。这个被转发的请求相当于我们日常浏览网页、上传文件、提交表单等的网络请求,这些请求会被包装,然后组合到 HttpContext 中。

就好像顾客到餐厅吃饭

  1. 需要先点菜、提出服务要求
  2. 服务员把你的菜单、需求送到厨房
  3. 厨师在加工好食品
  4. 服务员再把食品递给你

HttpContext 相当于这个服务员,她在前、后传递信息。


操作 HttpContext 前期准备

一般来说,我们主要写好Web程序,而无需理会 数据是怎么传导的。就好像两台电脑能够发送资料,我们用不着知道他们是通过无线Wifi、光纤还是铜线电缆传输的。

当有需要时,自然需要用~ 废话少说,先简单操作 HttpContext 了解下。后面接着解析这个对象。

如果你不需要练习,请直接跳过这一节内容。

  • 打开 VS(2017)
  • 新建项目
  • ASP.NET Core Web 应用程序
  • Web应用程序(模型视图控制器)
  • 打开 Startup.cs ,在 ConfigureServices 中,加上
1
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); //先不用管这个是干嘛的

  •  打开 HomeController.cs ,在顶部 using Microsoft.AspNetCore.Http; 把 HomeController 类替换成以下代码
    复制代码
      public class HomeController : Controller
        {
            private IHttpContextAccessor _accessor;
            public HomeController(IHttpContextAccessor accessor)
            {
                _accessor = accessor;
            }
            [HttpGet]
            public IActionResult Index(int? id)
            {
                var httpcontext = _accessor.HttpContext;
    
                return View(httpcontext);
            }
    
        }
    复制代码

     

  • 打开 Views/Home 目录,删除除 Index.cshtml 外的其它视图
  • 把 Index.cshtml 的代码改成
@model Microsoft.AspNetCore.Http.HttpContext
@{
    Layout = null;
}

到这里,准备已经完成。

以上代码的作用是把 HttpContext 对象 传递到 视图 中,直接在视图中使用。这样我们在理解时,只需在视图测试即可。


 HttpContext 类型的属性和方法

在 ASP.NET Core 中,系统为每一个请求分配一个线程,HttpContext 针对的,就是一个线程。所以它的类、方法、属性等,都是针对当前请求起作用。

 

Properties(特性)

Authentication                这个已经用不到了,这里只是列一下表。

用于身份认证(ASP.NET中用到),官方不建议在ASP.NT Core中使用。替代方案 Microsoft.AspNetCore.Authentication.AuthenticationHttpContextExtensions

Connection 获取有关此请求的基础连接的信息
Features 获取此请求上可用的服务器和中间件提供的HTTP特性的集合
Items 获取或设置可用于在该请求范围内共享数据的键/值集合
Request 请求
RequestAborted 通知此请求基础的连接何时中止,因此请求操作应取消
RequestServices 获取或设置 IServiceProvider 集合,提供访问的请求的服务容器
Response 响应
Session 获取或设置用于管理此请求的用户会话数据的对象
TraceIdentifier 获取或设置用于在跟踪日志中表示此请求的唯一标识符
User 获取或设置此请求的用户
WebSockets 获取一个对象,该对象管理此请求的WebSu套连接的建立

Item、Session、Response 等对象都是需要经常使用到的,下面笔者会详细实践。

 


HttpContext 对象实践与测试

Request

用于获取用户请求的对象,浏览器向Web程序提交表单、访问的URL、URL中包含的查询字符串、报文请求头等等。

Body 获取或设置 RequestBody 流
ContentLength 获取或设置 Content-Length 头
ContentType 获取或设置Content-Type 头
Cookies 获取或设置 Cookies
Form 获取或设置 表单内容
HasFormContentType      Checks the Content-Type header for form types.
Headers Gets the request headers.
Host 获取或设置主机头。可以包括端口
HttpContext 获取或设置请求上下文
IsHttps 检测当前是否HTTPS连接
Method 获取或设置HTTP方法
Path 获取或设置当前请求的路径,即URL
PathBase 获取或设置 RequestPathBase,就是URL前面那一段,如https://docs.microsoft.com
Protocol Gets or sets the RequestProtocol.
Query 查询字符串的集合
QueryString 获取或设置用于在Request.Query中创建查询集合的原始查询字符串
Scheme 获取或设置HTTP请求方案

试一试

打开 Index.Cshtml ,把以下代码加上去

(为了看得清楚一点,我加了表格)

复制代码
<table>
    <tr>
        <td>RequestBody流</td>
        <td> @Model.Request.Body</td>
    </tr>
    <tr>
        <td>Content-Length头</td>
        <td>@Model.Request.ContentLength</td>
    </tr>
    <tr>
        <td>Content-Type头</td>
        <td> @Model.Request.ContentType</td>
    <tr>
        <td>Cookies </td>
        <td>@Model.Request.Cookies</td>
        </tr>
    <tr>
        <td>IsHttps</td>
        <td>@Model.Request.IsHttps</td>
        </tr>
    <tr>
        <td>Host </td>
        <td>@Model.Request.Host</td>
    </tr>

</table>
复制代码

运行Web程序,结果如下

在浏览器 F12 后,可以看到控制台的内容。请查看 下图的 1、3部分

 

 

Request 的其它使用方法,就不再赘述,你可以在视图中 @Model.Request. 加上需要测试的属性即可。

推荐别人关于 Request 的文章 https://www.cnblogs.com/Sea1ee/p/7240943.html


Response

Request 是 客户端向 Web 发送请求,而 Response 则是 Web 响应 客户端 的请求。这里笔者就不全部翻译了

使用Response可以直接影响服务器响应,设置响应内容、响应类型(发送网页、文件、图片等)、视图响应前重定向。

Response 应该在控制器中使用。具体使用方法笔者这里就不赘述。

Body 获取或设置响应体流
ContentLength      Gets or sets the value for the Content-Type response header.
ContentType 获取或设置内容类型响应标头的值
Cookies 获取一个对象,该对象可用于管理此响应的Cookie
HasStarted Gets a value indicating whether response headers have been sent to the client.
Headers Gets the response headers.
HttpContext Gets the HttpContext for this response.
StatusCode Gets or sets the HTTP response code.

Response 的方法

     OnCompleted(Func<Task>)
在响应已发送到客户端之后添加要调用的委托
     OnCompleted(Func<Object,Task>, Object)           响应已发送到客户端之后添加要调用的委托
     OnStarting(Func<Task>) 在响应头将被发送到客户端之前添加要调用的委托
     OnStarting(Func<Object,Task>, Object) 在响应头将被发送到客户端之前添加要调用的委托
     Redirect(String) 向客户端返回一个临时重定向响应(HTTP 302)
     Redirect(String, Boolean) 向客户端返回重定向响应(HTTP 301或HTTP 302)
     RegisterForDispose(IDisposable) 处置(不可分)在请求完成处理后,注册主机处理的对象

Response 拓展方法

GetTypedHeaders(HttpResponse)
WriteAsync(HttpResponse, String, Encoding, CancellationToken) 取消令牌使用给定的编码将给定文本写入响应体
WriteAsync(HttpResponse, String, CancellationToken) 将给定文本写入响应体。UTF-8编码将被使用
Clear(HttpResponse)
SendFileAsync(HttpResponse, IFileInfo, Int64, Nullable<Int64>, CancellationToken)      使用Sendfile 扩展发送给定的文件
SendFileAsync(HttpResponse, IFileInfo, CancellationToken) Sends the given file using the SendFile extension.
SendFileAsync(HttpResponse, String, Int64, Nullable<Int64>, CancellationToken) Sends the given file using the SendFile extension.
SendFileAsync(HttpResponse, String, CancellationToken) Sends the given file using the SendFile extension.

请参考下图的第 2 部分

 


Item

如果你使用过 ViewData,就不难理解 HttpContext.Item

HttpContext.Item 是一个字典集合类型,具体类型为 IDictionary<TModel,TModel>。它的使用方法像 ViewData。(不要跟我说说你不知道 ViewBag、ViewData 是什么~)

打开 Index.Cshtml ,用下面代码复制替换

复制代码
@model Microsoft.AspNetCore.Http.HttpContext
@{
    Layout = null;
}
@{
    List<string> i = new List<string>();
    i.Add("a");
    i.Add("b");
    i.Add("c");
    i.Add("d");
    i.Add("e");
    i.Add("f");
    i.Add("g");
    i.Add("h");
    i.Add("i");

    Model.Items["Test"] = i;       
    /*
        Model.Items 是字典类型
        这里设置 键 Test
                 值 i ,它的值是 List<string> 类型
    */

foreach(var item in Model.Items["Test"] as List<string>) //字典类型,必须先用 as 转为对应类型
{
    <br> @item
    
}
}
复制代码

结果

可以用 HttpContext.Item  来存储当前请求的意向有用的数据。


HttpContext 的其它方法使用这里不再赘述,需要注意的是,HttpContext 是针对一个请求的而产生的。

uni-app发布 h5 与ASP .NET MVC 后台 发布 到 IIS的同一端口 并配置跨域_uniapp发布h5部署iis-CSDN博客

mikel阅读(162)

来源: uni-app发布 h5 与ASP .NET MVC 后台 发布 到 IIS的同一端口 并配置跨域_uniapp发布h5部署iis-CSDN博客

iis 安装URL重写

在这里插入图片描述

选择对应的后台项目,进行url重写

编辑【模式】部分的内容的重写规则,我这里是h5中请求的前缀是api,大家可以根据自己的前缀进行修改。
编写【操作类型】为重写,并写重写url,按照图中设置即可。
在这里插入图片描述

uni-app web发布配置

在这里插入图片描述

在这里插入图片描述

uni-app项目打包成H5部署到服务器(超详细步骤)_uni-app unpackage-CSDN博客

mikel阅读(174)

来源: uni-app项目打包成H5部署到服务器(超详细步骤)_uni-app unpackage-CSDN博客

咳咳, 第一次写博客, 有点激动, 昨天get了一个新技能, 也是我之前一直最不懂的一块, 就是项目做完后如何部署到服务器,昨天尝试了部署uni-app项目到测试服务器, 成功之后很开心, 后面又自己上网学了下怎么部署vue项目, 所以这篇会讲怎么部署uni-app项目, 下一篇讲怎么部署vue项目, 好, 上操作

一 ,打包项目
HBuilderX下载地址: https://www.dcloud.io/hbuilderx.html

1 , HBuilderX打开你的uni-app项目 — > 点发行 – > 网站 – PC Web或手机H5

 

2 , 点完之后会弹出一个框, 填写网站标题和和域名之后点发行

 

3 , 点完之后控制台会显示正在编译中… , 稍等一会

 

4, 打包成功 , 生成了unpackage文件夹, 打包好的文件存放在里面

 

二 , 用一个工具, 把打包好的文件上传到你的服务器 , 我用的是Xftp , 用别的工具也可以
Xftp下载链接:https://pan.baidu.com/s/1z7-AYhinrWR3qIuZTkk0XQ
提取码:cn6m

 

1, 打开Xftp , 点小窗口的新建

 

2 , 点完之后弹出这个框, 填写完信息之后点连接 , 服务器的相关信息问公司的人要

 

3 , 点完连接之后 , 弹出这个框 , 点接受并保存

 

4 , 然后会看到右侧出现了新建会话的窗口 , 表示连接到服务器了,

左侧是你自己的电脑本地 , 右侧是服务器电脑

左侧进到刚刚打包好的文件存放路径 , unpackage/dist/build/h5 , 把static文件夹和index.html 复制到右侧服务器中部署的文件夹里 , 看你们是部署到哪个文件夹就拖到哪里

 

5 , 部署成功 !! 打开浏览器,输入服务器ip地址,访问一首页的内容吧 ^_^

地址就是 服务器ip/部署的文件夹/ , 比如 服务器ip是123.60.120.40:3006 ,部署的文件夹名字是project , 地址就是如下

http://123.60.120.40:3006/project/
————————————————

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/weixin_49577940/article/details/118058899

uView 2.0版本 http请求封装_uni.$u.route-CSDN博客

mikel阅读(117)

来源: uView 2.0版本 http请求封装_uni.$u.route-CSDN博客

config/config.js写入

// 此vm参数为页面的实例,可以通过它引用vuex中的变量
module.exports = (vm) => {
	// 初始化请求配置
	uni.$u.http.setConfig((config) => {
		/* config 为默认全局配置*/
		config.baseURL = ''; /* 根域名 */
		return config
	})

	// 请求拦截
	uni.$u.http.interceptors.request.use((config) => { // 可使用async await 做异步操作
		// 初始化请求拦截器时,会执行此方法,此时data为undefined,赋予默认{}
		config.data = config.data || {}
		config.header['Content-Type'] = 'application/x-www-form-urlencoded'
		// console.log(uni.getStorageSync('storage_key'))
		// 根据custom参数中配置的是否需要token,添加对应的请求头
		if (uni.getStorageSync('storage_key')) {
			// 可以在此通过vm引用vuex中的变量,具体值在vm.$store.state中
			config.header.token = uni.getStorageSync('storage_key').token.token
		}
		return config
	}, config => { // 可使用async await 做异步操作
		return Promise.reject(config)
	})

	// 响应拦截
	uni.$u.http.interceptors.response.use((response) => {
		/* 对响应成功做点什么 可使用async await 做异步操作*/
		const data = response.data
		console.log(response.statusCode)
		// 自定义参数
		// const custom = response.config?.custom
		if (data.code != 1) {
			// 如果没有显式定义custom的toast参数为false的话,默认对报错进行toast弹出提示
			if (data.msg) {
				uni.$u.toast(data.msg)
			}
			// // 如果需要catch返回,则进行reject
			// if (custom?.catch) {
			// 	return Promise.reject(data)
			// } else {
			// 	// 否则返回一个pending中的promise,请求不会进入catch中
			// 	return new Promise(() => {})
			// }
			
		}
		return data === undefined ? {} : data
	}, (response) => {
		// 对响应错误做点什么 (statusCode !== 200)
		if(response.statusCode==401){
			uni.$u.route('/pages/jy_Sign/jy_Sign')
		}
		return Promise.reject(response)
	})
}

config/api.js封装

const http = uni.$u.http
import qs from 'qs'
export const restlist = (params, config = {}) => http.post('/api/ebook/restlist', qs.stringify(params), config)

引入配置

main.js引入

// 引入请求封装,将app参数传递到配置中
require('./config/request.js')(app)
app.$mount()
使用
import {
		restlist
	} from '../../config/api.js'
	
	getdata() {
				var that = this;
				that.page = 1;
				this.status='loading'
				var data = {
					page: this.page,
					keywords: this.selected,
				};
				restlist(data).then(res => {
					this.status='loadmore'
					if (res.code == 1) {
						that.list = res.data
					} else {
						uni.showToast({
							title: res.msg,
							icon: 'none',
							duration: 2000
						});
					}
				}).catch(err => {

				})
			},
			getmore() {
				var that = this;
				that.page = that.page + 1;
				that.status = 'loading';
				let data = {
					page: this.page,
					keywords: this.selected,
				};
				restlist(data).then(res => {
					var data = res.data;
					if (!data || data.length == 0) {
						that.status = 'nomore';
					}
					for (var i = 0; i < data.length; i++) {
						that.list.push(data[i]);
					}
				}).catch(err => {

				})
			},

request

// 此vm参数为页面的实例,可以通过它引用vuex中的变量
import configs from './config.js'
import {
	fungoPreviousPage
} from "@/utils/util.js"
module.exports = (vm) => {
	// 初始化请求配置
	uni.$u.http.setConfig((config) => {
		/* config 为默认全局配置*/
		config.baseURL = configs.baseUrl; /* 根域名 */
		return config
	})

	// 请求拦截
	uni.$u.http.interceptors.request.use((config) => { // 可使用async await 做异步操作
		config.header['Content-Type'] = 'application/json'
		config.data = config.data || {}

		// 根据custom参数中配置的是否需要token,添加对应的请求头
		config.header['cookie'] = uni.getStorageSync('cookie')
		// if (config?.custom?.auth) {
		// 	if (uni.getStorageSync('cookie')) {
		// 		// 可以在此通过vm引用vuex中的变量,具体值在vm.$store.state中
		// 	} else {
		// 		uni.redirectTo({
		// 			url: '/pages/login/wxlogin'
		// 		})
		// 	}
		// }
		return config
	}, config => { // 可使用async await 做异步操作
		return Promise.reject(config)
	})

	// 响应拦截
	uni.$u.http.interceptors.response.use((response) => {
		/* 对响应成功做点什么 可使用async await 做异步操作*/
		const data = response.data
		if (response.header['Set-Cookie']) {
			// Set-Cookie字符串获取
			var cookies = response.header['Set-Cookie']
			// 字符串分割成数组
			var cookieArray = cookies.split(/,(?=[^,]*=)/)
			// 分号拼接数组
			var newCookie = cookieArray.join(';')
			uni.setStorageSync('cookie', newCookie)
		}
		// 自定义参数
		// const custom = response.config?.custom
		if (data.code != 200) {
			// 如果没有显式定义custom的toast参数为false的话,默认对报错进行toast弹出提示
			if (data.message) {
				uni.$u.toast(data.message)
			}

			if (data.code == 401) {
				// uni.clearStorageSync()
				fungoPreviousPage()
				uni.$u.route('/pages/login/wxlogin')
			}
			if (data.code == 602) {
				// uni.clearStorageSync()
				fungoPreviousPage()
				uni.$u.route('/pages/login/wxlogin')
			}
		}
		return data === undefined ? {} : data
	}, (response) => {
		// 对响应错误做点什么 (statusCode !== 200)
		if (response.statusCode == 401) {
			fungoPreviousPage()
			uni.$u.route('/pages/login/wxlogin')
		}
		return Promise.reject(response)
	})
}