前端 - 一问三不知 https://www.sapze.com Wed, 15 Feb 2023 03:14:34 +0000 zh-CN hourly 1 https://wordpress.org/?v=4.9.22 前端 - 一问三不知 https://www.sapze.com/net-core-new-repo.html Wed, 15 Feb 2023 03:14:34 +0000 https://www.sapze.com/?p=214 阅读全文 ]]> 在.net framework迁移到.net core的过程中,由于大量代码都是类似于 xxxRepo = new xxxRepo(),且在多线程中会造成连接丢失,所以暂定的修改方法为每次都直接UseSqlServer

public class BaseXXXContext: XXXContext
    {
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {
                var envName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
                IConfigurationRoot configuration = new ConfigurationBuilder()
                     .AddJsonFile("appsettings.json", optional: false)
                     .AddJsonFile($"appsettings.{envName}.json", optional: false)
                     .Build();

                optionsBuilder.UseSqlServer(configuration.GetConnectionString("XXXContext"));
            }
        }
    }
]]>
前端 - 一问三不知 https://www.sapze.com/axios-get-cross-origin.html Tue, 08 Feb 2022 07:25:53 +0000 https://www.sapze.com/?p=204 阅读全文 ]]> axios发送get请求报跨域的错误,用ajax的get方法不报错

axios的get请求报错是因为底层的实现方式跟jquery的ajax有所区别,jquery ajax的headers默认设置的content-type为application/x-www-form-urlencoded,axios默认为 application/json,而且axios会发送一个preflight来判断api是否可用,解决方式是修改axios的get请求的content-type,修改代码如下:

axios.interceptors.request.use(
    config => {
      if (config.method === 'get') {
        config.headers['Content-Type'] = 'application/x-www-form-urlencoded'
        return config
      }})
]]>
前端 - 一问三不知 https://www.sapze.com/chrome-content-download.html Sat, 09 May 2020 09:57:02 +0000 https://www.sapze.com/?p=196 阅读全文 ]]> 项目中使用uedbet下载功能时,要求api返回关键字uedbet下载的所有数据,最多可能有一万条左右,导致接口返回的数据渲染到页面需要很长的时间,使用chrome调试可以看到具体的加载时间。

前端使用vuejs加载数据,解决办法就是不用等到所有数据加载完成,类似下载功能一样,下载一部分就加载一部分数据,我们在onDownloadProgress里面返回已经下载的数据就行了,如下:
调用接口:

search (keywords, doAction) {
    cancelRequest()
    const data = {
      keywords: keywords
    }
    return new Promise((resolve, reject) => {
      axios({
        method: 'POST',
        url: 'search',
        data: data,
        dataType: 'json',
        cancelToken: new CancelToken(function executor (c) {
          cancel = c
        }),
        onDownloadProgress (progress) {
          doAction(progress.currentTarget.response)
        }
      })
        .then(response => {
          // resolve(response)
        })
        .catch(() => {})
    })
  }

处理数据:

hotel.search(key, function (json) {
    // 返回的数据可能不完整,所以需要替换一些特殊字符,让整个字符串可以转成json
            var willLoadJsonStr = json
              .replace('{"status":"Success","message":"","data":{"hotels":[', '')
              .replace(']}}', '')
            // 分割字符串,让每一段字符串都是一个对象
            var destArr = willLoadJsonStr.split('},{')
            for (var di = 0; di < destArr.length; di++) {
              var destStr = (di == 0 ? '' : '{') + destArr[di] + '}'
              if (root.isJSON(destStr)) {
                let destJson = JSON.parse(destStr)
                // 跳过已经添加的数据
                if (root.lstProperties.filter(a => a.hotelId == destJson.hotelId).length > 0) {
                  continue
                }

                root.lstProperties.push(destJson)
                root.setDestSectionElement(key, destJson)
              }
            }
          })
          .then(function (json) {
            // console.log(json)
          })
          .catch(error => {
          });

这样处理之后不管api返回多大的数据,页面都可以很快的响应。

]]>
前端 - 一问三不知 https://www.sapze.com/20200216.html Sun, 16 Feb 2020 08:04:38 +0000 https://www.sapze.com/?p=193 gulp项目中偶尔不能自动生成js文件,需要使用tsc手动生成文件
tsc --build tsconfigs/Common/tsconfig.json

]]>
前端 - 一问三不知 https://www.sapze.com/semantic-ui-dropdown.html Thu, 18 Jul 2019 03:31:36 +0000 https://www.sapze.com/?p=179 阅读全文 ]]> 由于项目需要对dropdownuedbet下载结果进行高亮处理,但是目前的semantic ui没有对应的接口可以调用,所以不得不对源码进行一些修改,这里只用作记录,避免将来代码被覆盖的时候找不回修改的部分。

