اکنون ثبت نام کنید

ورود

فراموشی پسورد

رمز را فراموش کردید ؟ لطفا ایمیل را وارد کنید تا لینک تغییر پسورد به ایمیل شما ارسال شود

ورود

اکنون ثبت نام کنید

Lorem ipsum dolor sit amet, consectetur adipiscing elit.Morbi adipiscing gravdio, sit amet suscipit risus ultrices eu.Fusce viverra neque at purus laoreet consequa.Vivamus vulputate posuere nisl quis consequat.

ایجاد یک برنامه یکسان در Vue و React. تفاوت در چیست؟

ایجاد یک برنامه یکسان در Vue و React. تفاوت در چیست؟

به دلیل اینکه در محل کار از Vue استفاده می‌کردم، شناخت نسبتا خوبی از آن داشتم. با این حال، کنجکاو بودم بدانم «چمنزارهای آن­سوی حصار چه شکلی است؟» (چمنزار در این مورد همان React است!)

مستندات و متون مربوط به React را خوانده و چندین ویدیو آموزشی هم تماشا کرده بودم. با وجود اینکه همه آن‌ها عالی بودند اما چیزی که من می‌خواستم بدانم این بود که React و Vue چه تفاوت‌هایی دارند. منظورم از تفاوت، این نبود که آیا هر دو آن‌ها دارای DOM های مجازی بودند یا خیر، یا اینکه پرداخت (Render) صفحات در هرکدام از آن‌ها چگونه انجام می‌گیرد. چیزی که من می‌خواستم این بود که یک نفر وقت بگذارد و تفاوت کد را برای من توضیح دهد! به مقاله‌ای نیاز داشتم که این موضوع را، برای کسی که تازه کار را با Vue یا React (یا به طورکلی توسعه وب) شروع کرده، به گونه‌ای توضیح دهد که بتواند شناخت بهتری از تفاوت‌های میان این دو به ­دست آورد.

متأسفانه، هیچ مقاله یا مطلبی که بتواند از عهده این کار برآمده و این موضوع را به‌خوبی پوشش دهد، نیافتم. بنابراین به این نتیجه رسیدم که بایستی خودم دست‌به‌کار شوم و شباهت‌ها و تفاوت‌های این دو را بیابم. به این ترتیب، با خودم فکر کردم که به همراه انجام این کار، کل روند انجام کار را نیز مستند کرده تا بالاخره مقاله‌ای با این موضوع تولید شده و در دسترس دیگران قرار گیرد.

کدام‌یک بهتر از پس آن برمی‌آید؟
کدام‌یک بهتر از پس آن برمی‌آید؟

تصمیم گرفتم یک برنامه نسبتاً استاندارد «فهرست انجام کارها» بسازم که به کاربر امکان اضافه و حذف موارد از فهرست را می‌دهد. هر دو برنامه (یکی نوشته‌شده با React و دیگری با Vue) با استفاده از CLI های پیش‌فرض (creat-react-app در React و vue-cli در Vue) ساخته شده‌اند. ضمناً، CLI مخفف عبارت Command Line Interface (واسط خط فرمان یا واسط نوشتاری) است.

به هر جهت، این مقدمه تا همین‌جا هم طولانی‌تر از آن شده که پیش‌بینی می‌کردم. پس بیایید با بررسی سریع ظاهر دو برنامه کار را شروع کنیم:

Vue در برابر React
Vue در برابر React

کد CSS برای هر دو برنامه کاملاً یکسان است، اما مکان قرارگیری این کدها، متفاوت است. با درنظرگرفتن این موضوع، بیایید نگاهی به ساختار فایل دو برنامه بیاندازیم:

ساختار Vue و React
Vue در سمت چپ و React در سمت راست

مشاهده خواهید کرد که ساختار هر دو نیز تقریباً یکسان است. تنها تفاوت این است که برنامه‌ای که با React ساخته شده دارای سه فایل CSS است درحالی‌که برنامه ساخته‌شده با Vue هیچ فایل CSS ای ندارد.

