zoukankan      html  css  js  c++  java
  • vue项目踩坑

      由于上一个小项目写的很次,这一次打算好好地写一个博客系统,最近刚刚结束了管理员的管理端的编写。其中遇到了很多小坑。

      其实只能说自己vue用的不是特别熟练吧。很多问题都有些想当然了,实现起来发现了很多的问题。简单的记录几个我自己认为值得记录的吧。

    一、一个很坑的问题,vue在对其中一个目标进行改变的时候,实际上会对模板内部的方法和变量等都进行重新渲染,这样就会导致一个问题。如下

    <template>
      <div class="hello">
        <ul>
          <li v-for="item in datas">
            <div :style="{fontSize:changsize()}">{{item}}</div>
          </li>
        </ul>
        <input type="text" v-model="tests">
        {{tests}}
      </div>
    </template>
    
    <script>
    export default {
      name: 'HelloWorld',
      data () {
        return {
          datas:['one','two','three','one','two','three','one','two','three'],
          fz:'',
          tests:'',
        }
      },
      watch:{
        datas(val){
          console.log(111);
          return;
        }
      },
      methods:{
        changsize(){
          return (parseInt(Math.random()*15)+10)+'px';
        }
      }
    }
    </script>
    
    <!-- Add "scoped" attribute to limit CSS to this component only -->
    <style scoped>
    h1, h2 {
      font-weight: normal;
    }
    ul {
      list-style-type: none;
      padding: 0;
    }
    li {
      display: inline-block;
      margin: 0 10px;
    }
    a {
      color: #42b983;
    }
    </style>
    

      代码如上,如果我在input内部输入内容,这样就会改变了data内部的tests,进而整个模板都进行一次重新渲染。这样就导致我输入一个数据这个字体的大小就全部改变一次。这样就违背了我的初衷,仅仅是想在模板加载的时候赋值一次就可以了!!!以后输入内容的时候不需要改变了。开始还以为能有类似钩子函数的东西来禁止一下。最后发现有点问题。

    在网上解决问题的时候找到这样一句话:

    每个vue实例都有一个根元素id的属性el,Vue对象通过它来找到要渲染的部分。之后使用createDocumentFragment()方法创建一个documentFragment,遍历根元素的所有子元素,依次劫持并插入文档片段,将根元素掏空。然后执行Vue的编译:遍历documentFragment中的节点,对其中的v-for,v-text等属性进行相应的处理。最后,把编译完成后的documentFragment还给根元素。

    这样也就是说其实它实际上是对整体都进行了处理,如果要改变的话可能需要重写一些方法......

    那就换一个思路好了,在自己写的代码层面上想办法。

    1.当时想的第一个办法是每一次在生成datas(在我得项目里这个数据是从数据库取出来的),就直接生成一个随机的字体大小存储在数据库中。这样加载的时候就可以直接设置了。但是也有坏处。改变了自己的初始设计想法。。。。

    2.今天仔细想了一下,想出了一个办法。使用一个变量用来存储模板刷新的时候所生成的字体大小,这样在使用的时候用这个自己定义的数组变量和相应的item的index来进行分辨到底设置哪个字体的大小。代码如下

    <template>
      <div class="hello">
        <ul>
          <li v-for="(item,index) in datas">
            {{changsize(index)}}
            <div :style="{fontSize:font_size[index]}">{{item}}</div>
          </li>
        </ul>
        <input type="text" v-model="tests">
        {{tests}}
      </div>
    </template>
    
    <script>
    export default {
      name: 'HelloWorld',
      data () {
        return {
          datas:['one','two','three','one','two','three','one','two','three'],
          fz:'',
          tests:'',
          font_size:[],
        }
      },
      watch:{
        datas(val){
          console.log(111);
          return;
        }
      },
      methods:{
        changsize(index){
          if(this.font_size.length!=this.datas.length){this.font_size[index]=(parseInt(Math.random()*15)+10)+'px';  
          }else{
            return;
          }
        }
      }
    }
    </script>
    
    <!-- Add "scoped" attribute to limit CSS to this component only -->
    <style scoped>
    ul {
      list-style-type: none;
      padding: 0;
    }
    li {
      display: inline-block;
      margin: 0 10px;
    }
    a {
      color: #42b983;
    }
    </style>

     3.对于上面的方法纯属是属于通过自己的逻辑来进行判断。在methods运行的时候还需要使用if来判断一下。那么根据上一个方法有个优化的方法,我们可以声明一个数组变量,然后不断地push进新的数据进行存储,在赋值的时候依旧使用  数组[index]  这样的形式来赋值,这样就可以了。

    <template>
      <div class="hello">
        <ul>
          <li v-for="(item,index) in datas">
            {{changsize()}}
            <div :style="{fontSize:font_size[index]}">{{item}}</div>
          </li>
        </ul>
        <input type="text" v-model="tests">
        {{tests}}
      </div>
    </template>
    <script>
    export default {
      name: 'HelloWorld',
      data () {
        return {
          datas:['one','two','three','one','two','three','one','two','three'],
          fz:'',
          tests:'',
          // font_size:[],
        }
      },
      computed:{
        font_size(){
          return [];
        }
      },
      methods:{
        changsize(){
          this.font_size.push((parseInt(Math.random()*15)+10)+'px');
        }
      }
    }
    </script>
    
    <!-- Add "scoped" attribute to limit CSS to this component only -->
    <style scoped>
    h1, h2 {
      font-weight: normal;
    }
    ul {
      list-style-type: none;
      padding: 0;
    }
    li {
      display: inline-block;
      margin: 0 10px;
    }
    a {
      color: #42b983;
    }
    </style>

    这样就比较完美的解决了这个问题。当然,我们也可以将存储数据的变量放到data内部,例如我在data内部注释的那行代码一样,但是这样会有一个缺点,浏览器会报错

    [Vue warn]: You may have an infinite update loop in a component render function.

    这个问题的原因就是如果我们在v-for内部使用方法来改变data内的数据的时候,很有可能会导致无线循环,按照我这种写法当然不会触发,但是毕竟还是有可能的,所以我们还是把变量声明到computed好了。毕竟有个红色的报错提醒看着也是很烦的。

    -------------------------------------------------2018-05-03 23:56:14--------------------------------------------------------

  • 相关阅读:
    静态(static)代码块、构造代码块、构造函数、父类子类执行顺序
    Java基本特征
    下列哪项不属于jdk1.6垃圾收集器?
    Model-View-Controller(MVC) is an architectural pattern that frequently used in web applications. Which of the following statement(s) is(are) correct?
    ServletConfig对象详解
    ServletConfig接口默认是哪里实现的?
    eclipse根据父类打开子类快捷键
    IDE:Eclipse查看Servlet源码
    IDE:Eclipse查看接口实现类快捷键
    Qt探索之路——多线程实现方法
  • 原文地址:https://www.cnblogs.com/acefeng/p/8988356.html
Copyright © 2011-2022 走看看