ホームページ  >  記事  >  ウェブフロントエンド  >  Vue プロジェクトで使用される実践的なヒントを共有します

Vue プロジェクトで使用される実践的なヒントを共有します

青灯夜游
青灯夜游転載
2020-09-28 18:00:212480ブラウズ

Vue プロジェクトで使用される実践的なヒントを共有します

Vue を開発する過程で、何らかの問題が発生し、長い間立ち往生しなければならないことがよくあります。元の問題を発見できれば問題は解決しますが、詳細はまだ理解できていません。今日は、編集者がプロジェクトで使用する実践的なヒントをいくつかまとめましたので、お金を稼ぐために頑張っているあなたの助けになれば幸いです。世界のルールは、最初にいいね、後で読む、そして無限のロマンチックな出会いをすることです。

データが応答しません。使用方法に問題がある可能性があります。

数日前、友人がコードを送ってきて、Vue と言いました。 はいバグ、彼は明らかに正しく書いていますが、データが応答しないのはなぜですか?それはVueの##バグに違いありません?彼はYou Yuxiよりも強力で、それ以上のレベルには到達できないと感じたので、無視しました。しかし、開発中にデータが応答しないことがあることは事実です。では、どうすればよいでしょうか?たとえば、次のコード:

<template>
  <div>
    <div>
      <span>用户名: {{ userInfo.name }}</span>
      <span>用户性别: {{ userInfo.sex }}</span>
      <span v-if="userInfo.officialAccount">
        公众号: {{ userInfo.officialAccount }}
      </span>
    </div>
    <button @click="handleAddOfficialAccount">添加公众号</button>
  </div>
</template>
<script>
export default {
  data() {
    return {
      userInfo: {
        name: &#39;子君&#39;,
        sex: &#39;男&#39;
      }
    }
  },
  methods: {
    // 在这里添加用户的公众号
    handleAddOfficialAccount() {
      this.userInfo.officialAccount = &#39;前端有的玩&#39;
    }
  }
}
</script>

上記のコードでは、公式アカウント属性をユーザー情報に追加したいと考えていますが、

this.userInfo.officialAccount = '一部のユーザーは、フロントエンド' 追加しても効果がありません。なぜですか?

これは、

Vue 内でデータ応答が Object.definePrototype を使用してオブジェクトの各キーをリッスンするためですgetter,setter メソッドが実装されていますが、このメソッドでは既存の属性のみを監視でき、新しく追加された属性は監視できません。ただ監視したいだけです。編集者の方、どうすればよいか教えてください。以下のエディタでは 4 つの方法が提供されていますが、さらに方法がある場合は、下のコメント欄で教えてください。

1.

data

に追加する属性を事前に定義します。たとえば、上記のパブリック アカウントの場合、 # 事前に##userInfo

は内部で定義されているため、次の

data() {
    return {
      userInfo: {
        name: &#39;子君&#39;,
        sex: &#39;男&#39;,
        // 我先提前定义好
        officialAccount: &#39;&#39;
      }
    }
  }
2 のように新しい属性ではありません。

userInfo を直接置き換えます。

userInfo

に新しい属性を追加することはできませんが、userInfo は定義されているため、userInfo の値を直接変更することができます。次のように記述することもできます

this.userInfo = {
  // 将原来的userInfo 通过扩展运算法复制到新的对象里面
  ...this.userInfo,
  // 添加新属性
  officialAccount: &#39;前端有的玩&#39;
}

3.

Vue.setIn を使用します実際、上記 2 つのメソッドは少し注意が必要です。実際、新しい属性については、

Vue

が新しいメソッド Vue.set を正式に提供し、新しい属性を追加できない問題を解決しています。 . トリガーデータ応答。

Vue.set メソッド定義

/**
* target 要修改的对象
* prpertyName 要添加的属性名称
* value 要添加的属性值
*/
Vue.set( target, propertyName, value )

##上記のコードは Vue.set

で使用できます。

import Vue from &#39;vue&#39;

