首页
工具
心境语句
相册
建站轨迹
关于
Search
1
微信小程序:计算属性的两种体现方式及应用场景
1,621 阅读
2
Antd Upload 组件上传文件接收数据流并下载
1,112 阅读
3
[C#]使用dnSpy对目标程序(EXE或DLL)进行反编译修改并编译运行
590 阅读
4
C#插件火车头采集器动态切换代理IP,及自动切换UserAgent
583 阅读
5
ADODB.Connection 错误 800a0e7a 未找到提供程序。该程序可能未正确安装解决方法
529 阅读
react
typecho
ASP
Centos
MYSQL
PHP
Sql server
Javascript
nodejs
数据采集
.NET
git
编程算法
管理及流程
Vue
微信小程序
android
python
mongodb
登录
Search
标签搜索
kotlin
node-sass
nuxtjs
C#火车头插件
火车头采集器
火车头代理
C#反编译
程序逆向
dnSpy教程
Antd
InputNumber
NPM教程
NPM命令
rrweb教程
git慢
git镜像
vim命令
git命令
网页音乐插件
网页播放器
Elysian
累计撰写
74
篇文章
累计收到
0
条评论
首页
栏目
react
typecho
ASP
Centos
MYSQL
PHP
Sql server
Javascript
nodejs
数据采集
.NET
git
编程算法
管理及流程
Vue
微信小程序
android
python
mongodb
页面
工具
心境语句
相册
建站轨迹
关于
搜索到
74
篇与
Elysian
的结果
2022-03-09
解决项目执行 npm install (yarn)的时候报 node-sass 错误
项目执行 npm install 或 yarn 的时候经常遇到 node-sass 下载错误, sass_binary 无法下载,或者提示让你安装 python ( 安装python这个提示有点扯, 严重误导人, 以下详述 ),还有很多其他千奇百怪的说法,照着试了一大堆之后发现一个有用的都没有。对于 node-sass ,如果通过以下设置已经解决了问题,那基本上能判断出来是网络原因了。但后面的内容我仍然建议你看一看。set SASS_BINARY_SITE=https://npm.taobao.org/mirrors/node-sass/ && npm install node-sass如果这种办法尝试几次还不行, 基本可以排除网络原因了, 可能是你所使用 node-sass 依赖的版本跟电脑上安装的 node.js 版本不对应导致的.因为项目所需要的 sass_binary 的版本是由 node 的版本和项目中依赖的 node-sass 版本共同决定的。然而有时候错误的版本并没有与之对应的 sass_binary 文件,那么解决问题的关键就在于选对 node 和 node-sass 的版本。怎么确定项目所需的 sass_binary 的版本呢? 首先通过 node -v 查看电脑中已安装 node 的版本,然后在 https://nodejs.org/zh-cn/download/releases/ 页面的表格中找到这个版本的 node ,在 NODE_MODULE_VERSION 这一列中指定了该版本 node 对应的 node-sass 的 SASS_BINARY 版本。举例来说,假设电脑中安装的 node 版本号是 v14.15.4,它对应的 NODE_MODULE_VERSION 是 83,那么我们再到项目中的 package.js 和 yarn.lock (如果有)找到 node-sass 的版本,我的项目中使用的 node-sass 版本是 v4.13.0 ,至此我们就能得到项目所需要的 sass_binary 文件名为 node-sass@v4.13.0 版本中的 win32-x64-83_binding.node(其它操作系统同理),然后通过 https://npm.taobao.org/mirrors/node-sass 找到对应的 node-sass 版本,进入文件夹内查找 win32-x64-83_binding.node 发现该文件并不存在 ( 我们看到在 node-sass@v4.13.0 中最大的 binding 文件版本才到 79 ), 这才是在执行 npm Install 时报错的根本原因:项目试图下载一个不存在的文件。这时候就需要修改 node-sass 依赖的版本号了,原则是在不跨越大版本的前提下,我们优先在最接近 ( 步子迈太大怕扯到蛋 ) 当前所使用的 node-sass 更新版本中查找有没有这个 binding 文件,如果有,那么就优先使用这个版本即可,如果还没有,那就继续往后找。比如我一直到 node-sass@v4.14.0 的文件夹中才找到有对应的 win32-x64-83_binding.node 文件,那么我们就在项目中重新安装使用这个版本的 node-sass 即可。需要注意的是移除旧版本和安装新版本最好是通过命令操作,否则在使用 yarn.lock 锁定了项目依赖版本的情况下无法正常更新版本。 如果在安装过程中仍然报错,那就先把之前的 node_modules 文件夹删掉再重新安装一次。至此, 我们的项目应该就可以正常安装依赖并启动了。补充:截止发文时我们看到 nodejs 官网中 "当前发布版" 是 v16.0.0, 通过之前的链接查询发现,此版本 nodejs 对应的 NODE_MODULE_VERSION 版本都™到 93 了我们再到 GayHub 看看, 此时 node-sass 最后一个 release 版本是 5.0.0, 下方的版本日志清楚地写着支持的 node 版本为 10, 12, 14, 15, 并没有说支持最新的 nodejs v16, 而且在 Assets 中也没有找到有对应的 win32-x64-93_binding.node 文件. (这就是你使用 node 当前发布版的后果, 所以千万不要随意升级 nodejs, 就算要升也要使用长期支持版, 切忌使用当前发布版)(至此我们也许可以猜测一下有人让安装 python,莫非是想要让我们自己来编译生成所需要的 binding.node 文件?未作相关了解,有兴趣的可以一起在评论区交流)通过这个问题我们知道了更高版本的 nodejs 需要更高版本的 node-sass, 因此升级了 nodejs 之后可能不再与项目中的旧版本的 node-sass 兼容, 这时候还要升级所有不兼容的 node-sass, 要么就尽量不要手欠随意升级电脑上的 nodejs 的版本, 以免不必要的麻烦. 以前我就是这样, 每次闲的蛋疼的时候就去 nodejs 官网升级版本, 升级的还不是长期支持版本, 而是最新发布版本 (以前的自己是多么的无知). 如此导致的问题就是每次启动项目的时候报一大堆错误然后启动失败, 而且网上还找不到靠谱的答案. 至于 python 的提示,其实都是同一个问题,只要找到了有效的 binding 文件,这个问题也就随之解决了。很多人看见 python 的提示就去百度,按照网上说的方法下载 python,然后配置环境变量, 往往按照步骤操作到一半时忍无可仍最终放弃, 继而再去找别的方法. 其实根本就不是这个原因,最根本的问题是解决依赖的版本,而不是去搞 python。我们只是在开发一个web项目,怎么还跟 python 扯上关系了,看到这种回答我就越想越奇怪?回想一下以前能正常运行的时候,我们的电脑上也并未安装过python,更没有配置python环境的过程,这根本说不过去啊, 可能这也是我每次按照步骤配置python到一半就选择放弃的原因吧。说到底,要多思考, 不要人云亦云, 要搞清楚问题的根源,这样才能少走很多弯路。原文链接:https://blog.csdn.net/baobao_123456789/article/details/116047109
2022年03月09日
332 阅读
0 评论
0 点赞
2022-01-18
node进程管理工具PM2的安装和使用
一、简介PM2是node进程管理工具,可以利用它来简化很多node应用管理的繁琐任务,如性能监控、自动重启、负载均衡等,而且使用非常简单。二、前期必备node 环境npm三、安装全局安装npm install -g pm2四、入门教程挑express应用来举例。一般我们都是通过npm start启动应用,其实就是调用node ./bin/www。那么,换成pm2就是注意,这里用了–watch参数,意味着当你的express应用代码发生变化时,pm2会帮你重启服务(长时间监测有可能会出现问题,这时需要重启项目)pm2 start ./bin/www –watch五、常用命令启动参数说明: –watch :监听应用目录的变化,一旦发生变化,自动重启。如果要精确监听、不见听的目录,最好通过配置文件。-i –instances :启用多少个实例,可用于负载均衡。如果-i 0或者-i max,则根据当前机器核数确定实例数目。–ignore-watch :排除监听的目录/文件,可以是特定的文件名,也可以是正则。比如 –ignore-watch=”test node_modules “some scripts”“ -n –name :应用的名称。查看应用信息的时候可以用到。-o –output :标准输出日志文件的路径。-e –error :错误输出日志文件的路径。–interpreter :the interpreter pm2 should use for executing app (bash, python…)。比如你用的coffee script来编写应用。完整命令行参数列表:地址pm2 start app.js –watch -i 2 重启 pm2 restart app.js 停止停止特定的应用。可以先通过pm2 list获取应用的名字(–name指定的)或者进程id。pm2 stop app_name|app_id 如果要停止所有应用,可以pm2 stop all 删除 pm2 stop app_name|app_id pm2 stop all 查看进程状态 pm2 list 自动重启 pm2 start app.js –watch *这里是监控整个项目的文件日志查看除了可以打开日志文件查看日志外,还可以通过pm2 logs来查看实时日志。pm2 logs 更新pm2 pm2 save # 记得保存进程状态 npm install pm2 -g pm2 update 附pm2命令:$ npm install pm2 -g # 命令行安装 pm2 $ pm2 start app.js -i 4 # 后台运行pm2,启动4个app.js # 也可以把'max' 参数传递给 start # 正确的进程数目依赖于Cpu的核心数目 $ pm2 start app.js --name my-api # 命名进程 $ pm2 list # 显示所有进程状态 $ pm2 monit # 监视所有进程 $ pm2 logs # 显示所有进程日志 $ pm2 stop all # 停止所有进程 $ pm2 restart all # 重启所有进程 $ pm2 reload all # 0 秒停机重载进程 (用于 NETWORKED 进程) $ pm2 stop 0 # 停止指定的进程 $ pm2 restart 0 # 重启指定的进程 $ pm2 startup # 产生 init 脚本 保持进程活着 $ pm2 web # 运行健壮的 computer API endpoint (http://localhost:9615) $ pm2 delete 0 # 杀死指定的进程 $ pm2 delete all # 杀死全部进程 本文转自:https://www.cnblogs.com/bjgua/p/7656833.html
2022年01月18日
89 阅读
0 评论
0 点赞
2022-01-07
Nuxtjs,SSR解决服务端用户登录鉴权
Nuxt.js是基于在Vue.js的服务端渲染框架,能完美的解决SEO的问题,但同时权限认证成为了一大痛点,需要解决用户登录后,保存token,来验证后续的权限的问题。该处主要使用如下解决方法使用 nuxt/axios/proxy 代理,使前端和后端的接口的域名统一,因为需要使前后端的cookie共用。在登录的时候将登录信息的token和用户信息写入 cookie ,然后通过cookie传递给nuxtjs的服务端。服务端在 store/index.js 中,构建actions的nuxtServerInit,然后通过context参数中的request的headers拿到cookie中的登录信息。这样就可以实现nuxt的服务端用户信息。具体的部分核心代码提供如下,可以做下参考:store/index.jsconst store = new Vuex.Store({ modules, actions: { nuxtServerInit({ commit }, { req }) { let cookie = req.headers.cookie || ""; if (cookie.indexOf("token") > -1) { let token = ""; try { token = cookie.split(';').map(a => { var arr = a.split('='); return { key: arr[0], value: arr[1] }; }).filter(a => a.key === 'token')[0].value; } catch (e) { } if (token) { ajax.defaults.headers["token"] = token; } } } } }) export default () => store登录逻辑async loginIn() { if (!this.phone) { Toast("请输入验证码"); return; } const data = await this.$api.requestLoginInApi(this.phone, this.code); if (data.status === 0) { Toast(data.msg); return; } ajax.defaults.headers["token"] = data.token; window.localStorage.setItem("token", data.token); window.localStorage.setItem("userinfo", JSON.stringify(data.user)); document.cookie = "token=" + data.token; Toast("登陆成功"); this.onClose(); }以上代码中的ajax使用的是axios
2022年01月07日
317 阅读
0 评论
0 点赞
2021-12-28
vue继承vant实现支持下拉刷新上拉加载更多的瀑布流组件
组件背景需要实现瀑布流效果、使用的前端框架是基于vant的。瀑布流内容多种形式,除了图文还有标签形式。项目需要SSR。片寻网络,找到一个不错的瀑布流组件,基于它修改了部分内容(优化了数据获取方式,传递列表支持ssr,传递promise参数支持下拉刷新和上拉加载更多,修改内容部分,使用slot支持组件外部自定义内容格式)实现效果组件源码:<template> <div class="flow-box"> <div class="type-box" v-if="typeList && typeList.length"> <ul class="type-list"> <li @click="changeType(index)" v-for="(item, index) in typeList" :class="['type-item', typeIndex == index ? 'type-item-on' : '']" :key="index" > <div class="text">{{ item.name }}</div> <div class="line"></div> </li> </ul> </div> <van-pull-refresh v-model="isLoading" @refresh="onRefresh" style="min-height: 100vh" :success-duration="800" success-text="加载成功" loading-text="加载中..." > <van-list v-if="haveData == 2" v-model="loading" :finished="finished" finished-text="没有更多了" @load="onBottomLoad" :offset="150" :immediate-check="false" > <div class="data-list-box" id="data-list-box"> <div class="data-item" v-for="(item, index) in dataList" :style="{ width: boxWidth + 'px' }" :key="index" > <slot :item="item" :index="index"></slot> </div> </div> </van-list> </van-pull-refresh> </div> </template> <script> export default { props: ["dataSource", "promisefunc"], data() { return { typeList: [ //分类列表 // { name: "全部" }, // { name: "手机数码" }, // { name: "家用电器" }, // { name: "酒水饮料" }, // { name: "钟表珠宝" }, // { name: "美妆护肤" }, // { name: "运动户外" }, // { name: "汽车生活" }, ], typeIndex: 0, //分类索引 dataList: this.dataSource || [], //列表数据 haveData: 0, //是否有数据,1=无,2=有,0=页面还未初始化 pageIndex: 1, //页码 pageSize: 8, //每页加载数据数量 isLoading: false, //下拉刷新进行中,请求开始true, 请求完成false,用于下拉刷新组件van-pull-refresh loading: false, //上拉加载更多中,上拉触底时自动变成true, 请求完成设置为false, 用于列表组件van-list finished: false, //上拉加载是否加载完最后一页数,用于组件van-list itemCount: 0, //上一次加载完成后的瀑布流item个数 lastRowHeights: [0, 0], //最后一行标签的顶部间距+高度,2列 boxMargin: 15, //每个item之间的边距 boxWidth: 165, //每个item宽度 }; }, created() { if (process.server) { return; } this.$toast.loading({ message: "加载中...", duration: 0, }); //当前瀑布流设置为两列,计算瀑布流每个item和图片的宽度 //console.log("load", window.innerWidth); let screenWidth = window.innerWidth || 375; //屏幕宽度 this.boxWidth = (screenWidth - this.boxMargin * 3) / 2; //每个item的宽度 if (this.dataSource == null || !this.dataSource.length) { this.onRefresh(); //刷新数据 } else { this.pageIndex = 1; //重置第一页 this.finished = false; //上拉加载"所有数据已经完成"标识 重置为false this.dataList = []; this.loadImagesHeight(this.dataSource); } }, methods: { changeType(index) { //切换类型 if (this.typeIndex == index) return; this.$toast.loading({ message: "加载中...", duration: 0, }); this.typeIndex = index; this.onRefresh(); }, onRefresh() { //下拉刷新 // if (this.isLoading) return; //还在请求中,返回 this.pageIndex = 1; //重置第一页 this.finished = false; //上拉加载"所有数据已经完成"标识 重置为false //接口请求 this.getDataList(); }, onBottomLoad() { //上拉加载更多 if (this.finished) return; //说明所有数据已经加载完毕,返回 this.getDataList(); //下一页数据请求中 }, //数据请求 getDataList() { this.promisefunc({ page: this.pageIndex }) .then((res) => { let list = res ? res : []; if (list.length > 0) { //从list中取pageSize条数据出来 var tempList = []; for (let i = 0; i < this.pageSize; i++) { if (list.length > 0) { let tempIndex = parseInt(Math.random() * 1000) % list.length; tempList.push(list[tempIndex]); list.splice(tempIndex, 1); } } this.loadImagesHeight(tempList); //模拟预加载图片,获取图片高度 } else { this.loadImagesHeight(list); //处理数据 } }) .catch((res) => { //console.log("..fail: ", res); this.$toast.clear(); this.isLoading = false; //下拉刷新请求完成 this.loading = false; //上拉加载更多请求完成 }); }, loadImagesHeight(list) { var count = 0; //用来计数,表示是否所有图片高度已经获取 list.forEach((item, index) => { //创建图片对象,加载图片,计算图片高度 var img = new Image(); img.src = item.cover; img.onload = img.onerror = (e) => { count++; if (e.type == "load") { //图片加载成功 //计算图片缩放后的高度:图片原高度/原宽度 = 缩放后高度/缩放后宽度 list[index].imgHeight = Math.round( (img.height * this.boxWidth) / img.width ); // console.log('index: ', index, ', load suc, imgHeiht: ', list[index].imgHeight); } else { //图片加载失败,给一个默认高度50 list[index].imgHeight = 50; //console.log("index: ", index, ", 加载报错:", e); } //加载完成最后一个图片高度,开始下一步数据处理 if (count == list.length) { this.resolveDataList(list); } }; }); }, resolveDataList(list) { //处理数据 //下拉刷新,清空原数据 if (this.pageIndex <= 1) { this.itemCount = 0; this.dataList = []; this.lastRowHeights = [0, 0]; //存储每列的最后一行高度清0 } if (list.length >= this.pageSize) { this.pageIndex++; //还有下一页 } else { this.finished = true; //当前tab类型下所有数据已经加载完成 } //合并新老两个数组数据 this.dataList = [...this.dataList, ...list]; //判断页面是否有数据 this.haveData = this.dataList.length > 0 ? 2 : 1; // this.isLoading = false; //下拉刷新请求完成 // this.loading = false; //上拉加载更多请求完成 //console.log("...datalist: ", this.dataList); //console.log("...this.isLoading: ", this.isLoading); this.$nextTick(() => { setTimeout(() => { //渲染完成,计算每个item宽高,设置标签坐标定位 this.setItemElementPosition(); this.isLoading = false; //下拉刷新请求完成 this.loading = false; //上拉加载更多请求完成 }, 100); }); }, //获取每个item标签高度,设置item的定位 setItemElementPosition() { if (process.server) { return; } let parentEle = document.getElementById("data-list-box"); let boxEles = parentEle.getElementsByClassName("data-item"); for (let i = this.itemCount; i < boxEles.length; i++) { let tempEle = boxEles[i]; //上一个标签最小高度的列索引 let curColIndex = this.getMinHeightIndex(this.lastRowHeights); let boxTop = this.lastRowHeights[curColIndex] + this.boxMargin; let boxLeft = curColIndex * (this.boxWidth + this.boxMargin) + this.boxMargin; tempEle.style.left = boxLeft + "px"; tempEle.style.top = boxTop + "px"; this.lastRowHeights[curColIndex] = boxTop + tempEle.offsetHeight; // console.log('i = ', i, ', boxTop: ', boxTop, ', eleHeight: ', tempEle.offsetHeight); } this.itemCount = boxEles.length; //修改父级标签的高度 let maxHeight = Math.max.apply(null, this.lastRowHeights); parentEle.style.height = maxHeight + "px"; this.$toast.clear(); //console.log("...boxEles: ", boxEles.length, ", maxH: ", maxHeight); }, //获取数组中最小值的索引 getMinHeightIndex(arr) { var minHeight = Math.min.apply(null, arr); for (let i = 0; i < arr.length; i++) { if (arr[i] == minHeight) { return i; } } }, }, }; </script> <style lang="scss" scoped> .flow-box { background-color: #ffffff; width: 100vw; height: 100vh; } .flow-box .type-box { width: 100%; height: 40px; position: fixed; top: 0; font-size: 14px; background: #fff; color: rgba(0, 0, 0, 0.4); z-index: 99; border-bottom: 0.5px solid #dddddd; padding: 0 5px; } .type-box .type-list { white-space: nowrap; overflow-x: scroll; } .type-list .type-item { display: inline-block; padding: 0 12.5px; height: 40px; text-align: center; } .type-list .type-item .text { line-height: 37.5px; font-size: 14px; color: rgba(0, 0, 0, 0.4); margin: 0; } .type-list .type-item .line { background-color: #ffffff; } .type-list .type-item-on .text { font-size: 16px; color: #f0142d; } .type-list .type-item-on .line { width: 19px; height: 2px; margin: 0 auto; background-color: #f0142d; border-radius: 2px; } /* 隐藏滚动条 */ .type-list::webkit-scrollbar { display: none; } /* 列表数据样式 */ @keyframes data-item-ani { 0% { transform: scale(0.5); } 100% { transform: scale(1); } } .flow-box .data-list-box { position: relative; height: 100vh; /* margin-top: 40px; */ } .data-list-box .data-item { height: auto; position: absolute; background-color: #ffffff; /* box-shadow: 0px 0px 5px 2px rgba(0, 0, 0, 0.5); */ left: -1000px; animation: data-item-ani 0.4s; transition: left 0.6s, top 0.6s; transition-delay: 0.1s; } </style>使用方法<template> <Waterfall :dataSource="anlilist" :promisefunc="this.requestFunc || this.$api.requestZhuangxiuCase" > <template slot-scope="child"> <div class="hot-list" v-if="child.index === 5 && hotlist && hotlist.length" > <lookall :list="hotlist" /> </div> <div class="item-box"> <a href="/shop/" class="a"> <img :src="child.item.cover" class="data-cover" :alt="child.item.title" :style="{ width: '100%', height: child.item.imgHeight + 'px' }" /> <p class="p">{{ child.item.sign }}</p> <h3 class="h3">{{ child.item.title }}</h3> <i class="icon icon-an"></i> </a> <div class="news-list-info cf"> <a href="/shop/" class="source" ><img :src="child.item.iconimg" alt="" />{{ child.item.icontitle }}</a ><a href="" class="btn-zan">{{ child.item.count }}赞</a> </div> </div> </template> </Waterfall> </template> <script> import lookall from "~/components/jiajuhao/lookall.vue"; export default { components: { lookall, }, props: ["dataSource", "requestFunc", "hotlist"], data() { return { anlilist: this.dataSource || [], }; }, }; </script> <style lang="scss"> /* 全局样式 */ .hot-list { border-radius: 0.1rem; border: 1px solid #e5e5e5; overflow: hidden; background: #fff; padding: 0.35rem 0.2rem; margin-bottom: 0.25rem; .news-block { padding: 0; border: 0; h2 { border: 0; margin: 0; } ul { li { width: 100%; } } } } </style> <style lang="scss" scoped> .item-box { border-radius: 0.1rem; border: 1px solid #e5e5e5; overflow: hidden; background: #fff; .a { position: relative; display: block; height: auto; padding-bottom: 0.2rem; } .data-cover { margin-bottom: 0.1rem; display: block; } .p { padding: 0.05rem 0.2rem 0.1rem; font-size: 0.2rem; color: #999; } .h3 { padding: 0 0 0 0.2rem; font-size: 0.26rem; } .icon-an { width: 0.59rem; height: 0.33rem; background-position: 0 -2.5rem; position: absolute; top: 0; left: 0; } .data-name { font-size: 14px; padding: 5px 10px; text-align: left; } .news-list-info { margin: 0 0.1rem 0.1rem; } } </style>组件原地址转至:https://www.cnblogs.com/tandaxia/p/12189301.html
2021年12月28日
340 阅读
0 评论
0 点赞
2021-12-24
Nuxtjs优化建议
样式提取(将样式输出到一个样式文件中,ssr不显示在页面中)//nuxt.config.js配置文件修改配置 //官网介绍地址:https://www.nuxtjs.cn/api/configuration-build (搜索extractCSS) build: { extractCSS: true, },去掉多余的window.__NUXT__内容hooks: { 'vue-renderer:ssr:context'(context) { if (context?.nuxt?.error?.statusCode === 200) { const routePath = JSON.stringify(context.nuxt.routePath); context.nuxt = { serverRendered: true, routePath }; } } },该方法存在副作用,因为去掉了__NUXT__里面的内容,原本服务端传递给客户端的状态和数据都存在该位置,清除后页面再加载后客户端会再次请求asyncData里的请求,可能还会存在一些状态的问题,建议时候后多测试调优。
2021年12月24日
212 阅读
0 评论
0 点赞
1
...
5
6
7
...
15