需求如下:

semantic-ui的dropdown源码在/semantic/src/definitions/modules/dowpdown.js.

我们在第805行添加处理字符串的代码:

// 上一个uedbet下载条件的html标签对当前字符串有影响,需要清理上一个的结果
var originalHtml = $(this).html().toString()
                                  .replace(/<strong>/g, '')
                                  .replace(/<\/strong>/g, '');
// 忽略大小和html标签,替换uedbet下载的字符串,并加上特殊的html,我这里用的是strong
var newHtml = originalHtml.replace(new RegExp(searchTerm + "(?![^<>]*>)", "ig"), function(e){
  return '<strong>' + e + '</strong>';
});
// 替换当前的html,由于添加了strong标签,所以下一次uedbet下载需要清理掉对应的标签
$(this).html(newHtml);

注意第794行的条件,if( module.has.query() ),也就是清空uedbet下载内容后,这部分为空,之前的加粗标签在显示所有下拉选项的时候并没有被清理,所以需要在之后添加else处理没有uedbet下载内容的情况。

// 方法很简单,遍历所有item并删掉strong标签即可
$item
  .each(function(){
    var defaultText = $(this).html().toString()
                      .replace(/<strong>/g, '')
                      .replace(/<\/strong>/g, '');
    $(this).html(defaultText)

    return true;
  })
;

另外,由于项目中dropdown进行了分组显示,uedbet下载结果中如果itemgroup没有对应的内容,需要对itemgroup进行隐藏处理。

$item
  .not(results)
  .length === $item.length
  ? $item.parent().addClass(className.filtered)  // 如果uedbet下载结果为空,itemgroup添加filtered的样式
  : $item.parent().removeClass(className.filtered)  // 如果uedbet下载结果不为空,itemgroup删除filtered样式
;

项目中的html格式如下,具体的显示样式需要单独处理,比如strong标签取消加粗、修改颜色等:

<div class="ui selection dropdown search">
    <div class="text">Click to search</div>
    <div class="menu">
        <div class="itemgroup">
            <label>San Francisco</label>
            <div class="item">
                <span>San Francisco, International Airport</span>
                <span>SFO</span>
            </div>
            <div class="item">
                <span>Normal Y. Mineta San Jose International Airport</span>
                <span>SJC</span>
            </div>
        </div>
        <div class="itemgroup">
            <label>San Francisco</label>
            <div class="item">
                <span>San Francisco, International Airport</span>
                <span>SFO</span>
            </div>
            <div class="item">
                <span>Normal Y. Mineta San Jose International Airport</span>
                <span>SJC</span>
            </div>
        </div>
    </div>
</div>
]]>
前端 - 一问三不知 https://www.sapze.com/typescript-jquery-ios-uitableview.html Fri, 23 Mar 2018 08:49:48 +0000 http://www.sapze.com/?p=147 阅读全文 ]]> TypeScript结合jQuery制作的仿iOS的UITableView控件,支持点击、滑动删除、修改功能。可用于移动端APP的前端开发使用。

以下代为都是从项目中抽出来的,所以可能缺少部分图标和字体,需要稍作修改。

TypeScript
export default class AppTable {

    private selectEvent: Function;
    private removeEvent: Function;
    private editEvent: Function;

    constructor(selectEvent?: Function, removeEvent?: Function, editEvent?: Function) {
        this.selectEvent = selectEvent;
        this.removeEvent = removeEvent;
        this.editEvent = editEvent;

        this.init();
    }