// 在这里添加用户的公众号
handleAddOfficialAccount() {
  Vue.set(this.userInfo,&#39;officialAccount&#39;, &#39;前端有的玩&#39;)
}
に修正しますが、set

メソッドを使いたい場合は毎回

Vueを導入する必要があり非常に面倒なので、簡単に言うと、 Vueset メソッドを Vue のプロトタイプ チェーンにマウントしています。つまり、Vue.prototype.$set = Vue.set したがって、Vue では、Vue.set

this.$set(this.userInfo,&#39;officialAccount&#39;, &#39;前端有的玩&#39;)
の代わりに this.$set をコンポーネント内で直接使用できます。エディターが見つけました。 Vue.set

をいつ使用すればよいのか、多くの学生は知りません。実際、

Vue,set を使用する必要があるのは、割り当てたい属性が定義されていない場合だけです。通常、他の時には使用する必要はありません。 4.

$forceUpdate

$forceUpdate

の存在により、多くのフロントエンド開発者が仕事をしなくなるのではないかと思います。双方向データ バインディングの原則に注意してください。

data をいつ変更しても、$forceUpdate を呼び出すと Vue コンポーネントが再レンダリングされるためです。 . 、bug は存在しません。しかし実際には、この方法は不必要なパフォーマンスの消費を大量に引き起こすため、お勧めできません。 配列の特定のメソッド

実際には、オブジェクトだけではなく、配列でも、次のコードのように、データ変更後に応答しなくなる状況があります。

<template>
  <div>
    <ul>
      <li v-for="item in list" :key="item">
        {{ item }}
      </li>
    </ul>
    <button @click="handleChangeName">修改名称</button>
  </div>
</template>
<script>
export default {
  data() {
    return {
      list: [&#39;张三&#39;, &#39;李四&#39;]
    }
  },
  methods: {
    // 修改用户名称
    handleChangeName() {
      this.list[0] = &#39;王五&#39;
    }
  }
}
</script>

上記のコードは、Zhang San の名前を Wang Wu に変更しても、実際には有効にならないことを願っています。これは、

Vue

が次の変更された配列を検出できないためです:

    Whenインデックスを使用して項目を直接設定します。例:
  • this.list[index] = newValue

  • 配列の
  • length プロパティを変更します。例: this.list.length = 0

所以在上例中通过this.list[0] = '王五' 是无法触发数据响应的,那应该怎么办呢?像上面提到的Vue.set$forceUpdate都可以解决这个问题,比如Vue.set可以这样写

Vue.set(this.list,0,&#39;王五&#39;)

除了那些方法之外,Vue还针对数组提供了变异方法

在操作数组的时候,我们一般会用到数据提供的许多方法,比如push,pop,splice等等,在Vue中调用数组上面提供的这些方法修改数组的值是可以触发数据响应的,比如上面的代码改为以下代码即可触发数据响应

this.list.splice(0,1,&#39;王五&#39;)

实际上,如果Vue仅仅依赖gettersetter,是无法做到在数组调用push,pop等方法时候触发数据响应的,因此Vue实际上是通过劫持这些方法,对这些方法进行包装变异来实现的。

Vue对数组的以下方法进行的包装变异:

  • push
  • pop
  • shift
  • unshift
  • splice
  • sort
  • reverse

所以在操作数组的时候,调用上面这些方法是可以保证数据可以正常响应,下面是Vue源码中包装数组方法的代码:

var original = arrayProto[method];
  def(arrayMethods, method, function mutator () {
    // 将 arguments 转换为数组
    var args = [], len = arguments.length;
    while ( len-- ) args[ len ] = arguments[ len ];
    var result = original.apply(this, args);
    // 这儿的用法同dependArray(value),就是为了取得dep
    var ob = this.__ob__;
    var inserted;
    switch (method) {
      case &#39;push&#39;:
      case &#39;unshift&#39;:
        inserted = args;
        break
      case &#39;splice&#39;:
        inserted = args.slice(2);
        break
    }
    // 如果有新的数据插入,则插入的数据也要进行一个响应式
    if (inserted) { ob.observeArray(inserted); }
   // 通知依赖进行更新
    ob.dep.notify();
    return result
  });

文本格式化,filter更简单

使用filter 简化逻辑

我想把时间戳显示成yyyy-MM-DD HH:mm:ss的格式怎么办?是需要在代码中先将日期格式化之后,再渲染到模板吗?就像下面这样

<template>
  <div>
    {{ dateStr }}
    <ul>
      <li v-for="(item, index) in getList" :key="index">
        {{ item.date }}
      </li>
    </ul>
  </div>
</template>
<script>
import { format } from &#39;@/utils/date&#39;
export default {
  data() {
    return {
      date: Date.now(),
      list: [
        {
          date: Date.now()
        }
      ]
    }
  },
  computed: {
    dateStr() {
      return format(this.date, &#39;yyyy-MM-DD HH:mm:ss&#39;)
    },
    getList() {
      return this.list.map(item => {
        return {
          ...item,
          date: format(item.date, &#39;yyyy-MM-DD HH:mm:ss&#39;)
        }
      })
    }
  }
}
</script>

像上面的写法,针对每一个日期字段都需要调用format,然后通过计算属性进行转换?这时候可以考虑使用Vue提供的filter去简化

<template>
  <div>
    <!--使用过滤器-->
    {{ dateStr | formatDate }}
    <ul>
      <li v-for="(item, index) in list" :key="index">
        <!--在v-for中使用过滤器-->
        {{ item.date | formatDate }}
      </li>
    </ul>
  </div>
</template>
<script>
import { format } from &#39;@/utils/date&#39;
export default {
  filters: {
    formatDate(value) {
      return format(value, &#39;yyyy-MM-DD HH:mm:ss&#39;)
    }
  },
  data() {
    return {
      date: Date.now(),
      list: [
        {
          date: Date.now()
        }
      ]
    }
  }
}
</script>

通过上面的修改是不是就简单多了

注册全局filter

有些过滤器使用的很频繁,比如上面提到的日期过滤器,在很多地方都要使用,这时候如果在每一个要用到的组件里面都去定义一遍,就显得有些多余了,这时候就可以考虑Vue.filter注册全局过滤器

对于全局过滤器,一般建议在项目里面添加filters目录,然后在filters目录里面添加

// filters\index.js

import Vue from &#39;vue&#39;
import { format } from &#39;@/utils/date&#39;

Vue.filter(&#39;formatDate&#39;, value => {
  return format(value, &#39;yyyy-MM-DD HH:mm:ss&#39;)
})

然后将filters里面的文件引入到main.js里面,这时候就可以在组件里面直接用了,比如将前面的代码可以修改为

<template>
  <div>
    <!--使用过滤器-->
    {{ dateStr | formatDate }}
    <ul>
      <li v-for="(item, index) in list" :key="index">
        <!--在v-for中使用过滤器-->
        {{ item.date | formatDate }}
      </li>
    </ul>
  </div>
</template>
<script>
export default {
  data() {
    return {
      date: Date.now(),
      list: [
        {
          date: Date.now()
        }
      ]
    }
  }
}
</script>

是不是更简单了

开发了插件库,来安装一下

在使用一些UI框架的时候,经常需要使用Vue.use来安装, 比如使用element-ui时候,经常会这样写:

import Vue from &#39;vue&#39;;
import ElementUI from &#39;element-ui&#39;;
import &#39;element-ui/lib/theme-chalk/index.css&#39;;
Vue.use(ElementUI,{size: &#39;small&#39;});

使用了Vue.use之后,element-ui就可以直接在组件里面使用了,好神奇哦(呸,娘炮)。接下来我们实现一个简化版的element来看如何去安装。

了解Vue.use的用法

Vue.use是一个全局的方法,它需要在你调用 new Vue() 启动应用之前完成,Vue.use的参数如下

/**
* plugin: 要安装的插件 如 ElementUI
* options: 插件的配置信息 如 {size: &#39;small&#39;}
*/
Vue.use(plugin, options)

模拟element-ui的安装逻辑

想一下,使用Vue.use(ElementUI,{size: 'small'}) 之后我们可以用到哪些element-ui提供的东西

// 这个是一个按钮组件
import Button from &#39;@/components/button&#39;

// loading 指令
import loadingDirective from &#39;@/components/loading/directive&#39;

// loading 方法
import loadingMethod from &#39;@/components/loading&#39;

export default {
  /**
   * Vue.use 需要插件提供一个install方法
   * @param {*} Vue Vue
   * @param {*} options 插件配置信息
   */
  install(Vue, options) {
    console.log(options)
    // 将组件通过Vue.components 进行注册
    Vue.components(Button.name, Button)

    // 注册全局指令
    Vue.directive(&#39;loading&#39;, loadingDirective)

    // 将loadingMethod 挂载到 Vue原型链上面,方便调用
    Vue.prototype.$loading = loadingMethod
  }
}

通过上面的代码,已经实现了一个丐版的element-ui插件,这时候就可以在main.js里面通过Vue.use进行插件安装了。大家可能会有疑问,为什么我要用这种写法,不用这种写法我照样可以实现功能啊。小编认为这种写法有两个优势

  • 标准化,通过提供一种统一的开发模式,无论对插件开发者还是使用者来说,都有一个规范去遵循。

  • 插件缓存,Vue.use 在安装插件的时候,会对插件进行缓存,即一个插件如果安装多次,实际上只会在第一次安装时生效。

插件的应用场景

  • 添加全局方法或者 property。

  • 添加全局资源:指令/过滤器/过渡等。

  • 通过全局混入来添加一些组件选项。

  • 添加 Vue 实例方法,通过把它们添加到 Vue.prototype 上实现。

  • 一个库,提供自己的 API,同时提供上面提到的一个或多个功能。如element-ui

提高Vue渲染性能,了解一下Object.freeze

当一个 Vue 实例被创建时,它将 data 对象中的所有的 property 加入到 Vue 的响应式系统中。当这些 property 的值发生改变时,视图将会产生“响应”,即匹配更新为新的值。但是这个过程实际上是比较消耗性能的,所以对于一些有大量数据但只是展示的界面来说,并不需要将property加入到响应式系统中,这样可以提高渲染性能,怎么做呢,你需要了解一下Object.freeze

Vue官网中,有这样一段话:这里唯一的例外是使用 Object.freeze(),这会阻止修改现有的 property,也意味着响应系统无法再_追踪_变化。这段话的意思是,如果我们的数据使用了Object.freeze,就可以让数据脱离响应式系统,那么该如何做呢?

比如下面这个表格,因为只是渲染数据,这时候我们就可以通过Object.freeze来优化性能

<template>
  <el-table :data="tableData" >
    <el-table-column prop="date" label="日期" width="180" />
    <el-table-column prop="name" label="姓名" width="180" />
    <el-table-column prop="address" label="地址" />
  </el-table>
</template>
<script>
export default {
  data() {
    const data = Array(1000)
      .fill(1)
      .map((item, index) => {
        return {
          date: &#39;2020-07-11&#39;,
          name: `子君${index}`,
          address: &#39;大西安&#39;
        }
      })
    return {
      // 在这里我们用了Object.freeze
      tableData: Object.freeze(data)
    }
  }
}
</script>

有的同学可能会有疑问,如果我这个表格的数据是滚动加载的,你这样写我不就没法再给tableData添加数据了吗?是,确实没办法去添加数据了,但还是有办法解决的,比如像下面这样

export default {
  data() {
    return {
      tableData: []
    }
  },
  created() {
    setInterval(() => {
      const data = Array(1000)
        .fill(1)
        .map((item, index) => {
          // 虽然不能冻结整个数组,但是可以冻结每一项数据
          return Object.freeze({
            date: &#39;2020-07-11&#39;,
            name: `子君${index}`,
            address: &#39;大西安&#39;
          })
        })
      this.tableData = this.tableData.concat(data)
    }, 2000)
  }
}

合理的使用Object.freeze,是可以节省不少渲染性能,特别对于IE浏览器,效果还是很明显的,赶快去试试吧。

最后如果你现在需要开发移动端项目,可以了解一下小编整理的一个开箱即用框架 vue-vant-base,也许可以帮到你哦

结语

不要吹灭你的灵感和你的想象力; 不要成为你的模型的奴隶。 ——文森特?梵高

相关推荐:

2020年前端vue面试题大汇总(附答案)

vue教程推荐:2020最新的5个vue.js视频教程精选

更多编程相关知识,请访问:编程入门!!

以上がVue プロジェクトで使用される実践的なヒントを共有しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はsegmentfault.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。