この記事では、私が Vue の研究中に学んだ、開発効率とパフォーマンスを向上させるためのいくつかのヒントを共有します。
$attrs
と $listeners
# を上手に使用する#$attrs
は、親コンポーネントから子コンポーネントに渡される、props
によってキャプチャされず、class
および style## ではないすべてのパラメーターを記録するために使用されます。 # ただし、
$listeners は、
.native 修飾子なしで親コンポーネントから渡されたすべてのイベントを記録するために使用されます。 (学習ビデオ共有:
vuejs ビデオ チュートリアル )
Vue.component('child', { props: ['title'], template: '<h3>{{ title }}</h3>' }) new Vue({ data:{a:1,title:'title'}, methods:{ handleClick(){ // ... }, handleChange(){ // ... } }, template:' <child class="child-width" :a="a" b="1" :title="title" @click.native="handleClick" @change="handleChange">', })
にあります。
の値は
{a:1,b:"1"}
です値は
{change: handleChange}
$attrs と
$listeners を使用できます。次のようなサブカプセル化されたコンポーネントで使用すると効率的です:
Vue.component("custom-dialog", { // 通过v-bind="$attrs"和v-on="$listeners"把父组件传入的参数和事件都注入到el-dialog实例上 template: '<el-dialog v-bind="$attrs" v-on="$listeners"></el-dialog>', }); new Vue({ data: { visible: false }, // 这样子就可以像在el-dialog一样用visible控制custom-dialog的显示和消失 template: '<custom-dialog :visible.sync="visible">', });
Vue.component("custom-select", { template: `<el-select v-bind="$attrs" v-on="$listeners"> <el-option value="选项1" label="黄金糕"/> <el-option value="选项2" label="双皮奶"/> </el-select>`, }); new Vue({ data: { value: "" }, // v-model在这里其实是v-bind:value和v-on:change的组合, // 在custom-select里,通过v-bind="$attrs" v-on="$listeners"的注入, // 把父组件上的value值双向绑定到custom-select组件里的el-select上,相当于<el-select v-model="value"> // 与此同时,在custom-select注入的size变量也会通过v-bind="$attrs"注入到el-select上,从而控制el-select的大小 template: '<custom-select v-model="value" size="small">', });
## の賢い使用法 は、親コンポーネントから子コンポーネントに渡される、props
によってキャプチャされ、class
ではないすべての props を記録するために使用されます。 スタイル
パラメータ。たとえば、<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">Vue.component(&#39;child&#39;, {
props: [&#39;title&#39;],
template: &#39;<h3>{{ title }}</h3>&#39;
})
new Vue({
data:{a:1,title:&#39;title&#39;},
methods:{
handleClick(){
// ...
},
handleChange(){
// ...
}
},
template:&#39;
<child class="child-width" :a="a" b="1" :title="title">&#39;,
})</pre><div class="contentsignin">ログイン後にコピー</div></div>
は
にあり、$props
の値は {title:'title'}## です。 #。
$props は、
Vue.component('grand-child', { props: ['a','b'], template: '<h3>{{ a + b}}</h3>' }) // child和grand-child都需要用到来自父组件的a与b的值时, // 在child中可以通过v-bind="$props"迅速把a与b注入到grand-child里 Vue.component('child', { props: ['a','b'], template: ` <div> {{a}}加{{b}}的和是: <grand-child v-bind="$props"/> </div> ` }) new Vue({ template:' <child class="child-width" :a="1" :b="2">', })
3 のように、self コンポーネントと孫コンポーネントによって定義された props
が同じ場合に使用できます。コンポーネントcreated、
mounted などのライフサイクルがないことを意味します)。利点は、これは単なる関数であるため、レンダリングのオーバーヘッドがはるかに低いことです。
冒頭の例を機能コンポーネントに変更すると、コードは次のようになります:
<script> export default { name: "anchor-header", functional: true, // 以functional:true声明该组件为函数式组件 props: { level: Number, name: String, content: String, }, // 对于函数式组件,render函数会额外传入一个context参数用来表示上下文,即替代this。函数式组件没有实例,故不存在this render: function (createElement, context) { const anchor = { props: { content: String, name: String, }, template: '<a :id="name" :href="`#${name}`"> {{content}}</a>', }; const anchorEl = createElement(anchor, { props: { content: context.props.content, //通过context.props调用props传入的变量 name: context.props.name, }, }); const el = createElement(`h${context.props.level}`, [anchorEl]); return el; }, }; </script>
4. Vue.config.devtools をうまく使いましょう
Vue.config.devtools 構成を変更するだけです:
// 务必在加载 Vue 之后,立即同步设置以下内容 // 该配置项在开发版本默认为 `true`,生产版本默认为 `false` Vue.config.devtools = true;
検出を通過できます。
cookie のユーザー ロール情報を使用して、この構成項目を有効にするかどうかを決定します。これにより、オンラインでのバグ発見の利便性が向上します。 5.method
method を使用して、高階関数によって返された結果を割り当てます。例:
<script> import { debounce } from "lodash"; export default { methods: { search: debounce(async function (keyword) { // ... 请求逻辑 }, 500), }, }; </script>
上記の
search 関数には、手ぶれ補正機能付きリクエスト関数である debounce によって返された結果が割り当てられます。この方法により、コンポーネント内に手ぶれ補正ロジックを自分で記述する必要がなくなります。
これは例です
サンドボックス
メソッドと元のメソッドの違いを確認できます。 . 以下に示すように:
さらに、method
は、generator として定義することもできます。必要な関数 実行中に順序が強調され、最後のステータスを記録するために
data で変数を定義する必要がある場合は、ジェネレーターの使用を検討できます。 たとえば、非常に一般的なシナリオがあります: WeChat ビデオ通話が接続されると、
通話時間
通話時間 1 秒ごとに更新する、つまり 呼び出し時刻 を取得する関数を 1 秒に 1 回実行する必要がある 通常の関数として記述する場合、時刻を記録する変数を data に格納する必要がある。しかし、ジェネレーターを使用すると、以下に示すように非常に賢く解決できます:
<template> <div id="app"> <h3>{{ timeFormat }}</h3> </div> </template> <script> export default { name: "App", data() { return { // 用于显示时间的变量,是一个HH:MM:SS时间格式的字符串 timeFormat: "", }; }, methods: { genTime: function* () { // 声明存储时、分、秒的变量 let hour = 0; let minute = 0; let second = 0; while (true) { // 递增秒 second += 1; // 如果秒到60了,则分加1,秒清零 if (second === 60) { second = 0; minute += 1; } // 如果分到60了,则时加1,分清零 if (minute === 60) { minute = 0; hour += 1; } // 最后返回最新的时间字符串 yield `${hour}:${minute}:${second}`; } }, }, created() { // 通过生成器生成迭代器 const gen = this.genTime(); // 设置计时器定时从迭代器获取最新的时间字符串 const timer = setInterval(() => { this.timeFormat = gen.next().value; }, 1000); // 在组件销毁的时候清空定时器和迭代器以免发生内存泄漏 this.$once("hook:beforeDestroy", () => { clearInterval(timer); gen = null; }); }, }; </script>
ページの効果は次のとおりです:
コードアドレス: https://codesandbox.io/s/jovial-williams-nkouf?file=/src/App.vue
ただし、このメソッドは実行できないことに注意してください。アロー関数であること
アロー関数は、
method関数 (例:plus: () =>) の定義には使用しないでください。 ; これ.a
)。その理由は、アロー関数が親スコープのコンテキストにバインドされているため、
thisは期待どおりに Vue インスタンスをポイントせず、
this.aは
unknown# になります。 ##。6. watch の配列形式を賢く使用する
<script> export default { data() { return { value: "", }; }, methods: { fn1() {}, fn2() {}, }, watch: { value: { handler() { fn1(); fn2(); }, immediate: true, deep: true, }, }, }; </script>
虽然fn1
和fn2
都需要在value
变动的时候调用,但两者的调用时机可能不同。fn1
可能仅需要在deep
为false
的配置下调用既可。因此,Vue
在watch
的值添加了Array
类型来针对上面所说的情况,如果用watch
为Array
的写法处理可以写成下面这种形式:
<script> watch:{ 'value':[ { handler:function(){ fn1() }, immediate:true }, { handler:function(){ fn2() }, immediate:true, deep:true } ] } </script>
$options
$options
是一个记录当前Vue
组件的初始化属性选项。通常开发中,我们想把data
里的某个值重置为初始化时候的值,可以像下面这么写:
this.value = this.$options.data().value;
这样子就可以在初始值由于需求需要更改时,只在data
中更改即可。
这里再举一个场景:一个el-dialog
中有一个el-form
,我们要求每次打开el-dialog
时都要重置el-form
里的数据,则可以这么写:
<template> <div> <el-button @click="visible=!visible">打开弹窗</el-button> <el-dialog @open="initForm" title="个人资料" :visible.sync="visible"> <el-form> <el-form-item label="名称"> <el-input v-model="form.name"/> </el-form-item> <el-form-item label="性别"> <el-radio-group v-model="form.gender"> <el-radio label="male">男</el-radio> <el-radio label="female">女</el-radio> </el-radio-group> </el-form-item> </el-form> </el-dialog> </div> </template> <script> export default { name: "App", data(){ return { visible: false, form: { gender: 'male', name: 'wayne' } } }, methods:{ initForm(){ this.form = this.$options.data().form } } }; </script>
每次el-dialog
打开之前都会调用其@open
中的方法initForm
,从而重置form
值到初始值。如下效果所示:
以上代码放在sanbox里
如果要重置data
里的所有值,可以像下面这么写:
Object.assign(this.$data, this.$options.data()); // 注意千万不要写成下面的样子,这样子就更改this.$data的指向。使得其指向另外的与组件脱离的状态 this.$data = this.$options.data();
v-pre
用于跳过被标记的元素以及其子元素的编译过程,如果一个元素自身及其自元素非常打,而又不带任何与Vue
相关的响应式逻辑,那么可以用v-pre
标记。标记后效果如下:
只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。
对于部分在首次渲染后就不会再有响应式变化的元素,可以用v-once
属性去标记,如下:
<el-select> <el-option v-for="item in options" v-once :key="item.value" :label="item.label" :value="item.value" >{{i}}</el-option > </el-select>
如果上述例子中的变量options
很大且不会再有响应式变化,那么如例子中用上v-once
对性能有提升。
如果想监听子组件的生命周期时,可以像下面例子中这么做:
<template> <child @hook:mounted="removeLoading" /> </template>
这样的写法可以用于处理加载第三方的初始化过程稍漫长的子组件时,我们可以加loading
动画,等到子组件加载完毕,到了mounted
生命周期时,把loading
动画移除。
初次之外hook
还有一个常用的写法,在一个需要轮询更新数据的组件上,我们通常在created
里开启定时器,然后在beforeDestroy
上清除定时器。而通过hook
,开启和销毁定时器的逻辑我们都可以在created
里实现:
<script> export default { created() { const timer = setInterval(() => { // 更新逻辑 }, 1000); // 通过$once和hook监听实例自身的beforeDestroy,触发该生命周期时清除定时器 this.$once("hook:beforeDestroy", () => { clearInterval(timer); }); }, }; </script>
像上面这种写法就保证了逻辑的统一,遵循了单一职责原则。
以上が開発効率とパフォーマンスを向上させるための 9 つの Vue のヒントの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。