دلیل آن، این است که در create-react-app، جزئی (Component) از React یک فایل همراه برای حفظ سبک‌های آن خواهد داشت درحالی‌که CLI کتابخانه Vue، شیوه‌ای جامع و همه‌جانبه را در پیش گرفته و تمام سبک‌ها درون فایل Component موجود (فعلی) اعلان می‌گردند.

هر دو برنامه درنهایت خروجی یکسانی دارند و نمی‌توان گفت که امکان ساخت CSS ى متفاوت با React یا Vue وجود ندارد. درواقع این به ترجیح شخصی برمی‌گردد؛ بحث و گفتگوهای بسیاری در میان جامعه توسعه‌دهندگان درباره این‌که CSS چگونه باید باشد، وجود دارد؛ اما فعلاً، ما ساختار ارائه شده توسط این دو CLI را دنبال می‌کنیم.

پیش از اینکه جلوتر برویم، بیایید نگاهی کوتاه به یک نمونه جزء (Component) در Vue و React بیاندازیم:

Vue در سمت چپ و React در سمت راست
Vue در سمت چپ و React در سمت راست

اکنون، بیایید جزئیات اساسی و اصلی را بررسی کنیم!

چگونه داده‌ها را جهش (تغییر) می‌دهیم؟

نخست، منظور از «جهش داده (Mutate)» چیست؟ به نظر اصطلاحی فنی و تخصصی است، این‌طور نیست؟ این اصطلاح در اصل، تنها به معنی تغییر داده‌هایی است که قبلا ذخیره کرده‌ایم. بنابراین، اگر بخواهیم مقدار نام یک فرد را از John به Mark تغییر دهیم، درواقع «جهش داده» انجام داده‌ایم. تفاوت اصلی میان React و Vue در همین مورد است. درحالی‌که Vue ذاتاً یک شیء داده ( Data Object) ایجاد می‌کند تا داده بتواند آزادانه به‌روزرسانی شود، React یک شیء حالت (State Object) ایجاد می‌کند که برای به‌روزرسانی شدن، به انجام عملیات بیشتری نیاز دارد.

React این عملیات اضافی را به دلیلی قانع ­کننده و سودمند درنظر گرفته که بعدا به شرح آن می‌­پردازیم؛ اما بیایید ابتدا نگاهی به شیء داده در Vue و شیء حالت در React بیاندازیم:

همان­گونه که مشاهده می‌کنید ما داده‌هایی یکسان به هر دو وارد کرده‌­ا‌یم، اما هرکدام از آن­‌ها، این داده را به ­گونه‌­ای متفاوت برچسب زده است . بنابراین واردکردن داده­های اولیه به اجزاء (در هر دو کتابخانه) بسیار شبیه است. اما همان­گونه که قبلاً گفتیم، تغییر (جهش) این داده‌­ها در هرکدام از این دو متفاوت است.

فرض کنید یک عنصر داده‌ای به‌صورت   زیر داریم:

name: "Ehsan"

در Vue، به این داده با فراخوانی this.name ارجاع می‌­دهیم. همچنین می­‌توانیم با فراخوانی "this.name = "John این عنصر را به ­روزرسانی کنیم. این کار باعث می­‌شود که نام من به John تغییر کند.

در React، ما به همین بخش از داده با فراخوانی this.state.name ارجاع می­دهیم. در اینجا، تفاوت اصلی این است که ما نمی‌­توانیم به­ سادگی فقط بنویسیم "this.state.name = "John ، زیرا React به ­منظور جلوگیری از رخ دادن چنین جهش‌­هایی (تغییرات) که به سادگی اتفاق می‌­افتد و ناشی از بی­ دقتی و عدم توجه کافی است، محدودیت‌هایی در نظر گرفته است. ازاین‌رو، در React، این کار را در حالت کلی با نوشتن this.setState({name: "John"}) انجام می‌­دهیم.

