Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 890|回复: 0

vuejs 解决数组子组件,在子组件相同情况下,splice更换或删除数组数据,组件不刷新,组件外能刷新的问题

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-4-16 16:20:52 | 显示全部楼层 |阅读模式
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>电子答题卡</title>
        <link rel="stylesheet" href="css/answer_card.css">
    </head>
    <body >
    <div v-cloak class="answerCard" id="answerCard">
        <div class="choicetype clearfix">
            <div class="addtype">
                <span>添加题型</span>
                <a  v-for="(item,index) in classData" 
                    v-on:click="clicktype(item,index)" 
                    href="#">
                    +{{item.radiotopic}}
                </a>
            </div>
        </div>
        <div class="questiontype" v-for="(item,index) in newData">
            <div class="question " v-bind:class="addClassState(item)">
                <div class="title clearfix" v-on:click="isOpne(item,index)">
                    <div class="sort">
                        <em>题型排序</em>
                        <span><i class="up" v-bind:class="{noup: index==newData.length-1}" v-on:click.stop="upClick(item,index)"></i><i class="down" v-bind:class="{nodown: index==0}" v-on:click.stop="downClick(item,index)"></i><a href="javascript:void(0)" class="del"  v-on:click.stop="delClick(item,index)"></a></span>
                    </div>
                </div>
                <component :is="curComponentFn(item)" :key="item.guid" v-bind:oitem="item" v-bind:class="{open:activeOpen==index}" v-bind:onewdata="newData" v-bind:oindex="index" ></component>
            </div>
        </div>
    </div>
    <script type="text/javascript" src="js/lib/jquery.min.js"></script>
    <script type="text/javascript" src="js/lib/es6-promise.auto.min.js"></script>
    <script type="text/javascript" src="js/lib/axios.min.js"></script>
    <script type="text/javascript" src="js/lib/vue.min.js"></script>
    <script type="text/javascript" src="js/base.js"></script>
    <script type="text/javascript" src="js/app/testKey.js"></script>
    </body>
    </html>
    html
    var oData={
        timelimit:0,  //设置时间
        istime:true,    //是否设置时间开关
        allWrongNum:0,    //错题数
        countDown:0,  //倒计时
        activeIndex: -1, //题型当前选中
        activeOpen:0,    //当前选中题型展开
        curComponent:"", //加展相应组件
        classData:[],   //记录题型数据
        newData:[],  //得到新的数据(用于编辑POST)
        getData:[],  //得到新的数据(用于GET)
    }
    
    // 注册组件4
    var custom4=Vue.component('custom4', {
        props: ["oitem","onewdata","oindex"],
        data:function(){
            return {
                odata:this.oitem,
                list: [],
                anewdata:this.onewdata,
                aindex:this.oindex,
                asortnum:[],
            }
        },
        template: '<div class="cont">'+
                        '<ul class="clearfix">'+
                            '<li v-for="(oitemli,index) in creadData">'+
                                '<em>{{(index+1)+asortnumHandler}}.</em>'+
                                '<p>'+
                                    '<input type="text"  v-for="(oitemspan,index1) in oitemli.selected" placeholder="参考答案" v-model=oitemspan  v-on:keyup.self="addOn(oitemspan,index,index1)" v-bind:class="{on:oitemspan!=\'\'}"/>'+
                                '</p>'+
                            '</li>'+
                        '</ul>'+
                    '</div>',
        computed: {
            creadData:function(){
                this.list=[];
                this.creadDaan();
                for(var i=0;i<this.odata.num;i++){
                    var c=this.creatAnswer(parseInt(this.odata.option))
                    for(var m=0;m<c.length;m++){
                        var oindex=this.odata.answer.text[m];
                        c.splice(m, 1);
                        c.splice(m, 0, oindex);
                    }
                    var item = {
                        selected: c,
                    }
    
                    this.list.push(item)
                }
                return this.list
            },
            sortNumHandler:function(){
                   var alln=[];
                   for(var i=0;i<this.anewdata.length;i++){
                       alln.push(this.anewdata.num)
                   }
                   this.asortnum=alln
                   return this.asortnum
            },
               asortnumHandler:function(){
                   var ao=0;
                   if(this.aindex==0){
                    ao=0;
                    return ao
                }
                   for(var i=0;i<this.sortNumHandler.length;i++){    
                       ao+=parseInt(this.sortNumHandler)
                       if(i==this.aindex-1){
                           return ao
                       }
                   }
               }
       },
        methods:{
            creatAnswer:function(n){ //生成答案
                var letter=[];
                for(var i=0;i<n;i++)
                {
                    letter.push("");
                }
                return letter;
            },
            creadDaan:function(index){
                var c = this.creatAnswer(parseInt(this.odata.option))
                var createLength=this.odata.num-this.odata.answer.length;
                for (var i = 0; i < createLength; i++) {
                    var n={text:c}
                    this.odata.answer.push(n)
                }
                return this.odata.answer    
            },
        },
        created: function() {
            this.creadDaan();
        }
    })
    
    // 注册组件5
    var custom5=Vue.component('custom5', {
        props: ["oitem","onewdata","oindex"],
        data:function(){
            return {
                odata:this.oitem,
                list: [],
                anewdata:this.onewdata,
                aindex:this.oindex,
                asortnum:[],
                handPop: -1,
                keepCanvas:null
            }
        },
        template: '<div class="cont look_subjective" id="look_subjective">'+
                        '<ul class="clearfix">' +
                            '<li v-bind:id="\'subjective\'+(index + 1)" v-for="(oitemli,index) in creadData">'+
                                '<em>{{(index+1)+asortnumHandler}}.</em>'+
                                 '<div class="upload" v-bind:class="{on:oitemli.options.tit!=\'\'||oitemli.options.img!=\'\'}" >'+
                                    '<p class="tit" >'+
                                        '<textarea  type="text" maxlength="400" v-model="oitemli.options.tit" v-on:keyup.self="addTit(oitemli.options.tit,index)" placeholder="请编辑文字" />' +
                                    '</p>'+
                                    '</div>'+
                                '</div>'+
                            '</li>'+
                        '</ul>'+
                    '</div>',
        computed: {
            creadData:function(){
                this.list=[];
                this.creadDaan();
                for(var i=0;i<this.odata.num;i++){
                    var item = {
                        options: this.odata.answer,
                    }
                    this.list.push(item)
                }
                return this.list
            },
            sortNumHandler:function(){
                   var alln=[];
                   for(var i=0;i<this.anewdata.length;i++){
                       alln.push(this.anewdata.num)
                   }
                   this.asortnum=alln
                   return this.asortnum
            },
               asortnumHandler:function(){
                   var ao=0;
                   if(this.aindex==0){
                    ao=0;
                    return ao
                }
                   for(var i=0;i<this.sortNumHandler.length;i++){    
                       ao+=parseInt(this.sortNumHandler)
                       if(i==this.aindex-1){
                           return ao
                       }
                   }
               }
        },
        methods:{
            creadDaan: function (index) {
                var createLength = this.odata.num - this.odata.answer.length;
                for (var i = 0; i < createLength; i++) {
                    var n = { tit: '', img: [] }
                    this.odata.answer.push(n)
                }
                return this.odata.answer
            },
            },
    
        created: function() {
            this.creadDaan();
        },
    })
      
      
    var editApp=new Vue({
        el:'#answerCard',
        data:oData,
        filters:{//过滤器
            numChinese: function (n) {  //提供中文数字
                var cnum = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'];
                var s = '';
                n = n + 1;
                var tenNum =parseInt(n / 10);
                var units = n % 10;
                if (tenNum === 1)
                    s += "十";
                else if (tenNum > 1)
                    s += cnum[tenNum] + "十";
                if (units > 0)
                    s += cnum[units];
                return s;
            } 
       },
        methods:{
            newDataFn:function(idata){  //根据state生成数据
                this.newData=[];
                if(idata){
                    for (var n = 0; n < idata.length; n++) {
                        this.newData.push(idata[n])
                    }
                return this.newData
                }
              },
            clicktype: function (todo, index) { //选择题型
                //todoPop(todo);
                todo.guid = guid();
                this.newData.push(JSON.parse(JSON.stringify(todo)));
                this.activeOpen = this.newData.length - 1;
            },
    
    
    
            isOpne:function(todo,index){  //组件按需展开
                for(var i=0;i<this.newData.length;i++){
                    this.activeOpen=index;
                }
            },
            delClick:function(todo,index){  //删除题型    
                this.newData.splice(index, 1);
                //var sss= JSON.parse(JSON.stringify(this.newData));
                //this.newData = null;
                //this.newData = sss;
            },
            upClick:function(todo,index){   //排序向下
                  if(index==this.newData.length-1){
                      return
                  }
                  var ss = this.newData.splice(index, 1);
                  //var newss = JSON.parse(JSON.stringify(ss));
                  this.newData.splice(index + 1, 0, ss[0]);
                  //this.$set(this.newData, index + 1, ss[0]);
                  //Vue.set(this.newData, index + 1, ss[0])
                this.isOpne(todo,index)    
              },
              downClick:function(todo,index){ //排序向上
                  if(index==0){
                      return
                  }
                  var ss=this.newData.splice(index, 1);
                  this.newData.splice(index-1, 0, ss[0]);
                  this.isOpne(todo,index)    
              },
              addClassState:function(todo){    //自动生成题数类型加class
                  if(todo.radioid=="itemFill"){
                      return {itemFill:true}
                  }
                  if(todo.radioid=="itemSubjective"){
                      return {itemSubjective:true}
                  }
              },
            curComponentFn:function(todo){
                  if(todo.radioid=="itemFill"){
                      return "custom4"
                  }
                  if(todo.radioid=="itemSubjective"){
                      return "custom5"
                  }
            },
            innt:function(){ //初始化渲染页面
                  this.newDataFn(this.getData)
            },
        },
        created: function() {
              var _this=this;
                   _this.getData = [];
    var classStr="[{\"guid\":null,\"radiotopic\":\"填空题\",\"radioid\":\"itemFill\",\"isselect\":true,\"num\":\"1\",\"option\":\"1\",\"fraction\":\"1\",\"answer\":[]},{\"guid\":null,\"radiotopic\":\"主观题\",\"radioid\":\"itemSubjective\",\"isselect\":true,\"num\":\"1\",\"option\":\"1\",\"fraction\":\"1\",\"answer\":[]}]"; 
                   var classtype = JSON.parse(classStr);
    _this.classData = classtype ;
                _this.innt()
                
        }
        
        
    })
    
    //生成guid ,解决排序
    function guid() {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
            var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
            return v.toString(16);
        });
    }
    
    //选择题型弹出层
    function todoPop(todo){
        alert(todo.radiotopic+"弹出层")
        var mydata={
            "num":"4",
            "option":"4",
            "fraction":"10",
        }
        todo.num=mydata.num;
        todo.option=mydata.option;
        todo.fraction=mydata.fraction;
    }
    
    
    //获取class
    function getByClass(clsName, parent){         
        var oCls=parent.getElementsByTagName('*')//获取所有的标签元素
        var arr=[];
        for(i in oCls){
        //对遍历的标签元素与要查找的元素进行判断
            if(oCls.className==clsName){
                arr.push(oCls)
            }
        }
        return arr
    }
    js

    var ss = this.newData.splice(index, 1);
    this.newData.splice(index + 1, 0, ss[0]);

    通过splice进行数组切换后发现,组件内视图没有刷新,但外面的标题刷新了,如下图。

      添加2个主观题 

    数组改变后

     

    原因是vue内部组件缓存机制导致的。,解决方案:为每个组件添加key, 下图是官方解释

     

     

    <component :is="curComponentFn(item)" :key="item.guid" v-bind:oitem="item" v-bind:class="{open:activeOpen==index}" v-bind:onewdata="newData" v-bind:oindex="index" ></component>

    去掉 :key="item.guid" 就会重现

     

    demo https://pan.baidu.com/s/1cCqsnO

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-1-24 16:44 , Processed in 0.059088 second(s), 27 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表