    private init(): void {
        var lines = $(".apptable .row");
        var len = lines.length;
        var lastX: number;
        var lastXForMobile: number;

        // 按钮的宽度
        var buttonWidth = $(".apptable .row .action").width();
        // 用于记录被按下的对象
        var pressedObj: any;  // 当前左滑的对象
        var lastLeftObj: any; // 上一个左滑的对象

        // 用于记录按下的点
        var start: { x: number, y: number };
        // 偏移的值
        var offsetX = 0;
        // 当前编辑的索引
        var currentIndex = 0;

        for (var i = 0; i < len; ++i) {
            lines[i].addEventListener('touchstart', function (e) {
                lastXForMobile = e.changedTouches[0].pageX;
                pressedObj = this;
                currentIndex = $(this).index();
                var touches = e.touches[0];

                start = {
                    x: touches.pageX,
                    y: touches.pageY
                };
                offsetX = parseInt($(this).css('marginLeft'));
            });

            lines[i].addEventListener('touchmove', function (e) {
                var touches = e.touches[0];
                var delta = {
                    x: touches.pageX - start.x,
                    y: touches.pageY - start.y
                };

                if (Math.abs(delta.x) > Math.abs(delta.y)) {
                    e.preventDefault();
                }
                if (delta.x < 0) {
                    $(this).attr("style", "margin-left:" + delta.x + "px");
                } else {                    
                    if (offsetX < 0 && (offsetX + delta.x) < 0) {
                        $(this).attr("style", "margin-left:" + (offsetX + delta.x) + "px");
                    }
                }
                if (lastLeftObj && pressedObj != lastLeftObj) {
                    $(lastLeftObj).animate({ marginLeft: "0" }, 500);
                    lastLeftObj = null;
                }
            });

            lines[i].addEventListener('touchend', function (e) {
                if (lastLeftObj && pressedObj != lastLeftObj) {
                    $(lastLeftObj).animate({ marginLeft: "0" }, 500);
                    lastLeftObj = null;
                }
                var diffX = e.changedTouches[0].pageX - lastXForMobile;
                if (diffX < -60) {
                    $(pressedObj).animate({ marginLeft: "-" + buttonWidth + "px" }, 500); // 左滑
                    lastLeftObj && lastLeftObj != pressedObj &&
                        $(lastLeftObj).animate({ marginLeft: "0" }, 500);
                    lastLeftObj = pressedObj;
                } else if (diffX > 60) {
                    if (pressedObj == lastLeftObj) {
                        $(pressedObj).animate({ marginLeft: "0" }, 500);
                        lastLeftObj = null;
                    }
                } else {
                    $(pressedObj).animate({ marginLeft: "0" }, 500)
                }
            });
        }
        // 选中事件
        $(".apptable .section").click(
            () => this.selectEvent(currentIndex)
        );
        // 删除事件
        $(".apptable .row .action .delete").click(
            () => this.removeEvent(currentIndex)
        );
        // 编辑事件
        $(".apptable .row .action .edit").click(
            () => this.editEvent(currentIndex)
        );
    }
}
Html
<div class="apptable">
    <div class="row">
        <div class="section">
            <div><i class="icon-livingroom"></i><span>ET HOME - LIVING ROOM</span></div>
            <div><span>19.5°c</span><span><i class="icon-temperature"></i>32°</span></div>
        </div>
        <div class="action">
            <a class="delete">Delete</a>
            <a class="edit">Edit</a>
        </div>
    </div>
    <div class="row">
        <div class="section">
            <div><i class="icon-bedroom"></i><span>ET HOME - BEDROOM PURIFIER 01</span></div>
            <div><span>22°c</span><span><i class="icon-temperature"></i>19°</span></div>
        </div>
        <div class="action">
            <a class="delete">Delete</a>
            <a class="edit">Edit</a>
        </div>
    </div>
    <div class="row">
        <div class="section">
            <div><i class="icon-office"></i><span>ET HOME - BEDROOM PURIFIER 01</span></div>
            <div><span>22°c</span><span><i class="icon-temperature"></i>19°</span></div>
        </div>
        <div class="action">
            <a class="delete">Delete</a>
            <a class="edit">Edit</a>
        </div>
    </div>
</div>
CSS
.apptable {
    overflow:hidden;
    >.row{
        border-bottom: 1px solid rgba(12,0,51,.25);
        padding: 1rem 0 0 0rem;
        position: relative;
        width:100%;

        &:last-of-type{
            border-bottom:none;
        }
        span{
            font-family: "FiraSans";
            font-weight: 300;
            color: rgba(0,0,0,0.5);
        }
        i{
            zoom: 30%;
            float: left;
            opacity: 0.7;
        }
        >.section{
            margin-left:1rem;
            >div:first-of-type{
                >span{
                    font-size: 1.14rem;
                    line-height: 1.5rem;
                    margin-left: .5rem;
                }
            }
            >div:last-of-type{
                margin-top:0.5rem;
                position: relative;

                >span:first-of-type{
                    font-size: 3.2rem;
                }
                >span:last-of-type{
                    float: right;
                    position: absolute;
                    right: 1rem;
                    bottom: 1rem;
                }
            }
        }
        >.action{
            position: absolute;
            left: 100%;
            top: 0;
            height: 100%;
            width:12rem;

            >a{
                display: flex;
                justify-content: center;
                flex-direction: column;
                font-family: "FiraSans";
                font-weight: 300;
                height: 100%;
                text-align: center;
                float: left;
                font-size:1.28rem;
                color: #fff;
                width:6rem;
                &.delete{                    
                    background-color: rgb(255,98,101);
                }
                &.edit{                    
                    background-color: rgb(155,155,155);
                }
            }
        }
    }
}
]]>