Maison  >  Article  >  interface Web  >  Résumé complet : Résumé de la résolution des problèmes rencontrés lors de l'utilisation de vue (à lire absolument)

Résumé complet : Résumé de la résolution des problèmes rencontrés lors de l'utilisation de vue (à lire absolument)

不言
不言original
2018-08-17 14:29:244970parcourir

Cet article vous apporte un résumé complet : un résumé des solutions aux problèmes rencontrés lors de l'utilisation de vue (à lire absolument). L'article introduit la compréhension de cela en js, qui a une certaine valeur de référence et est nécessaire. référez-vous-y, j'espère que cela vous sera utile.

Cet article est purement un résumé de quelques expériences personnelles dans la pratique quotidienne. C'est une petite astuce, pas une technologie brillante. Si cela vous aide, j'en serais honoré.

Cet article n'implique pas 罕见API les méthodes d'utilisation, etc. La plupart du contenu est basé sur certaines pratiques de vue. En raison de soupçons d'opportunisme, cela peut entraîner des effets secondaires non standard, veuillez l'utiliser de manière appropriée en fonction des exigences du projet.

  1. Cette méthode peut être utilisée sur plusieurs pages Il sera très pratique de la mettre sur vue.prototype

    Faites-le quand vous l'êtes. nouveau sur vue J'ai fait une bêtise, car j'ai encapsulé une interface de requête asynchrone post, je l'ai mise dans le fichier post.js, puis j'ai introduit

    import port from './xxxx/xxxx/post'

    dans chaque page qui doit être utilisée requête asynchrone. Si tel est le cas, ce n'est pas grave. Nous pouvons écrire une page et la copier plus tard, en nous assurant que chaque page contient l'instruction ci-dessus. Mais que se passe-t-il si le niveau de répertoire de chaque fichier est différent ?

    // 假设正常是这样
    import port from '../xxxx/xxxx/post'
    // 目录加深一级,就变成这样
    import port from '../../xxxx/xxxx/post'
    // 再加深一级的样子
    import port from '../../../xxxx/xxxx/post'

    Bien sûr, à cette heure, on peut utiliser des alias @/xxxx/post, mais il faut quand même citer chaque page.
    Alors voyons à quel point il est pratique d'utiliser vue.prototype ?
    Tout d'abord, vous devez effectuer les réglages suivants dans le fichier d'entrée de vue (pour les projets générés par vue-cli, la valeur par défaut est /src/main.js)

     import port from './xxxx/xxxx/post'
    
     vue.prototype.$post = post

    De cette façon, nous peut définir La méthode vue est utilisée dans le composant this.post() (page), tout comme le fils biologique de vue

    astuce : Lorsque vous accrochez la méthode sur prototype, il est préférable d'ajouter un $ Préfixe pour éviter les conflits avec d'autres variables

    à nouveau : Ne montez pas trop de méthodes sur prototype, montez seulement celles qui sont très fréquemment utilisées

  2. Les données auxquelles il faut répondre. Lors de l'obtention des données d'interface, définissez-les d'abord. L'élément est un attribut qui contrôle l'affichage, par exemple s'il peut être supprimé, s'il est sélectionné, etc. L'interface finale ne renvoie généralement pas ce type de champ, car il s'agit d'un affichage purement frontal et n'a rien à voir avec le back-end, comme les données fournies par le back-end. Comme suit

    <.> Autant supposer que les données ci-dessus sont une liste d'étudiants

    Ensuite, nous devons restituer cette liste et afficher un bouton de coche derrière chaque élément. Si l'utilisateur vérifie, ce bouton Il est vert, et. le bouton est gris par défaut. À l'heure actuelle, le tableau ci-dessus ne contient pas de données qui répondent à cette condition de rendu. Si nous ajoutons ces données lorsque l'utilisateur coche, l'approche normale ne pourra pas répondre à temps.
    [
      {name: 'abc', age: 18},
      {name: 'def', age: 20},
      {name: 'ghi', age: 22},
    ]

    Si nous ajoutons d'abord une coche à chaque élément du tableau lorsque nous obtenons les données, nous pouvons résoudre ce problème. Nous supposons que les données que nous obtenons sont

    Le principe de cela est que

    ne peut pas répondre à des attributs inexistants, donc lorsque nous obtenons les données, nous ajoutons d'abord les attributs requis puis les attribuons à res.list, comme ceci

    Lorsque les données sont reçu, cet attribut existe déjà, il répondra donc. Il existe bien sûr d’autres façons de procéder. Cependant, pour une personne atteinte de trouble obsessionnel-compulsif, je préfère quand même cette approche
    res.list.map(item => { 
      item.isTicked = false
    })

    vuedatadataEncapsuler la méthode de requête asynchrone globale basée sur

  3. J'ai lu le code source de nombreux projets et constaté que la plupart des requêtes asynchrones utilisent directement des méthodes telles que , comme suit promise

    S'il y a plusieurs domaines, ou si vous devez définir le

    en-tête, vous devez également ajouter plus de configurations, et ces configurations sont fondamentalement les mêmes pour le même projet. Les seules différences sont axios et les paramètres. Dans ce cas, pourquoi ne pas l'encapsuler dans une méthode ?

    axios({
      method: 'post',
      url: '/user/12345',
      data: {
        firstName: 'Fred',
        lastName: 'Flintstone'
      }
    })
     .then(function (response) {
        console.log(response);
      })
      .catch(function (error) {
        console.log(error);
      });

    astuce : Il s'avère que j'ai utilisé une couche de promesse supplémentaire pour le conclure, ce qui est trop redondant pour des besoins simples. Je pense que l'utilisateur de Nuggets http l'a souligné url et je l'ai combiné avec le premier À un moment donné, nous pouvons utiliser

    function post (url,param) {
        return axios({
          method: 'post',
          url: url,
          data: param
          ... axios 的其他配置
        })
    }
    dans n'importe quelle instance @日月为易。 comme celle-ci. Est-ce beaucoup plus simple que celui d'origine ? Si votre projet prend en charge

    , vous pouvez également utiliser vue

    let param = {
      firstName: 'Fred',
      lastName: 'Flintstone'
    }
    this.post('/user/12345',param)
    .then(...)
    .catch(...)
    astuce :

    le mot-clé doit être dans asyncawait

    let param = {
      firstName: 'Fred',
      lastName: 'Flintstone'
    }
    let res  = await this.post('/user/12345',param)
    console.log(res) // res 就是异步返回的数据
    awaitSi vous pensez que parfois, vous avez vraiment besoin que les composants parent et enfant partagent une valeur, pourquoi ne pas essayer de passer un type référence pour transmettre la valeur aux composants parent et enfant de 被 async 修饰的函数里面使用
  4. . Il existe de nombreuses façons, ici je ne les énumérerai pas une par une, mais ce que nous voulons savoir aujourd'hui, c'est utiliser les caractéristiques de type référence de

    pour atteindre un autre objectif de transmission de valeur .

    假设有这么一个需求,父组件需要传 3 个值到子组件,然后再子组件里面改动后,需要立马再父组件上作出响应,我们通常的做法上改完以后,通过 this.$emit 发射事件,然后再父组件监听对应的事件,然而这么做应对一两个数据还好,如果传的数据多了,会累死人。
     我们不妨把这些要传递的数据,包再一个对象/数组 里面,然后在传给子组件

    <subComponent :subData="subData"></subComponent>
    data () {
      return {
        subData: {
          filed1: 'field1',
          filed2: 'field2',
          filed3: 'field3',
          filed4: 'field4',
          filed5: 'field5',
        }
      }
    }

    这样,我们在子组件里面改动 subData 的内容,父组件上就能直接作出响应,无需 this.$emitvuex 而且如果有其他兄弟组件的话,只要兄弟组件也有绑定这个 subData ,那么兄弟组件里面的 subData 也能及时响应

    tip: 首先,这么做我个人上感觉有点不符合规范的,如果没有特别多的数据,还是乖乖用 this.$emit 吧,其次,这个数据需要有特定的条件才能构造的出来,并不是所有情况都适用。

  5. 异步请求的参数在 data 里面构造好,用一个对象包起来,会方便很多

    有做过类似 ERP 类型的系统的同学,一定碰到过这样的一个场景,一个列表,有 N 个过滤条件,这个时候通常我们这么绑定

     <input type="text" v-model="field1">
     <input type="text" v-model="field2">
     <input type="text" v-model="field3">
     ....
     <input type="text" v-model="fieldn">
    data () {
     return {
       field1: 'value1',
       field2: 'value2',
       field3: 'value3',
       ...
       fieldn:'valuen'
     }
    }

    然后提交数据的时候这样:

     var param = {
       backend_field1: this.field1,
       backend_field2: this.field2,
       backend_field3: this.field3,
       ...
       backend_fieldn: this.fieldn
     }
     this.post(url,param)

    如你看到的,每次提交接口,都要去构造参数,还很容易遗漏,我们不妨这样:先去接口文档里面看一下后端需要的字段名称,然后

        <input type="text" v-model="queryParam.backend_field1">
        <input type="text" v-model="queryParam.backend_field2">
        <input type="text" v-model="queryParam.backend_field3">
        ....
        <input type="text" v-model="queryParam.backend_fieldn">
     
      "javascript
      data () {
       return {
         queryParam:{
           backend_field1: 'value1'
           backend_field2: 'value2'
           backend_field3: 'value3'
           ...
           backend_fieldn: 'valuen'
         }
       }
      }
      "
      然后提交数据的时候这样:
      "javascript
       this.post(url,this.queryParam)
      "

    是的,这样做也是有局限性的,比如你一个数据在 2 个地方共用,比如前端组件绑定的是一个数组,你需要提交给后端的是 2 个字符串(例:element ui 的时间控件),不过部分特殊问题稍微处理一下,也比重新构建一个参数简单不是吗?

  6. data 里面的数据多的时候,给每个数据加一个备注,会让你后期往回看的时候很清晰

    续上一点,data 里面有很多数据的时候,可能你写的时候是挺清晰的,毕竟都是你自己写的东西,可是过了十天半个月,或者别人看你的代码,相信我,不管是你自己,还是别人,都是一头雾水(记忆力超出常人的除外),所以我们不妨给每个数据后面加一个备注

    data () {
     return {
       field1: 'value1',  // 控制xxx显示
       field2: 'value2',  // 页面加载状态
       field3: [],        // 用户列表
       ...
       fieldn: 'valuen'   // XXXXXXXX
     }
    }
  7. 逻辑复杂的内容,尽量拆成组件

    假设我们有一个这样的场景:

    <p>
       <p>姓名:{{user1.name}}</p>
       <p>性别:{{user1.sex}}</p>
       <p>年龄:{{user1.age}}</p>
       ...此处省略999个字段...
       <p>他隔壁邻居的阿姨家小狗的名字:{{user1.petName}}</p>
    </p>
    <-- 当然,显示中我们不会傻到不用 v-for,我们假设这种情况无法用v-for -->
    <p>
        <p>姓名:{{user2.name}}</p>
        <p>性别:{{user2.sex}}</p>
        <p>年龄:{{user2.age}}</p>
        ...此处省略999个字段...
        <p>他隔壁邻居的阿姨家小狗的名字:{{user2.petName}}</p>
    </p>

    这种情况,我们不妨把[用户]的代码,提取到一个组件里面:
     假设如下代码,在 comUserInfo.vue

    <template>
     <p>
       <p>姓名:{{user.name}}</p>
       <p>性别:{{user.sex}}</p>
       <p>年龄:{{user.age}}</p>
       ...此处省略999个字段...
       <p>他隔壁邻居的阿姨家小狗的名字:{{user.petName}}</p>
     </p>
    </template>
    
    <script >
    export  default {
     props:{
       user:{
         type:Object,
         default: () => {}
       }
     }
    }
    </script>

    然后原来的页面可以改成这样(省略掉导入和注册组件,假设注册的名字是 comUserInfo ):

    <comUserInfo :user="user1"/>
    <comUserInfo :user="user2"/>

    这样是不是清晰很多?不用看注释,都能猜的出来,这是2个用户信息模块, 这样做,还有一个好处就是出现错误的时候,你可以更容易的定位到错误的位置。

  8. 如果你只在子组件里面改变父组件的一个值,不妨试试 $emit('input') ,会直接改变 v-model

    我们正常的父子组件通信是 父组件通过 props 传给子组件,子组件通过 this.$emit('eventName',value) 通知父组件绑定在 @eventName 上的方法来做相应的处理。
     但是这边有个特例,vue 默认会监听组件的 input 事件,而且会把子组件里面传出来的值,赋给当前绑定到 v-model 上的值

    正常用法 - 父组件

    <template>
      <subComponent :data="param" @dataChange="dataChangeHandler"></subComponent>
    </template>
    
    <script >
      export default {
        data () {
          return {
            param:'xxxxxx'
          }
        },
        methods:{
          dataChangeHandler (newParam) {
            this.param = newParam
          }
        }
      }
    </script>

    正常用法 - 子组件

    <script >
      export default {
        methods:{
          updateData (newParam) {
            this.$emit('dataChange',newParam)
          }
        }
      }
    </script>

    利用默认 input 事件 - 父组件

    <template>
      <subComponent  v-model="param"></subComponent>
    </template>

    利用默认 input 事件 - 子组件

    <script >
      export default {
        methods:{
          updateData (newParam) {
            this.$emit('input',newParam)
          }
        }
      }
    </script>

    这样,我们就能省掉父组件上的一列席处理代码,vue 会自动帮你处理好

    tip: 这种方法只适用于改变单个值的情况,且子组件对父组件只需简单的传值,不需要其他附加操作(如更新列表)的情况。

    补充一个 this.$emit('update:fidldName',value) 方法 (感谢掘金用户 @日月为易。 指出)
     具体用法如下:

    父组件

        <subComponent field1.sync="param1" field2.sync="param2"></subComponent>

    子组件

    <script >
      export default {
        methods:{
          updateData1 (newValue) {
            this.$emit('update:field1',newValue)
          },
          updateData2 (newValue) {
            this.$emit('update:field2',newValue)
          }
        }
      }
    </script>

    该方法,个人认为比较适用于 要更新的数据不能绑定在 v-model 的情况下,或者要双向通信的数据大于 1 个(1个也可以用,但我个人更推荐 input 的方式, 看个人喜好吧),但又不会很多的情况下.

  9. conponents放在 Vue options 的最上面

    不知道大家有没有这样的经历: 导入组件,然后在也页面中使用,好的,报错了,为啥?忘记注册组件了,为什么会经常忘记注册组件呢?因为正常的一个 vue 实例的结构大概是这样的:

    import xxx form 'xxx/xxx'
    export default {
      name: 'component-name',
      data () {
        return {
          // ...根据业务逻辑的复杂程度,这里省略若干行
        }
      },
      computed: {
        // ...根据业务逻辑的复杂程度,这里省略若干行
      },
      created () {
        // ...根据业务逻辑的复杂程度,这里省略若干行
      },
      mounted () {
        // ...根据业务逻辑的复杂程度,这里省略若干行
      },
      methods () {
        // ...根据业务逻辑的复杂程度,这里省略若干行
      },
    }

    我不知道大家正常是把 components 属性放在哪个位置,反正我之前是放在最底下,结果就是导致经常犯上述错误。

    后面我把 components 调到第一个去了

    import xxx form 'xxx/xxx'
    export default {
      components: {
        xxx
      },
      // 省略其他代码
    }

    从此以后,妈妈再也不用担心我忘记注册组件了,导入和注册都在同一个位置,想忘记都难。

  10. 大部分情况下,生命周期里面,不要有太多行代码,可以封装成方法,再调用

    看过很多代码,包括我自己之前的,在生命周期里面洋洋洒洒的写了一两百行的代码,如:把页面加载的时候,该做的事,全部写在 created 里面,导致整个代码难以阅读,完全不知道你在页面加载的时候,做了些什么,
     这个时候,我们不妨把那些逻辑封装成方法,然后在生命周期里面直接调用:

    created () {
      // 获取用户信息
      this.getUserInfo()
      // 获取系统信息
      this.getSystemInfo()
      // 获取配置
      this.getConfigInfo()
    },
    methods:{
      // 获取用户信息
      getUserInfo () {...},
      // 获取系统信息
      getSystemInfo () {...},
      // 获取配置
      getConfigInfo () {...},
    }

    这样是不是一眼就能看的出,你在页面加载的时候做了些什么?

    tip: 这个应该算是一个约定俗成的规范吧,只是觉得看的比较多这样写的,加上我自己初学的时候,也这么做了,所以写出来,希望新入坑的同学能避免这个问题
  11. 少用 watch,如果你觉得你好多地方都需要用到 watch,那十有八九是你对 vueAPI 还不够了解

    vue 本身就是一个数据驱动的框架,数据的变动,能实时反馈到视图上去,如果你想要根据数据来控制试图,正常情况一下配合 computed 服用就能解决大部分问题了,而视图上的变动,我们一般可以通过监听 input change 等事件,达到实时监听的目的,
     所以很少有需求使用到 watch 的时候,至少我最近到的十来个项目里面,是没有用过 watch 当然,并不是说 watch 是肯定没用处, vue 提供这个api,肯定是有他的道理,也有部分需求是真的需要用到的,只是我觉得应该很少用到才对,如果你觉得到处都得用到的话,
     那么我觉得 十有八九你应该多去熟悉一下 computedvue 的其他 api

相关推荐:

Vue登录注册的实现方法(代码解析)

ES6中全新的数字方法总结(必看)

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn