vue2.5.17-beta.0版本存在dom渲染问题
发布于 15天前 作者 qing_321 232 次浏览 来自 问答

1、首先我手动生成5条数据,然后视图也会跟着渲染5各遮罩模块,如下图

QQ截图20180705113529.png QQ截图20180705113538.png

2、渲染出来的5个视图都有5个移除按钮,初始状态这五个视图位置是叠加的,后面我对5个视图遮罩都移动了位置,现在他们都有了自己的top和left值

3、当我随便点击一个删除按钮时,他们删除的视图我验证过是正确的,但是他们的位置不正确,让人有种错觉,点击当前删除按钮删除了别的视图,其实删除的是当前视图,但是位置存在问题。代码如下可直接运行测试,不存在依赖。如有高手知道如何解决这个问题,请下方贴出解决方案,小弟感激不尽

4.demo 预览地址 https://qing_321.gitee.io/tbtools/FullScreenHot/index.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="GBK">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>90设计 - 电商工具 - 全屏热点海报</title>
    <link rel="stylesheet" href="./../colorpicker/css/spectrum.css">
    <link rel="stylesheet" href="./../css/tb-tools-common.css">
    <link href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
    <link rel="stylesheet" href="http://js.90sjimg.com/css/codeProduce/tbcdn/default-min.css">
</head>

<body>
    <div class="main-tb-tools" id="app">
        <div class="tb-tools-title">
            <h1>全屏热点海报
                <span class="sub-title">该工具支持实时预览</span>
            </h1>
        </div>
        <div class="tb-tools-preview" id="app">
            <div class="preview-box">
                <!-- 自定义代码开始 -->
                <div ref="FullScreenHot" id="FullScreenHot">
                    <img src="http://img03.taobaocdn.com/imgextra/i3/867101640/TB28QPRaVXXXXX_XpXXXXXXXXXX-867101640.jpg" usemap="#ma345520274">
                    <div v-for="(item,index) in itemList" :k="item.href" class="map-position-bg" @click="move(event)">
                        {{item.href}}
                        <a href="javascript:;" class="btn-delete fa fa-close" @click="close_layer(index)"></a>
                        <a href="javascript:;" class="nw-resize" @click="resize(event)"></a>
                    </div>
                </div>
                <!-- <div data-title="来自淘宝代码生成网www.001daima.com" style="height:648px;">
                    <div class="most-footer footer-more-trigger" style="left:auto;right:auto;width:950px;height:648px;top:auto;padding:0;border:none;z-index:1;background:none;">
                        <div class="most-footer footer-more-trigger" style="left:-485px;top:0px;width:1920px;height:648px;border:none;padding:0;background:none;">
                            <img src="http://img03.taobaocdn.com/imgextra/i3/867101640/TB28QPRaVXXXXX_XpXXXXXXXXXX-867101640.jpg" usemap="#ma345520274">
                            
                            <map name="ma345520274">
                                <area style="outline:none;" target="_blank" shape="rect" coords="572,122,1369,390" href="">
                            </map>
                        </div>
                    </div>
                </div> -->

                <!--  自定义代码结束-->
            </div>
        </div>

        <div class="path w1200">
            <a href="javascript:;">首页</a> >
            <a href="javascript:;">淘宝工具</a> >
            <a href="javascript:;">全屏工具</a>
        </div>
        <div class="tb-tools-type w1200">
            <dl>
                <dt>店铺类型</dt>
                <dd class="active">
                    <a href="javascript:;">淘宝专业版</a>
                </dd>
                <dd>
                    <a href="javascript:;">淘宝基础版</a>
                </dd>
                <dd>
                    <a href="javascript:;">天猫店铺</a>
                </dd>
            </dl>
        </div>
        <div class="tb-tools-config w1200">
            <div class="tb-tools-tab">
                <ul>
                    <li class="active">
                        <a href="javascript:;">工具配置</a>
                    </li>
                </ul>
            </div>
            <div class="tb-tools-tab-panel">
                <div class="tab-panel">
                    <div class="row">
                        <dl>
                            <dt>开启无缝</dt>
                            <dd>
                                <input type="radio" v-model="top_size" name="top_size" id="" value="-20">
                                <label for="">向上收缩20px</label>
                            </dd>
                            <dd>
                                <input type="radio" v-model="top_size" name="top_size" id="" value="-10">
                                <label for="">向上收缩10px</label>
                            </dd>
                            <dd>
                                <input type="radio" v-model="top_size" name="top_size" id="" value="0">
                                <label for="">关闭</label>
                            </dd>
                            <span class="hint" style="float: left;margin-left: 60px;display: block;">默认自定义模块顶部会存在20px;收缩20px,则底部间距0px(无缝);收缩10px,则底部间距10px;无,则保留淘宝默认底部间距20px</span>
                        </dl>
                    </div>
                    <div class="row">
                        <dl>
                            <dt>背景图片</dt>
                            <dd>
                                <input type="number">
                            </dd>
                            <dd>
                                <span class="hint">设置背景图片地址</span>
                            </dd>
                        </dl>
                    </div>
                    <div class="func-module">
                        <h1 class="func-module-title">
                            <i class="fa  fa-chevron-down"></i> 新增热点</h1>
                        <div class="func-module-body">
                            <div class="row">
                                <table class="img-config table-normal" style="width: 500px;">
                                    <thead>
                                        <tr>
                                            <th>名称 ▼</th>
                                            <th>链接 ▼</th>
                                            <th>操作 ▼</th>
                                        </tr>
                                    </thead>
                                    <tbody>
                                        <tr v-for="(item,index) in itemList">
                                            <td>链接{{index+1}}</td>
                                            <td>
                                                <input type="text" v-model="item.href">
                                            </td>
                                            <td>
                                                <a  @click="close_layer(index)" href="javascript:;">删除</a>
                                            </td>
                                        </tr>
                                        <tr>
                                            <td colspan="3" style="text-align: center;">
                                                <a href="javascript:;" @click="add_layer()" class="tr-btn">+ 增加热点</a>
                                            </td>
                                        </tr>
                                    </tbody>
                                </table>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="module-code w1200">
            <textarea name="" id="code" cols="30" rows="10"></textarea>
            <!-- <code id="code"></code> -->
        </div>
        <div class="code-build w1200">
            <a href="javascript:;" onclick="showMask()">免费代码生成</a>
            <a href="javascript:;">预览</a>
            <a href="javascript:;" class="btn-copy-code">复制代码</a>
        </div>

    </div>
    <!--弹出层-->
    <div class="mask popup-1 scale">
        <div class="popup" style="height: 320px">
            <a href="javascript:;" class="mask-close icon_c"></a>
            <div class="popup-box">

            </div>
        </div>
    </div>