با وجود اینکه خروجی این کار در اصل همان است که در Vue به ­دست آورده بودیم، اما علت نوشتن آن بخش از کد اضافه این است که زمانی ­که یک بخش از داده به­روزرسانی می­‌گردد، Vue ذاتاً به ­صورت پیش­فرض، نسخه خودش از setState را ترکیب می­‌کند. پس به طور خلاصه، React به setState و پس از آن داده به ­روزرسانی ­شده درون آن نیاز داشته و آن را درخواست می­‌کند، درحالی‌که Vue فرض می‌­کند اگر شما مقدار درون شیء را به­ روزرسانی کرده­‌اید، این کار (setState) را نیز می­‌خواهید انجام دهید. بنابراین، اصلاً چرا React این کار را انجام می­‌دهد و به چه علتی setState موردنیاز است؟ اجازه دهید ببینیم  Revanth Kumar دراین باره چه توضیحی می­‌دهد:

«دلیل این امر این است زمانی­که حالت (state) تغییر می­‌کند، React می­خواهد هوک‌های (Hooks) چرخه‌هایی مانند: componentWillReceiveProps، shouldComponentUpdate، componentWillUpdate، پرداخت (render) و componentDidUpdate را دوباره اجرا کند. React اطلاع دارد زمانی ­که شما تابع setState را فراخوانی کرده‌­اید، حالت تغییر کرده است. اگر شما مستقیماً حالت را جهش (تغییر) داده‌­اید، React برای پیگیری و دنبال­ کردن تغییرات ایجاد شده و اینکه چه هوک‌هایی در چرخه را باید اجرا کند و امثال آن، بایستی کارهای بسیاری انجام دهد. بنابراین React به­ منظور ساده نمودن این کار از useState استفاده می­نماید.»

حال که جهش‌­ها را بررسی کرده و از سر راه برداشتیم، بیایید از طریق بررسی شیوه افزودن موارد جدید به دو برنامه «فهرست انجام کارها» (که یکی با React و دیگری با Vue نوشته شده)، به سراغ بررسی مطالب پایه‌­ای و اصولی برویم.

چگونه در فهرست انجام کارها، موردی جدید ایجاد کنیم؟


React:

createNewToDoItem = () => {
    this.setState( ({ list, todo }) => ({
      list: [
          ...list,
        {
          todo
        }
      ],
      todo: ''
    })
  );
};

React چگونه موردی جدید به فهرست انجام کارها اضافه می­‌کند؟

در React، فیلد ورودی ما دارای یک خصیصه­ است که مقدار (Value) نامیده می­‌شود. این مقدار به‌طور خودکار از طریق استفاده از تعدادی تابع به روز می­‌شود که این توابع به ­منظور ایجاد چیزی شبیه شیوه انجام اتصال دوطرفه توسط Vue، باهم ادغام می­‌شوند. ما این مورد (مشابه شیوه اتصال دوطرفه در Vue) را با اضافه نمودن یک onChange event listener اضافی به فیلد ورودی، ایجاد می­‌کنیم. بیایید به فیلد ورودی نگاهی سریع بیندازیم تا موضوع را متوجه شوید:

<input type="text" 
       value={this.state.todo} 
       onChange={this.handleInput}/>


تابع handInput هرزمان که مقدار فیلد ورودی تغییر کند، اجرا می­‌گردد. این تابع، todo را که درون شیء حالت (State Object) جای گرفته، با تنظیم آن به هر چیزی که در فیلد ورودی قرار دارد، به ­روز می­‌کند. این تابع، به‌صورت زیر عمل می­‌کند:

handleInput = e => {
  this.setState({
    todo: e.target.value
  });
};

حال هر زمان که کاربر برای اضافه نمودن یک مورد جدید دکمه + را در صفحه فشار دهد، تابع createNewToDoItem ذاتاً this.setState را اجرا کرده و (خروجی) آن را به یک تابع منتقل می‌­کند. این تابع به دو پارامتر نیاز دارد، پارامتر اول کل آرایه فهرست شیء حالت است و دومین پارامتر todo است (که توسط تابع handleInput به ­روز می‌­شود). درنهایت، خروجی این تابع شیء جدیدی است که شامل کل فهرست قبلی و todo اضافه ­شده به انتهای آن است. پس‌ازآن، کل فهرست با استفاده از اپراتور Spread اضافه می­‌گردد (اگر تاکنون راجع با این عملگر چیزی نشنیده­‌ا‌ید، آن را در گوگل جستجو کنید. این عملگر یکی از سینتاکس‌های ES6 است).

