首頁 web前端 js教程 全面總結:vue使用過程中遇到的問題解決總結(必看)

全面總結:vue使用過程中遇到的問題解決總結(必看)

Aug 17, 2018 pm 02:29 PM
html5 javascript node.js vue.js

這篇文章帶給大家的內容是關於全面總結:vue使用過程中遇到的問題解決總結(必看),文章介紹了對js中this的理解,有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

本文純屬個人平時實踐過程中的一些經驗總結,算是一點點小技巧吧,不是多麼高明的技術,如果對你有幫助,那麼不勝榮幸。

本文不涉及罕見API使用方法等,大部分內容都是基於對vue的一些實踐而已。由於涉嫌投機取巧,可能會帶來一些不符合規範的副作用,請根據專案要求酌情使用。

  1. 多個頁面都使用的到方法,放在vue.prototype 上會很方便

    剛接觸vue 的時候做過一件傻事,因為封裝了一個非同步請求介面post,放在post.js 檔案裡面,然後在每個需要使用非同步請求的頁面引入

    import port from './xxxx/xxxx/post'
    登入後複製

    如果只是這樣,還沒什麼,我們可以寫好一個頁面以後再複製,可以保證每個頁面都有上面的語句。但是如果每個檔案所在的目錄層級不一樣呢?

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

    當然,這時候,我們可以用 別名 @/xxxx/post,但還是少不了要每個頁面引用。
     那我們來看看,用vue.prototype 有多方便?
     首先,你得在vue 的入口檔案( vue-cli 產生的專案的話,預設是/src/main.js)裡面做如下設定

     import port from './xxxx/xxxx/post'
    
     vue.prototype.$post = post
    登入後複製

    這樣,我們就可以在所有的vue 元件(頁面)裡面使用this.post() 方法了,就像vue 的親兒子一樣

    tip: 把方法掛在到prototype 上的時候,最好加一個$ 前綴,避免跟其他變數衝突

    til again: 不要掛載太多方法到prototype 上,只掛載一些使用頻率非常高的

  2. 需要回應的數據,在取得到介面資料的時候,先設定

    大家有沒有很常碰到這樣都一種狀況,在循環清單的時候,我們需要給清單項目一個控制顯示的屬性,如是否可刪除,是否已選中等等,而後端接口一般不會返回這種字段,因為這屬於純前端展示的,跟後端沒啥關係,比如後端給的數據如下

    [
      {name: 'abc', age: 18},
      {name: 'def', age: 20},
      {name: 'ghi', age: 22},
    ]
    登入後複製

    我們不妨假設以上數據為學生列表

    然後我們需要渲染這個列表,在每一項後面顯示一個勾選按鈕,如果用戶打勾,則這個按鈕是綠色,默認這個按鈕是灰色,這個時候,上表是沒有滿足這個渲染條件的數據,而如果我們在用戶打勾的時候,再去添加這個數據的話,正常的做法是無法及時響應的。

    如果我們在取得到資料的時候,先給數組的每一項都加一個是否打勾的標示,就可以解決這個問題,我們假設我們得到的資料是res. list

    res.list.map(item => { 
      item.isTicked = false
    })
    登入後複製

    這麼做的原理是vue 無法對不存在的屬性作回應,所以我們在取得到資料的時候,先把需要的屬性加上去,然後在賦值給data , 這樣data 接收到資料的時候,已經是存在這個屬性了,所以會回應。當然還有其他方法可以實現。不過對於一個強迫症來說,我還是比較傾向於這種做法

  3. 封裝全域基於promise 的非同步請求方法

    看過很多項目的源碼,發現大部分的非同步請求都是直接使用axios 之類的方法,如下

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

    如果有跨域,或者需要設定http 頭等,還需要加入更多的配置,而這些配置,對於同一個專案來說,基本上都是一樣的,不一樣的只有url 跟參數,既然這樣,那我嗎為什麼不把它封裝成一個方法呢?

    function post (url,param) {
        return axios({
          method: 'post',
          url: url,
          data: param
          ... axios 的其他配置
        })
    }
    登入後複製
    tip: 這裡原來我多用了一層promise包起來,對簡單的需求來說是太多餘了,感覺掘金用戶 @日月為易。 指出

    再結合第一點,我們就可以再任意 vue 實例中這樣使用

    let param = {
      firstName: 'Fred',
      lastName: 'Flintstone'
    }
    this.post('/user/12345',param)
    .then(...)
    .catch(...)
    登入後複製

    有沒有比原始的簡單很多呢?如果你的專案支持async await,還可以這樣用

    let param = {
      firstName: 'Fred',
      lastName: 'Flintstone'
    }
    let res  = await this.post('/user/12345',param)
    console.log(res) // res 就是异步返回的数据
    登入後複製
    tip: await 關鍵字必須在被async 修飾的函數裡面使用
  4. 如果你覺得有時候,你真的需要父子元件共用一個值,不如試試傳個參考型別過去

    vue 的父子元件傳值,有好多種方法,這裡就不一一列舉了,但是今天我們要了解的,是利用javascript 的引用類型特性,還達到另一種傳值的目的

    假设有这么一个需求,父组件需要传 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中全新的数字方法总结(必看)

以上是全面總結:vue使用過程中遇到的問題解決總結(必看)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

HTML 中的表格邊框 HTML 中的表格邊框 Sep 04, 2024 pm 04:49 PM

HTML 表格邊框指南。在這裡,我們以 HTML 中的表格邊框為例,討論定義表格邊框的多種方法。

HTML 左邊距 HTML 左邊距 Sep 04, 2024 pm 04:48 PM

HTML 左邊距指南。在這裡,我們討論 HTML margin-left 的簡要概述及其範例及其程式碼實作。

HTML 中的巢狀表 HTML 中的巢狀表 Sep 04, 2024 pm 04:49 PM

這是 HTML 中巢狀表的指南。這裡我們討論如何在表中建立表格以及對應的範例。

HTML 表格佈局 HTML 表格佈局 Sep 04, 2024 pm 04:54 PM

HTML 表格佈局指南。在這裡,我們詳細討論 HTML 表格佈局的值以及範例和輸出。

HTML 輸入佔位符 HTML 輸入佔位符 Sep 04, 2024 pm 04:54 PM

HTML 輸入佔位符指南。在這裡,我們討論 HTML 輸入佔位符的範例以及程式碼和輸出。

HTML 有序列表 HTML 有序列表 Sep 04, 2024 pm 04:43 PM

HTML 有序列表指南。在這裡我們也分別討論了 HTML 有序列表和類型的介紹以及它們的範例

在 HTML 中移動文字 在 HTML 中移動文字 Sep 04, 2024 pm 04:45 PM

HTML 中的文字移動指南。在這裡我們討論一下marquee標籤如何使用語法和實作範例。

HTML onclick 按鈕 HTML onclick 按鈕 Sep 04, 2024 pm 04:49 PM

HTML onclick 按鈕指南。這裡我們分別討論它們的介紹、工作原理、範例以及各個事件中的onclick事件。

See all articles