</body>
<script src="https://cdn.bootcss.com/jquery/1.8.0/jquery-1.8.0.min.js"></script>
<script src="https://cdn.bootcss.com/vue/2.5.17-beta.0/vue.min.js"></script>
<script src="./../colorpicker/js/spectrum.js"></script>

</html>
<style>
    #FullScreenHot {
        position: relative;
    }

    .map-position-bg {
        width: 400px;
        height: 400px;
        position: absolute;
        left: 10px;
        top: 10px;
        border: 1px dashed #eee;
        background: rgba(255, 255, 255, 0.2);
        cursor: move;
        box-sizing: border-box;
        transition: all 1s ease;
    }

    .btn-delete {
        width: 22px;
        height: 22px;
        color: #fff !important;
        text-align: center;
        line-height: 22px;
        position: absolute;
        right: 0;
        top: 0;
    }

    .nw-resize {
        width: 10px;
        height: 10px;
        background: rgba(255, 255, 255, 0.5);
        position: absolute;
        right: -5px;
        bottom: -5px;
        cursor: nw-resize
    }
</style>
<script>
    $(document).ready(function () {
        //颜色选择器
        $("#ht_tit_color,#mod_tit_color,#tow_line_color,#bar_price_color,#bar_info_color").spectrum({
            color: '#fff',
            showInput: true,
            showInitial: false,
            preferredFormat: 'hex',
            cancelText: "取消",//取消按钮,按钮文字
            chooseText: "选择",//选择按钮,按钮文字
            togglePaletteMoreText: "展开",//展开面板,按钮文字
            togglePaletteLessText: "收缩",//收缩面板,按钮文字
            showPaletteOnly: true,
            togglePaletteOnly: true,
            color: '#fff',
            palette: [
                ["#000", "#444", "#666", "#999", "#ccc", "#eee", "#f3f3f3", "#fff"],
                ["#f00", "#f90", "#ff0", "#0f0", "#0ff", "#00f", "#90f", "#f0f"],
                ["#f4cccc", "#fce5cd", "#fff2cc", "#d9ead3", "#d0e0e3", "#cfe2f3", "#d9d2e9", "#ead1dc"],
                ["#ea9999", "#f9cb9c", "#ffe599", "#b6d7a8", "#a2c4c9", "#9fc5e8", "#b4a7d6", "#d5a6bd"],
                ["#e06666", "#f6b26b", "#ffd966", "#93c47d", "#76a5af", "#6fa8dc", "#8e7cc3", "#c27ba0"],
                ["#c00", "#e69138", "#f1c232", "#6aa84f", "#45818e", "#3d85c6", "#674ea7", "#a64d79"],
                ["#900", "#b45f06", "#bf9000", "#38761d", "#134f5c", "#0b5394", "#351c75", "#741b47"],
                ["#600", "#783f04", "#7f6000", "#274e13", "#0c343d", "#073763", "#20124d", "#4c1130"]
            ],
            hide: function (color) {
                app[this.id] = color;
            }
        });
        //tab选项卡
        panelTab('.tb-tools-tab', '.tb-tools-tab-panel');
        //店铺类型
        tbToolsType('.tb-tools-type');
        //模块收缩
        toggleDownUp('.func-module-title');

    });

    //显示弹出层
    function showMask() {
        //$('.mask').show().find('.popup-box').html('<p>' + app.banner_config + '</p>');
        var code = $('.preview-box').html();
        $('#code').val(code);
    }

    //tab选项卡
    function panelTab(header, body) {
        $(header).find('li').each(function (index, item) {
            var $bodyPanel = $(body).find('.tab-panel').eq(index);
            $(item).click(function () {
                $(this).addClass('active').siblings().removeClass('active');
                $bodyPanel.show().siblings().hide();
            });
        });
    }
    //店铺类型
    function tbToolsType(ele) {
        $(ele).find('dd').click(function () {
            $(this).addClass('active').siblings().removeClass('active');
        });
    }

    //模块收缩
    function toggleDownUp(el_title) {
        $(el_title).find('i').on('click', function () {
            $(this).parents(el_title).next().toggleClass('toggle-down-up');
            $(this).toggleClass('fa-chevron-right');
            $(this).toggleClass('fa-chevron-down');
        })
    }




    var app = new Vue({
        el: '#app',
        data: {
            top_size: -20,//默认去除
            num:1,
            itemList: [
                {
                    href: '1'
                }
            ]
        },
        computed: {

        },
        methods: {
            //接受传来的位置数据,并将数据绑定给data下的val
            move: function (e) {
                var that = e.target;
                console.log('move');
                
                that.onmousedown = function (e) {
                 //鼠标按下,计算当前元素距离可视区的距离
                    let disX = e.clientX - that.offsetLeft;
                    let disY = e.clientY - that.offsetTop;

                    document.onmousemove = function (e) {
                      //通过事件委托,计算移动的距离 
                        let l = e.clientX - disX;
                        let t = e.clientY - disY;
                      //移动当前元素  
                      that.style.left = l + 'px';
                      that.style.top = t + 'px';
                    };
                    document.onmouseup = function (e) {
                        document.onmousemove = null;
                        document.onmouseup = null;
                     };
                };
                e.stopPropagation();
            },
            resize: function (e) {
                var that = e.target;
                console.log('resize');
                e.stopPropagation();
            },
            close_layer: function (index) {
                console.log(index)
                this.itemList.splice(index,1);
                console.log(this.itemList);
                //e.stopPropagation();
            },
            add_layer: function () {
                this.itemList.push({
                    href: ++this.num
                });
            }

        }
    })


</script>
4 回复

直接操作dom太粗暴的 不如把top和left放在对象里 动态绑定style

@carlxu94 谢谢提醒,可能是我直接操作dom造成vue dom渲染的问题

回到顶部