در آخر، todo را در یک استرینگ (String) خالی قرار می‌­دهیم که به طور خودکار مقدار موجود در فیلد ورودی را به ­روز می‌کند.


Vue:

createNewToDoItem() {
    this.list.push(
        {
            'todo': this.todo
        }
    );
    this.todo = '';
}

Vue چگونه موردی جدید به فهرست انجام کارها اضافه می­‌کند؟

در Vue، فیلد ورودی دارای قابلیتی است که v-model نام دارد. این قابلیت به ما امکان انجام کاری را می‌­دهد که به‌عنوان اتصال دوطرفه شناخته می‌­شود. بیایید به فیلد ورودی نگاهی سریع بیندازیم، پس‌ازآن موضوع را توضیح خواهیم داد:

<input type="text" v-model="todo"/>

V-model، ورودی این فیلد را به کلید موجود در شیء داده که toDoItem نام دارد، وصل می‌­کند. وقتی صفحه بارگیری می‌شود، باید toDoItem را به ­صورت یک استرینگ خالی تنظیم کنیم، به این شکل:  todo: "". اگر داده­‌ای از قبل در آن وجود داشته باشد، مانند  "todo: "add some text here، فیلد ورودی با متن add some text here که در داخل آن نمایش داده می‌­شود، بارگذاری می­‌گردد. در ­هرحال، همان­گونه که قبلاً گفتیم، آن (toDoItem) را به‌عنوان یک رشته خالی در نظر گرفته و هر متنی که در فیلد ورودی بنویسیم به مقدار todo متصل می­‌گردد (متن نوشته‌شده در فیلد ورودی در todo قرار می­‌گیرد). این، یک اتصال دوطرفه کارآمد و مؤثر است (فیلد ورودی می‌تواند شیء داده را به ­روز کند و شیء داده می‌تواند فیلد ورودی را به ­روز کند).

بنابراین با نگاهی به کدcreateNewToDoItem() که پیش‌تر ارائه شد، مشاهده می­‌کنیم که کار انجام‌گرفته به این صورت است: ابتدا محتویات todo را به آرایه وارد و سپس todo را به یک رشته خالی به ­روزرسانی می­‌کنیم.

چگونه موردی را از فهرست انجام کارها حذف کنیم؟

React:

deleteItem = indexToDelete => {
    this.setState(({ list }) => ({
      list: list.filter((toDo, index) => index !== indexToDelete)
    }));
};


React چگونه موردی را از فهرست انجام کارها حذف می‌­کند؟

بنابراین، باوجود اینکه تابع deleteItem در داخل ToDo.js قرار دارد، در مرحله اول، با استفاده از انتقال تابع deleteItem() به عنوان یک ویژگی مربوط به <ToDoItem/> ، به صورتی که در زیر بیان شده است، به ­سادگی توانستم در داخل ToDoItem.js به آن (تابع deleteItem) ارجاع دهم:

<ToDoItem deleteItem={this.deleteItem.bind(this, key)}/>

این انتقال به این دلیل انجام می­گیرد که تابع (deleteItem) را در دسترس (جزء) فرزند قرار دهد. با وجود اینکه کلید، در هنگام انجام کلیک مورد استفاده قرار گرفته تا تابع یاد شده بتواند تشخیص دهد که کدام یک از ToDoItem ها باید حذف گردند، مشاهده خواهید نمود که ما علاوه بر انتقال این پارامتر (کلید)، this را نیز متصل کرده و انتقال می­‌دهیم. سپس، در داخل جزء ToDoItem ، موارد زیر را انجام می‌دهیم:

<div className=”ToDoItem-Delete” onClick={this.props.deleteItem}>-</div> 

تنها کاری که نیاز است برای ارجاع به تابعی که در داخل جزء والد قرار دارد انجام دهیم، ارجاع به this.props.deleteItem است.


Vue:

onDeleteItem(todo){
  this.list = this.list.filter(item => item !== todo);
}

Vue چگونه موردی را از فهرست انجام کارها حذف می­‌کند؟

Vue این کار را با روشی انجام می‌­دهد که کمی متفاوت است. در اینجا، بایستی سه ​​مرحله را طی کنیم:


در مرحله نخست، روی عنصری که می‌­خواهیم تابع را (برای آن) فراخوانی کنیم:

<div class=”ToDoItem-Delete” @click=”deleteItem(todo)”>-</div>


سپس باید یک تابع emit را به‌عنوان method در داخل جزء فرزند (در این مورد ToDoItem.vue) ایجاد کنیم که به شکل زیر است:

deleteItem(todo) {
    this.$emit('delete', todo)
}


زمانی­که ToDoItem.vue را درون ToDo.vue اضافه می­‌کنیم، درواقع به یک تابع ارجاع می‌دهیم:

<ToDoItem v-for="todo in list" 
          :todo="todo" 
          @delete="onDeleteItem" // <-- this :)
          :key="todo.id" />

این همان چیزی است که به ­عنوان یک شنونده-رویداد (Event-listener) سفارشی شناخته می­‌شود. این شنونده-رویداد، هر رویدادی را که در آن یک انتشار (emit) از طریق رشته “delete” راه­‌اندازی و آغاز می‌­شود، شنود می­‌کند. اگر آن delete را بشنود، تابعی به نام onDeleteItem را راه­‌اندازی می­‌کند. این تابع به‌جای ToDoItem.vue ، در داخل ToDo.vue قرار می­‌گیرد. این تابع، همان‌طور که در آغاز گفته شد، صرفاً آرایه (array) todo را درون شیء داده فیلتر می­‌کند تا موردی را که روی آن کلیک شده است، حذف کند.

همچنین شایان ذکر است که در مورد مثال Vue می­‌توانستم به­ صورت زیر، به ­سادگی بخش $emit را در داخل شنونده @click نیز بنویسم:

 <div class=”ToDoItem-Delete” @click=”$emit(‘delete’, todo)”>-</div> 

این کار می‌تواند تعداد مراحل را از ۳ به ۲ کاهش دهد و انجام آن صرفاً یک ترجیح شخصی است.

به طور خلاصه، جزءهای (Components) فرزند در React از طریق this.props به توابع والد دسترسی خواهند داشت (به‌شرط اینکه شما این ویژگی­‌ها را (به جزء فرزند) انتقال دهید، که این عملی کاملاً استاندارد بوده و در سایر نمونه­‌های React بارها با آن روبه ­رو خواهید شد)، درحالی‌که در Vue، شما باید رویدادهای (جزء) فرزند را منتشر (emit) کنید که معمولاً (این رویدادها) در جزء والد گردآوری خواهند شد.

چگونه شنونده­‌های رویداد را ایجاد کنیم؟

React:

شنونده‌­های رویداد (Event listeners) برای موارد ساده مانند رویدادهای کلیک، ساده و سرراست هستند. در اینجا مثالی از چگونگی ایجاد یک رویداد کلیک برای دکمه‌­ای که یک مورد جدید ToDo (کار جدید) ایجاد می­‌کند، ارائه شده است:

<button className=”ToDo-Add” onClick={this.createNewToDoItem}>+</div>.


همان­ گونه که گفته شد، انجام این کار بسیار آسان بوده و تقریباً مشابه حالتی است که یک (رویداد) onClick درون­ خطی را با vanilla JS مدیریت و کنترل می­‌کنیم. همان‌طور که در بخش Vue گفته شد، راه­‌اندازی یک شنونده رویداد به­ منظور کنترل زمان فشرده ­شدن دکمه enter، به کار و زمان بیشتری نیاز دارد. انجام این کار، اصولاً نیاز به یک رویداد onKeyPress دارد که با فیلد ورودی، به ­صورت زیر، کنترل و مدیریت شود:

<input type=”text” onKeyPress={this.handleKeyPress}/>.


