zoukankan      html  css  js  c++  java
  • 用vue的抽象组件来做一个防止img标签url为空或url地址出错的验证

    看了网上文章学习了下vue的抽象组件,感觉就跟react的高阶组件一样的使用场景,只是更加面向vue的底层编程
    ,网上介绍的抽象组件一般有2种用法,1 用来加防抖和节流 2 用来控制按钮是否允许点击做权限效验,这2个对于
    目前我所做的一些项目用处不大,这里先介绍下我用抽象组件的使用场景,总不能说学习了抽象组件不管是否适用就
    强行加到项目里吧。。。

    1. 基本上公司项目所有用到动态地址的地方都要做2个效验,1 判断这个从后台返回的url是否为空,相信大家
         经常写这种代码 :src="imgUrl|| defUrl", 2 如果这个地址存在,那么还要做验证,防止地址报错,这个
         代码大家也经常写吧  @error="fixUrl"。 如果每个用动态img的地方都这么写,一个项目下来我都要吐了。
    
    2. 就算你愿意这么写,还是有一个问题,在 @error="fixUrl"里,一般的处理方式是在方法里把imgUrl替换成
      defUrl,这样就会有另一个问题,显示的图片是出来了,但是如果你的imgUrl不仅用来展示要在其他地方用,你总不能
      拿替换过的imgUrl用在其他地方吧,针对这种情况,大部分人(之前的我)的处理情况就是要2套数据放到data里,一套用来
      展示,一套用来内部传值使用,很不优雅对吧。
    
    3. 我也想过,做一个组件,然后所有需要验证的地方都不用img都用这个img组件,但是img的样式,和绑定的方法,这些你都要
      从外边取,然后绑定到真实img上,我只想处理个图片验证啊,怎么还有这么多需要兼容的地方要关注,好麻烦啊。
    

    所以遇到了抽象组件,稍微思考了一下,觉得可以完美解决以上3个问题。真香,直接看抽象组件的代码吧。

    
    <script>
    export default {
        name: "imgFix",
        abstract: true, //标记为抽象组件
        props: {
            // 要替换的图片,如果是服务器下的写url地址,public目录下的写地址记得加process.env.BASE_URL,原因请看
            // https://www.cnblogs.com/wzcsqaws/p/11283228.html
            // assets 目录下,记得用require包裹一下
            replaceImg: {
                type: String
            }
        },
        created() {
            // 为了解决如果replaceImg 也报错就会重复死循环调用error方法
            this.replaceObj = {
                originalSrc: "",
                isReplace: false
            };
        },
        render() {
            let replaceObj = this.replaceObj;  // 闭包在错误函数里锁住这个对象
            let replaceImg = this.replaceImg; // 要替换的图片
            let vnode = this.$slots.default[0]; // 子组件的vnode
            let that = vnode.context; // 子组件的vm也就是this
            let on = vnode.data.on || (vnode.data.on = {}); // 获取img标签的vnode上的绑定事件,没有绑定会为空
            let error = on.error; // 获取报错事件
            let originalSrc = vnode.data.attrs.src;
            if (!originalSrc) {
                // 如果动态获取的url为空,这里之间替换为replaceImg
                console.log("url is null");
                vnode.data.attrs.src = replaceImg;
            }
    
            // 写一个error事件防止报错,图片没有替换
            function errorFix(e) {
                // 已经替换过了,还报错,说明替换的url也有问题,就renturn,避免再次赋值死循环
                if (
                    replaceObj.isReplace &&
                    replaceObj.originalSrc === originalSrc
                ) {
                    console.log("replaceImg is also error");
                    return;
                }
                console.log(e, "url is error");
                // 注意这里是之间改变dom上的src没有修改vue里的
                // 值。就可以解决我上面说的第二个问题
                vnode.elm.src = replaceImg;
                replaceObj.isReplace = true;
                replaceObj.originalSrc = originalSrc;
                if (error) {
                    // 做个兼容,如果原文件也绑定了error事件,在替换图片后也会触发,并且手动绑定上下文和event
                    // 如果原error事件也改变了url,那么会以原文件的url来显示
                    error.call(that, e);
                }
            }
            on.error = errorFix;
            return vnode;
        }
    };
    </script>
    

    功能上还有一个细节没有处理到位,就是我在抽象组件里改了url,原文件的error事件也改了url,那么如果抽象
    组件的url加载快会先显示出来,等error事件的url加载好了再替换,这样子就会闪一下,体验不好,目前的解决
    办法是使用抽象组件的开发者通过规范不这么做,但是从代码角度解决最好.

  • 相关阅读:
    线性代数:名词概念
    机器学习:多元线性回归
    机器学习:衡量线性回归法的指标(MSE、RMSE、MAE、R Squared)
    Numpy:dot()函数
    机器学习:线性回归法(Linear Regression)
    算法的时间复杂度和空间复杂度
    机器学习:数据归一化(Scaler)
    机器学习:使用scikit-learn库中的网格搜索调参
    机器学习:调整kNN的超参数
    Windows:cmd的使用
  • 原文地址:https://www.cnblogs.com/wzcsqaws/p/12988285.html
Copyright © 2011-2022 走看看