این تابع، هرزمان که تشخیص دهد کلید “enter” فشرده شده است، به­طور ذاتی، تابع createNewToDoItem را به ­صورت زیر، راه­‌اندازی می‌­کند:

handleKeyPress = (e) => {
if (e.key === ‘Enter’) {
this.createNewToDoItem();
}
};

Vue:

این کار (ایجاد شنونده­‌های رویداد) در Vue بسیار ساده است. تنها کافیست از نماد @ استفاده و پس‌ازآن نوع شنونده رویدادی که می‌خواهیم پیاده‌­سازی کنیم، استفاده کنیم. به‌عنوان مثال، به ­منظور اضافه کردن یک شنونده رویداد کلیک، می‌توانیم کد زیر را بنویسیم:

<button class=”ToDo-Add” @click=”createNewToDoItem()”>+</div> 

نکته: @click درواقع شکل مختصر v-on:click است. نکته جالب در مورد شنونده­‌های رویداد در Vue این است که می‌توانید چیزهایی به آن­‌ها متصل کنید، مانند: .once که از اینکه شنونده رویداد بیشتر از یک‌بار راه‌­اندازی شود، جلوگیری می­‌کند. همچنین تعدادی میانبر برای نوشتن (کد) شنوند­ه‌-رویدادی که برای کنترل و مدیریت ضربه به کلیدها استفاده می‌­شوند، نیز وجود دارد. علاوه­ برآن، به این نکته نیز پی بردم که ایجاد یک شنونده رویداد در React برای زمانی که دکمه enter، جهت اضافه­ نمودن موارد جدید ToDo ، فشرده می­‌شود، کمی کار و زمان بیشتری نیاز دارد. در Vue، برای این کار به ­سادگی، صرفاً می‌­توان کد زیر را نوشت:

<input type=”text” v-on:keyup.enter=”createNewToDoItem”/>

چگونه داده‌­ها را به یک جزء فرزند انتقال دهیم:

React:

درواقع، ما ویژگی­‌ها (props) را در لحظه‌­ای که جزء (component) فرزند ساخته می‌­شود به ­صورت زیر به آن (جزء فرزند) انتقال می‌­دهیم:

<ToDoItem key={key} item={todo} />

در اینجا مشاهده می­‌کنیم که دو ویژگی به جزء ToDoItem منتقل شده است. از این لحظه به بعد، می‌توانیم در جزء فرزند از طریق this.props به آن­‌ها ارجاع دهیم. بنابراین برای دسترسی به ویژگی item.todo ، تنها لازم است که this.props.item را فراخوانی کنیم.

Vue:

در Vue نیز، ما ویژگی­‌ها را در لحظه­ای که جزء فرزند ساخته می‌­شود به­صورت زیر به آن انتقال می‌­دهیم:

<ToDoItem v-for="todo in list" 
            :todo="todo"
            :key="todo.id"
            @delete="onDeleteItem" />

پس‌ازآنکه این کار انجام شد، ما آن­‌ها (ویژگی­‌ها) را از طریق props: [ "todo" ] به آرایه ویژگی­‌ها در جزء فرزند انتقال می­‌دهیم. این ویژگی­‌ها از این به بعد می‌­توانند با استفاده از نامشان در جزء فرزند ارجاع داده شوند، در این مورد، این کار با “todo” انجام می‌­شود.

و حالا ما مقاله‌­ای که تفاوت React و Vue را بررسی کند، در اختیار داریم!

در این مقاله، ما به شیوه اضافه­ کردن، حذف و تغییر داده­‌ها، انتقال داده در قالب ویژگی (prop) از والد به فرزند و ارسال داده از فرزند به والد در قالب شنوند­ه­‌های رویداد، پرداختیم. البته تفاوت­های ظریف بسیار دیگری بین React و Vue وجود دارد، اما امیدوارم که مطالب این مقاله جهت استفاده به‌عنوان پایه و اصول شناخت عملکرد هر دو چارچوب، به شما کمک کند.

این مقاله توسط Sunil Sandhu نوشته و در مدیوم منتشر شده است.

لینک گیتهاب Vue

لینک گیتهاب React

درباره مدیریت

ارسال یک پاسخ