Vue js یک فریمورک جاوا اسکریپت برای طراحی روابط کاربری است. در این مطلب به آموزش Vue js به صورت گام به گام و مثال های کاربردی میپردازیم.

در عصر طلایی کتابخانه‌ها و فریمورک‌های (framework) جاوا اسکریپت هستیم.
هر روز شرکت‌های بیشتری برنامه‌های (
app) کاملاً تحت وب و پویا را در کنار برنامه‌های قدیمی pc (دسکتاپ) ارائه می‌کنند.
یا حتی برنامه‌های تحت وب را جایگزین برنامه‌های
pc کرده‌اند. این یعنی همه‌چیز به صورت مداوم در حال تغییر است.
برخی فریمورک‌ها شهرت خود را از دست می‌دهند و دوباره معروف می‌شوند، اما مفهوم اصلی، که برنامه‌نویسان سعی دارند به آن برسند، ثابت باقی می‌ماند.

Vue.js مانند ری‌اکت (React) از شهرت بالایی میان برنامه‌نویسان جاوااسکریپت برخوردار است. بیایید این آموزش را با هم شروع کنیم!

بهترین زبان‌‌ های برنامه نویسی در ۲۰۱۹: ۱۰ زبان برتر برای یادگیری

 

مطالبی که باید از پیش بدایند:

  • آشنایی اولیه با جاوا اسکریپت
  • آشنایی با ES6، ویژگی‌ها و سینتکس (syntax)
  • Node.js و nmp (یا yarn) باید به صورت سراسری در سیستم‌تان نصب باشد.
  • آشنایی با REST APIها به شما در یادگیری کمک می‌کند، اما درباره‌ی آنها در این آموزش توضیحاتی خواهیم داد.

دوره های مرتبط در فرانش

 

اهداف آموزش Vue js

می‌خواهیم در آموزش Vue.js یک اپلیکیشن ساده را با استفاده از Vue بنویسیم. این اپلیکیشن یک پایگاه داده‌ی ساده‌ی کارمندان است. مطالب زیر را یاد خواهیم گرفت:

  • چگونه Vue را راه‌اندازی کنیم.
  • آناتومی یک فایل Vue
  • چگونه در Vue با داده (Dataمتد (Methodدستورات شرطی (Conditional Statement) و رویدادها (Event) کار کنیم.
  • چگونه کاربران (کارمندان) را در سیستم ایجاد کنیم (Creatبه‌روزرسانی کنیم (Updateببینیم (View) و حذف کنیم (Delete).
  • چگونه برای هر یک از اعمال بالا یک API Call انجام دهیم.
  • چگونه از جدول، فرم و اعتبارسنجی فرم استفاده کنیم.

 

Vue.js چیست؟

  • Vue (یا Vue.js) یک فریمورک جاوا اسکریپت متن‌باز (Open Source) و فرانت‌اند (Front End) است.
  • Vue همان لایه‌ی View در یک اپلیکیشن MVC است (Model View Controller).
  • Vue در حال حاضر یکی از معروف‌ترین کتابخانه‌ها/فریمورک‌های جاوااسکریپت است.
  • مانند بسیاری از پروژه‌های معروف دیگر، مثل ری‌اکت (فیسبوک)(React-Facebook) و انگولار (گوگل)( Angular-Google)، یک شرکت بزرگ از Vue حمایت نمی‌کند. Evan You و یک انجمن متن‌باز (Open Source Community) ابتدا Vue را نوشتند.

 

نصب و راه‌اندازی Vuejs

دو روش برای راه‌اندازی Vue.js وجود دارد: در یک پروژه‌ی Node یا مستقیماً آن را به یک فایل استاتیک (HTML (Static HTML File وارد کنیم.
بیایید ابتدا به روش دوم نگاهی بیندازیم، چون ساده‌ترین روش راه‌اندازی و معرفی است.
آنهایی که فقط از کتابخانه‌ای مانند
JQuery استفاده کرده‌اند، با این روش بسیار آشنا هستند.
اگر قبلاً از ری‌اکت یا فریمورک جاوا اسکریپت دیگری استفاده کرده‌اید، می‌توانید به بخش بعدی آموزش بروید.

می‌توانیم یک فایل HTML پایه بسازیم و یک CDN مرتبط با Vue را به head اضافه کنیم و سپس یک تگ <div> با id، app بسازیم.

آموزش ایجاد وب سرور با صفحه HTML به کمک ESP8266

 

فایل HTML استاتیک

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width,initial-scale=1.0" />
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

    <title>Vue App</title>
  </head>

  <body>
    <div id="app"></div>
  </body>
</html>

می‌توانیم یک برنامه‌ی “Hellow World” ساده با Vue بنویسیم. در app با استفاده از {} از یک message رندر می‌گیریم (Render).
در تگ
<script>، داده و DOM را به هم لینک می‌کنیم. یک Vue جدید می‌سازیم و propery مربوط به message روی data به صورت زیر است:

<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width,initial-scale=1.0" />
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

    <title>Vue App</title>
  </head>

  <body>
    <div id="app">{{message}}</div>

    <script>
      const App = new Vue({
        el: '#app',
        data: {
          message: 'Hello Vue!',
        },
      })
    </script>
  </body>
</html>

آموزش vue

می‌توانیم داده‌ی رندر گرفته شده را ببینیم.

تا اینجا اتفاق خیره‌کننده‌ای رخ نداده است. می‌توانید آن را در بخش معرفی اسناد هم یاد بگیرید. اما مسئله‌ی اساسی این است که به شما نشان می‌دهد که Vue جاوا اسکریپت ساده است و نیازی نیست نگران Node، Babel، Webpack و امثال این‌ها باشید.

پیشنهاد فرانش به شما
بهترین زبان‌‌ های برنامه نویسی در ۲۰۱۹: ۱۰ زبان برتر برای یادگیری

Vue CLI

بیشتر اوقات از Vue در یک فایل استاتیک HTML استفاده نخواهید کرد. درعوض از اکوسیستم Node سود خواهید برد.
ساده
‌ترین راه برای انجام این کار استفاده از Vue CLI یا واسط دستوری (Vue (Vue Command Line Interface است.
همان‌طور که در بخش “مطالبی که از پیش باید بدانید” هم عنوان شد، باید با
Node و nmp/yarn آشنا باشید و نحوه‌ی کار با پکیج‌های محلی و سراسری (Local and Global Package) را بدانید.

اول Vue CLI را نصب خواهیم کرد.

# install with npm
npm i -g @vue/cli @vue/cli-service-global

# install with yarn
yarn global add @vue/cli @vue/cli-service-global

حالا که Vue CLI را به صورت سراسری نصب کرده‌ایم، می‌توانیم از دستور vue در هرجایی استفاده کنیم. از دستور vue create برای ایجاد یک پروژه‌ی جدید استفاده می‌کنیم.

vue create معادل create-react-app است.

vue create vue-app

به شما گزینه‌ای برای انتخاب default یا manual داده می‌شود و می‌توانیم default را انتخاب کنیم.

Vue CLI v3.7.0
? Please pick a preset: (Use arrow keys)
❯ default (babel, eslint)
  Manually select features

وقتی این کار را انجام دادید، می‌توایند به سراغ برنامه‌ی جدیدی که تازه ایجاد کردید، بروید و با دستور serve سرور dev را اجرا کنید.

cd vue-app
npm run serve
# or
yarn serve

وقتی سرور را اجرا کردید، به آدرس http://localhost:8080/ بروید تا صفحه‌ی default را ببینید.

vue.js

در این مرحله راه‌اندازی به پایان رسیده است و می‌توانید از Vue استفاده کنید.
اگر از
Visual Studio Code استفاده می‌کنید، پلاگ‌این Vetur را نصب کنید تا از امکانات هایلایت شدن سینتکس‌ها، فرمت و مانند این‌ها استفاده کنید.

آموزش React Native: برنامه نویسی اندروید با جاوا اسکریپت

 

Vue DevTools

آخرین چیزی که باید در استفاده از Vue در میان ابزارهایتان داشته باشید، Vue DevTools است.
Vue DevTools یک add-on DeveloperTools برای اتگولار (Angular) است که به شما کامپوننت‌ها (Component)، استیت (state) آنها، متدها و غیره را نشان می‌دهد.

  • Vue DevTools برای Chrome
  • Vue DevTools برای FireFox
پیشنهاد فرانش به شما
آموزش انگولار: شروع به کار با Angular 4

 

آغاز به کار

تبریک. حالا آماده به کار هستید! حالا یک Vue boilerplate جدید در اختیار دارید.
در فایل‌های پروژه، یک پوشه‌ی
public دارید که index.html در آن قرار دارد. main.js به عنوان نقطه‌ی شروع اجرای برنامه در پوشه‌ی src قرار دارد.
کامپوننت‌های
HelloWorld.vue و App.vue فایل‌های .vue را به ما نشان می‌دهند.

یادگیری vue.js

نقطه‌ی شروع اجرای برنامه

در main.js، Vue را وارد برنامه می‌کنیم و از App در قسمت app div در فایل index.html رندر می‌گیریم. لازم نیست این فایل را تغییر دهید.

import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
}).$mount('#app')

 

آناتومی یک فایل Vue

تمام چیزهایی دیگری که می‌سازیم، یک فایل .vue خواهند بود. این فایل شامل سه بخش است:

  • <template>
  • <script>
  • <style>

کد زیر را ببینید:

<template></template>

<script>
  export default {
    name: 'component-name',
  }
</script>

<style scoped></style>

شاید کد بالا برایتان عجیب باشد. معمولاً کد نویسی فرانت-اند (Front-End) مسائل مربوط به HTML، CSS و JavaScript را از هم جدا می‌کند، اما در کد بالا هر سه با هم یکجا هستند. با این وجود جاوا اسکریپت و شیوه‌ی طراحی برنامه‌ها تغییر کرده است و درواقع نگه‌ داشتن استایل، view و کامپوننت‌ها در یکجا نوعی مزیت محسوب می‌شود و نگه‌داری کد را ساده‌تر می‌کند.

داده‌ها و منطق یک کامپوننت به تگ <script> برده می‌شوند، اما تنها داشتن name الزامی است. تگ <style> فقط دارای CSS است.
می‌توانیم با استفاده از شناسه‌ی
scoped، کد CSS را تنها برای همان کامپوننت اعمال کنیم و اثر آن در کل برنامه اعمال نشود.

حالا بیایید نوشتن برنامه را شروع کنیم.

مثل همیشه، این آموزش درباره‌ی عملکرد است، نه استایل. بنابراین در فایل index.html، به Primitive /UI لینک می‌دهیم و کمی استایل پیش‌فرض و ساده به برنامه اضافه می‌کنیم.

<link rel="stylesheet" href="https://unpkg.com/primitive-ui/dist/css/main.css" />
پیشنهاد فرانش به شما
چگونه یادگیری جاوا اسکریپت را شروع کنیم؟

 

ساخت یک کامپوننت در Vue

فایلی با نام EmployeeTable.vue را در src/components بسازید. می‌خواهیم اینجا یک جدول (table) با کمی اطلاعات استاتیک در آن ایجاد کنیم.

<template>
  <div id="employee-table">
    <table>
      <thead>
        <tr>
          <th>Employee name</th>
          <th>Employee email</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>Richard Hendricks</td>
          <td>richard@piedpiper.com</td>
        </tr>
        <tr>
          <td>Bertram Gilfoyle</td>
          <td>gilfoyle@piedpiper.com</td>
        </tr>
        <tr>
          <td>Dinesh Chugtai</td>
          <td>dinesh@piedpiper.com</td>
        </tr>
      </tbody>
    </table>
  </div>
</template>

<script>
  export default {
    name: 'employee-table',
  }
</script>

<style scoped></style>

قوانین نام‌گذاری در Vue به این صورت است که نام فایل و import به صورت PascalCase است، مثل EmployeeTable.
اما وقتی از آن در یک تمپلت استفاده می‌شود، به صورت
kebab-case تغییر می‌یابد، مثل <employee-table>.
اینطور از قوانین نام‌گذاری جاوا اسکریپت و
HTML به‌ترتیب استفاده می‌شود.

در کد بالا template در یک div قرار گرفته است. انجام این کار الزامی نیست. اما یک template تنها می‌تواند یک المنت فرزند (root child element) داشته باشد و با این کار اگر بخواهیم المنت‌های بیشتری را در ادامه به آن اضافه کنیم، به مشکل بر نمی‌خوریم.

فایل EmployeeTable را برمی‌داریم و آن را در App.vue ایمپورت (import) می‌کنیم.
در
import، می‌توانیم با استفاده از @ به پوشه‌ی src ارجاع دهیم. App.vue با استفاده از property components” می‌فهمد که می‌تواند از چه کامپوننت‌هایی استفاده کند.
تمامی کامپوننت‌های
import شده باید در اینجا اضافه شوند. هم‌چنین در کد زیر کمی استایل سراسری نیز اضافه شده است.

<template>
  <div id="app" class="small-container">
    <h1>Employees</h1>

    <employee-table />
  </div>
</template>

<script>
  import EmployeeTable from '@/components/EmployeeTable.vue'

  export default {
    name: 'app',
    components: {
      EmployeeTable,
    },
  }
</script>

<style>
  button {
    background: #009435;
    border: 1px solid #009435;
  }

  .small-container {
    max-width: 680px;
  }
</style>

نتیجه‌ را در زیر می‌بینید:

vue

می‌خواهیم کد بالا را به‌گونه‌ای تغییر دهیم که به‌جای اضافه کردن تمامی مقادیر به صورت کد، بتوانیم از داده‌ها به شکل آرایه‌ها و اشیاء استفاده کنیم.
پس بیایید یک متد
data() اضافه کنیم و آرایه‌ای از employees را به عنوان خروجی برگردانیم.
هم‌چنین به هریک از
employeesها یک ID می‌دهیم تا منحصربه‌فرد و قابل شناسایی باشند.

import EmployeeTable from '@/components/EmployeeTable.vue'

export default {
  name: 'app',
  components: {
    EmployeeTable,
  },
  data() {
    return {
      employees: [
        {
          id: 1,
          name: 'Richard Hendricks',
          email: 'richard@piedpiper.com',
        },
        {
          id: 2,
          name: 'Bertram Gilfoyle',
          email: 'gilfoyle@piedpiper.com',
        },
        {
          id: 3,
          name: 'Dinesh Chugtai',
          email: 'dinesh@piedpiper.com',
        },
      ],
    }
  },
}
پیشنهاد فرانش به شما
تفاوت Angular و React

Data مثل state در ری‌اکت است.

حالا این داده‌ها را در App.vue داریم، اما می‌خواهیم آن را به EmployeeTable بدهیم.
می‌توانیم این کار را با فرستادن داده به صورت یک
property انجام دهیم. شناسه‌ای (attribute) که با یک : شروع شود، به شما اجازه می‌دهد داده بفرستید.
نسخه‌ی طولانی‌تر آن
v-bind است. در اینجا آرایه‌ی employees را می‌فرستیم.

<employee-table :employees="employees" />

<!-- this is the same thing -->
<employee-table v-bind:employees="employees" />

 

حالا در سمت EmployeeTable، می‌خواهیم این داده‌ها را بگیریم. بنابراین به کامپوننت می‌گوییم که propertyها را دریافت کند که در اینجا یک Array است.

export default {
  name: 'employee-table',
  props: {
    employees: Array,
  },
}

 

می‌توانید به جای یک مقدار و نوع به ازای هر property، از آرایه‌ای از رشته‌ها نیز استفاده کنید، مثل [‘props: [ ’employees. این هم خوب است، اما وضوح داده‌ای کمتری دارد.

 

حلقه‌ها (loop)

حالا که داده‌ها را در اختیار داریم، می‌خواهیم در حلقه‌ای به سراغ هر نود DOM برویم و آن را نمایش دهیم. این کار را می‌توانیم با شناسه‌ی v-for انجام دهیم.
حالا که می‌توانیم
employees را در EmployeeTable برداریم، هر employee را در یک ردیف از جدول نشان می‌دهیم.

<template>
  <div id="employee-table">
    <table>
      <!-- ...thead... -->
      <tbody>
        <tr v-for="employee in employees" :key="employee.id">
          <td>{{ employee.name }}</td>
          <td>{{ employee.email }}</td>
        </tr>
      </tbody>
    </table>
  </div>
</template>

 

در Vue (مثل ری‌اکت) لازم است به هر المنت در یک آرایه یک شناسه‌ی منحصربه‌فرد بدهیم.
بنابراین از
:key در هر ردیف جدول استفاده می‌کنیم و به آن مقداری منحصربه‌فرد می‌دهیم.

حالا ظاهر جدول ما تغییری نکرده است، اما به‌گونه‌ای تغییرش دادیم که بهتر می‌تواند با داده‌ها کار کند.

 

کار کردن با فرم‌ها

حالا با موفقیت قسمت Read عملیات‌های CRUD را در برنامه داریم، اما مهم‌ترین کاری که باید درادامه انجام دهیم، اضافه کردن قابلیت افزودن employee است.
می‌خواهیم یک فرم “افزودن
employee” بسازیم.

فایل EmployeeForm.vue را بسازید و در آن فیلدهایی برای وارد کردن نام (name) و ایمیل (email) و دکمه‌ای برای تأیید (submit) قرار دهید.
در ادامه یک
property به نام employee می‌سازیم که دارای name و email است.

<template>
  <div id="employee-form">
    <form>
      <label>Employee name</label>
      <input type="text" />
      <label>Employee Email</label>
      <input type="text" />
      <button>Add Employee</button>
    </form>
  </div>
</template>

<script>
  export default {
    name: 'employee-form',
    data() {
      return {
        employee: {
          name: '',
          email: '',
        },
      }
    },
  }
</script>

<style scoped>
  form {
    margin-bottom: 2rem;
  }
</style>

 

حالا باید روشی پیدا کنیم که با آن داده‌ای که تایپ می‌شود را به state کامپوننت Vue بیاوریم. برای این کار از v-model استفاده می‌کنیم.
v-model یک syntactic sugar توکار به همراه یک onchange event است که برای به‌روزرسانی یک فیلد input از آن استفاده می‌شود.

<template>
  <div id="employee-form">
    <form>
      <label>Employee name</label>
      <input v-model="employee.name" type="text" />
      <label>Employee Email</label>
      <input v-model="employee.email" type="text" />
      <button>Add Employee</button>
    </form>
  </div>
</template>

با اضافه کردن کد بالا، در DevTools می‌بینید کهstate  کامپوننت تغییر می‌کند.
فقط باید این مقادیر را
submit و state  والد (app) را با شئ employee جدید به‌روزرسانی کنیم.

Event Listenerها

می‌خواهیم یک onsubmit event روی فرم داشته باشیم.
می‌توانیم این کار را با
v-on:submit یا به صورت خلاصه @submit انجام دهیم.
این خلاصه‌ کردن نام برای هر
event مشابه دیگری مثل @click/ v-on:click برقرار است.
submit event دارای یک prevent مفید است که می‌توانیم به آن اضافه کنیم، که درست شبیه اضافه کردن event.preventDefault() داخل تابع submit  است.
از این روش استفاده می‌کنیم، چون از متدهای پیش‌فرض
GET/POST که فرم‌ها ارائه می‌دهند، استفاده نخواهیم کرد.

بیایید این فرم را اضافه کنیم و به متد handleSubmit که بعداً می‌سازیم، ارجاع دهیم.

<form @submit.prevent="handleSubmit"></form>

 

متدها (Method)

حالا می‌خواهیم اولین متد خود را برای یک کامپوننت بنویسیم.
زیر
data()، می‌توانیم یک شئ methods ایجاد کنیم که شامل همه‌ی متدهایی است که می‌سازیم.
بیایید متد
handleSubmit را به آن اضافه کنیم.

export default {
  name: 'employee-form',
  data() {
    return {
      employee: {
        name: '',
        email: '',
      },
    }
  },
  methods: {
    handleSubmit() {
      console.log('testing handleSubmit')
    },
  },
}
پیشنهاد فرانش به شما
آموزش زبان برنامه نویسی Ruby روبی پروژه محور

فرستادن eventها به والد

حالا اگر submit را بزنید، می‌بینید که پیغام در کنسول لاگ می‌شود. حالا می‌دانیم که متد submit فرم، به‌خوبی کار می‌کند و می‌توانیم داده‌ها را به App بفرستیم. با استفاده از $emit این کار را انجام می‌دهیم.

 Emit به صورت زیر، نام یک event و داده‌اش را به کامپوننت والد آن می‌فرستد.

this.$emit('name-of-emitted-event', dataToPass)

 

در برنامه‌ی ما، یک event به نام add:employee می‌سازیم و this.employee را می‌فرستیم.

handleSubmit() {
  this.$emit('add:employee', this.employee)
}

در اسناد Vue، به استفاده از سینتکس add:employee (برخلاف add-employee یا چیز دیگر) توصیه شده است.

وقتی کد بالا را اضافه کردید، روی add form بزنید و به سراغ Vue DevTools بروید. یک پیغام برای event جدید می‌بینید که به شما نام، منبع و playload آن را می‌گوید، که در اینجا همان شئ‌ای است که ساخته‌ایم.

گرفتن eventها از فرزند

حالا employee-form دارد emitted event خود را می‌فرستد، اما ما باید آن را بگیریم و در والد از آن استفاده کنیم.

اولین کاری که باید انجام دهیم این است که کاری کنیم employee-form، emitted event را بشناسد و آن را مدیریت کند و متدی جدید را فراخوانی کند. کد زیر همین کار است:

<component @name-of-emitted-event="methodToCallOnceEmitted"></component>

 

بیایید کد بالا را به App.vue اضافه کنیم:

<employee-form @add:employee="addEmployee" />

 

حالا فقط باید متد addEmployee را در App.vue بسازیم.
این متد با افزودن یک آیتم جدید به آرایه‌ی
employees، آن را تغییر می‌دهد. این کد حتماً به شکل زیر خواهد بود:

methods: {
  addEmployee(employee) {
    this.employees = [...this.employees, employee]
  }
}

 

چون باید یک id هم بسازیم، کد زیر را برای گرفتن ID کارمند (employee) جدید بر اساس تعداد آیتم‌های موجود در آرایه می‌نویسیم.
توجه کنید که در یک پایگاه‌داده‌ی واقعی، این
ID به صورت منحصر‌به‌فرد ساخته می‌شود یا به صورت خودکار یکی به آن افزوده می‌شود (auto incremented).

addEmployee(employee) {
  const lastId =
    this.employees.length > 0
      ? this.employees[this.employees.length - 1].id
      : ۰;
  const id = lastId + 1;
  const newEmployee = { ...employee, id };

  this.employees = [...this.employees, newEmployee];
}

 

با انجام این کار، حالا می‌توانید کامند جدید اضافه کنید.
دقت کنید که کارمندان جدید موقتی هستند و ذخیره نمی‌شوند. چون این تنها بخش
Front-end برنامه است و به یک پایگاه‌ داده وصل نیست.

 

اعتبارسنجی اولیه‌ی فرم

فرم حال حاضر کار می‌کند، اما می‌خواهیم کمی بهترش کنیم. می‌خواهیم:

  • اگر همه‌چیز به درستی پیش رفت، یک پیغام success نمایش داده شود.
  • اگر چیزی سر جای خودش نبود، یک پیغام error نمایش داده شود.
  • inputهایی که مقادیر نامعتبر دارند، highlight شوند.
  • بعد از submit شدن درست فرم، مقادیر فیلدهای input پاک شود.
  • بعد از submit موفق، اشاره‌گر تایپ (Focus) روی اولین فیلد input باشد.

Computed Propertyها

در Vue، می‌توانیم از computed propertyها استفاده کنیم. computed propertyها توابعی هستند که اگر تغییراتی اعمال شود، به صورت خودکار محاسبات را انجام می‌دهند.
در این صورت دیگر لازم نیست منطق پیچیده‌ای در تمپلت
Vue بنویسیم.
در کد پایین یک بررسی اولیه قرار می‌دهیم که از خالی نبودن هر دو فیلد مطمئن شویم.

computed: {
  invalidName() {
    return this.employee.name === ''
  },

  invalidEmail() {
    return this.employee.email === ''
  },
},

 

برای انجام تمامی موارد بالا، یک submitting state قرار می‌دهیم تا ببینیم که آیا فرم در حال حاضر submitted است یا خیر.
یک
error state برای مواقعی که مشکلی پیش آمد و یک success state برای وقتی که همه‌چیز درست پیش رفت.

data() {
  return {
    submitting: false,
    error: false,
    success: false,
    employee: {
      name: '',
      email: '',
    }
  }
}

 

تابع submit ابتدا بررسی می‌کند که success یا error تنظیم شده‌اند و سپس عمل submit را آغاز می‌کند.
computed propertyها را بررسی می‌کند و اگر یکی از آنها true بود، error تنظیم می‌شود.
در غیر این صورت می‌توانیم
submit کنیم و تمامی stateها به حالت اولیه برمی‌گردند.

methods: {
  handleSubmit() {
    this.submitting = true
    this.clearStatus()

    if (this.invalidName || this.invalidEmail) {
      this.error = true
      return
    }

    this.$emit('add:employee', this.employee)
    this.employee = {
      name: '',
      email: '',
    }
    this.error = false
    this.success = true
    this.submitting = false
  },

  clearStatus() {
    this.success = false
    this.error = false
  }
}

 

چون یک پیغام success  و یک پیغام error هم می‌خواهیم، CSS را برای آنها تنظیم می‌کنیم.

<style scoped>
  form {
    margin-bottom: 2rem;
  }

  [class*='-message'] {
    font-weight: 500;
  }

  .error-message {
    color: #d33c40;
  }

  .success-message {
    color: #32a95d;
  }
</style>

 

در نهایت، فرم را کامل می‌کنیم. اگر فرم در حال submit شدن باشد و یکی از computed propertyها نامعتبر باشد، می‌خواهیم که یک کلاس has-error روی input قرار دهیم.
استفاده از
:class= باعث می‌شود که کلاس به صورت کد جاوا اسکریپت درنظر گرفته شود نه یک رشته‌ی (string) ساده.
می‌توانیم کاری کنیم که
statusها در focus event و keypress event پاک شوند و پیغام‌های success و error را مطابق با آنها در پایین صفحه نمایش دهیم.

<form @submit.prevent="handleSubmit">
  <label>Employee name</label>
  <input
    ref="first"
    type="text"
    :class="{ 'has-error': submitting && invalidName }"
    v-model="employee.name"
    @focus="clearStatus"
    @keypress="clearStatus"
  />
  <label>Employee Email</label>
  <input
    type="text"
    :class="{ 'has-error': submitting && invalidEmail }"
    v-model="employee.email"
    @focus="clearStatus"
  />
  <p v-if="error && submitting" class="error-message">
    ❗Please fill out all required fields
  </p>
  <p v-if="success" class="success-message">
    ✅ Employee successfully added
  </p>
  <button>Add Employee</button>
</form>

 

دستورات شرطی‌ (Conditional)

در کد بالا دستور v-if را می‌بینید که یک دستور شرطی در Vue است. در این حالت، المنت <p> تنها زمانی که شرط true باشد، نمایش داده می‌شود.

propertyهای v-else-if و v-else هم هستند که مانند همتاهای vanilla JS خود عمل می‌کنند. 

با تمام شدن این قسمت، می‌توانیم المنت‌هایی را، که با شرطی خاص ازشان رندر گرفته شده است، ببینیم. در پایین خطای فیلد خالی را می‌بینید.

و تصویر زیر پیغام success را نشان می‌دهد.

پیشنهاد فرانش به شما
آموزش PHP رایگان از پایه: راهنمای گام به گام با PDF

 

اضافه کردن ارجاع (Reference)

می‌توانیم برنامه را کمی بهتر کنیم. بعد از submit کردن فرم، خوب است که اشاره‌گر تایپ به آیتم اول برگردد (Focus روی آیتم اول باشد)، تا بتوانیم بدون کلیک کردن‌های متوالی، به هر تعدادی که می‌خواهیم employee وارد کنیم. می‌توانیم برای انجام این کار از refs استفاده کنیم که به ما اجازه می‌دهد المنت‌ای خاص را هدف قرار دهیم.

تنها کافی است یک ref به فیلد input اول اضافه کنیم….

<input ref="first" ... />

 

و پس از submit کردن فرم، آن ref را در handleSubmit، focus کنید.

this.$emit('add:employee', this.employee)
this.$refs.first.focus()

 

حالا پس از submit کردن، focus به صورت خودکار به اولین فیلد در فرم برمی‌گردد.
@keypress eventای که به clearStatus اضافه کردیم، با شروع به تایپ، پیغام‌های success یا error را از صفحه حذف می‌کند.

فایل EmployeeForm تکمیل شد. اگر در هر جا به مشکل برخوردید، فایل کامل را از این مرجع بررسی کنید.

 

حذف آیتم‌ها

حالا که فرم تکمیل شده است، باید دو عمل دیگر یعنی ویرایش (editing) و حذف (Deleting) را به جدول اضافه کنیم.
با حذف شروع می‌کنیم، چون راحت‌تر است.

ابتدا یک سطر “Actions” به جدول اضافه می‌کنیم و دو button برای editing و Deleting اضافه می‌کنیم.

<template>
  <div id="employee-table">
    <table>
      <thead>
        <tr>
          <th>Employee name</th>
          <th>Employee email</th>
          <th>Actions</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="employee in employees" :key="employee.id">
          <td>{{ employee.name }}</td>
          <td>{{ employee.email }}</td>
          <td>
            <button>Edit</button>
            <button>Delete</button>
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</template>

<style scoped>
  button {
    margin: 0 0.5rem 0 0;
  }
</style>

 

مثل قبل یک event را emit می‌کنیم که deleteEmployee نام دارد. می‌توانیم id مربوط به employee را به عنوان payload بدهیم.

<button @click="$emit('delete:employee', employee.id)">Delete</button>

 

در فایل App.vue، باید به employee-table بگوییم که عملی را روی delete-employee انجام دهد.

<employee-table :employees="employees" @delete:employee="deleteEmployee" />

 

و سپس سطر حذف شده را filter می‌کنیم.

methods: {
  addEmployee(employee) {...},
  deleteEmployee(id) {
    this.employees = this.employees.filter(
      employee => employee.id !== id
    )
  }
}

 

می‌بینید که حالا می‌توانید آیتم‌ها را حذف کنید. بیایید یک پیغام برای مواقعی اضافه کنیم که هیچ employeeای وجود ندارد.

<div id="employee-table">
  <p v-if="employees.length < 1" class="empty-table">
    No employees
  </p>
  <table v-else>
    ...
  </table>
</div>

 

حالا با موفقیت می‌توانیم employeeها را اضافه و حذف کنیم.

ویرایش آیتم‌ها

ویرایش کمی پیچیده‌تر از حذف است. شروع آن از App.vue ساده است، پس از آن شروع می‌کنیم. فقط edit:employee eventای را، که خواهیم ساخت، اضافه می‌کنیم:

<employee-table
  :employees="employees"
  @delete:employee="deleteEmployee"
  @edit:employee="editEmployee"
/>

 

و متد editEmployee را بسازید، که پارامترهای id و updatedEmployee را می‌گیرد، در آرایه‌ی employees به دنبال نمونه‌ی مشابه می‌گردد (عمل map کردن) و employee مناسب را ویرایش می‌کند.

editEmployee(id, updatedEmployee) {
  this.employees = this.employees.map(employee =>
    employee.id === id ? updatedEmployee : employee
  )
}

 

تا اینجا به اندازه‌ی کافی ساده بود.

حالا برگردیم سراغ EmployeeTable.vue. در واقع یک “edit mode” می‌خواهیم که با زدن دکمه‌ای فعال شود.

<button @click="editMode(employee.id)">Edit</button>

 

یک editing state می‌سازیم که مقدار id سطری را می‌گیرد که با فعال شدن editMode، می‌خواهیم آن را ویرایش کنیم.
EmployeeTable متد محلی editEmployee خود را دارد که اگر فیلدها خالی نبودند، edit:employee را برای App، emit و editing state را ری‌ست می‌کند (reset).

data() {
  return {
    editing: null,
  }
},
methods: {
  editMode(id) {
    this.editing = id
  },

  editEmployee(employee) {
    if (employee.name === '' || employee.email === '') return
    this.$emit('edit:employee', employee.id, employee)
    this.editing = null
  }
}

 

در زیر وضعیت کنونی سطر جدول را می‌بینید. در اینجا فقط مقادیر را نشان می‌دهیم.

<tr v-for="employee in employees" :key="employee.id">
  <td>{{ employee.name }}</td>
  <td>{{ employee.email }}</td>
  <td>
    <button @click="editMode(employee.id)">Edit</button>
    <button @click="$emit('delete:employee', employee.id)">
      Delete
    </button>
  </td>
</tr>

 

برای فعال کردن قابلیت ویرایش، editing === employee.id را برای یک سطر خاص بررسی می‌کنیم و یک فیلد input به‌جای آن نمایش می‌دهیم.
هم‌چنین یک
button برای cancel در نظر می‌گیریم، که با قرار دادن مقدار null ویرایش را لغو کند.

<tr v-for="employee in employees" :key="employee.id">
  <td v-if="editing === employee.id">
    <input type="text" v-model="employee.name" />
  </td>
  <td v-else>{{employee.name}}</td>
  <td v-if="editing === employee.id">
    <input type="text" v-model="employee.email" />
  </td>
  <td v-else>{{employee.email}}</td>
  <td v-if="editing === employee.id">
    <button @click="editEmployee(employee)">Save</button>
    <button class="muted-button" @click="editing = null">Cancel</button>
  </td>
  <td v-else>
    <button @click="editMode(employee.id)">Edit</button>
    <button @click="$emit('delete:employee', employee.id)">Delete</button>
  </td>
</tr>

 

حالا می‌توانیم هر بار یک سطر را ویرایش کنیم.

ویرایش کار می‌کند، اما نمی‌توانید جلوی آپدیت شدن state را با این کد بگیرید. حتی اگر مقادیر به فراخوانی API (API call) فرستاده نشوند. cancelEdit را می‌سازیم.
سپس کاری می‌کنیم دکمه‌ی “(
cancel، @click=”cancelEdit(employee را فراخوانی کند و .id را از دکمه‌یedit  حذف می‌کنیم.
یک
cached employee می‌سازیم که می‌توانیم دوباره به آن دسترسی داشته باشیم.

editMode(employee) {
  this.cachedEmployee = Object.assign({}, employee)
  this.editing = employee.id
},
cancelEdit(employee) {
  Object.assign(employee, this.cachedEmployee)
  this.editing = null;
}

 

در این مرحل، برنامه تکمیل شده است، اما یک اپلیکیشن واقعی، احتمالاً API callهایی به یک پایگاه‌داده در قسمت بک‌اند برنامه انجام می‌دهد. پس ما هم یک نسخه‌ی غیرواقعی از آن را می‌سازیم.

پیشنهاد فرانش به شما
آموزش لاراول Laravel گام به گام پروژه محور ۲۰۱۹

 

اجرای فراخوانی‌های آسنکرون REST API (Asynchronous REST API)

می‌خواهیم از JSON Placeholder برای ایجاد API callهای غیرواقعی استفاده کنیم که پاسخ‌هایی واقعی به ما می‌دهند. می‌توانیم مقادیر را GET کنیم (برای مثال، به آدرس https://jsonplaceholder.typicode.com/users بروید و users JSONای را، که استفاده خواهیم کرد، ببینید.) و می‌توانیم درخواست‌هایی را POST، PUT و DELETE کنیم. این درخواست‌ها در یک پایگاه‌داده‌ی واقعی باقی نمی‌مانند، چون برای اهداف آموزشی هستند.

با استفاده از دستور try/catch، یک متد آسنکرون با async/await به صورت زیر است.

از Fetch API توکار استفاده خواهیم کرد که Node و مرورگر به آن دسترسی دارند. اگرچه گزینه‌های معروف . دردسترس دیگری مثل Axios نیز مناسبند.

async asynchronousMethod() {
  try {
    const response = await fetch('url')
    const data = await response.json()

    // do something with `data`
  } catch (error) {
    // do something with `error`
  }
}

 

در این مرحله، تمامی متدهای CRUD را با متدهای async عوض می‌کنیم و داده‌ها و فرانت‌اند را از طریق API به‌روزرسانی می‌کنیم.

متدهای Lifecycle

با GET، می‌خواهیم تمامی داده‌های آماده‌ی آرایه‌ی employees را حذف کنیم و به جای آن از داده‌های API استفاده کنیم. GET را در متد mounted فراخوانی می‌کنیم که یک متد Lifecycle است.

اگر با ری‌اکت آشنا باشید، درباره‌ی متدهای lifecycle می‌دانید. این متدها معادل componentDidMount در Vue هستند.

mounted به کامپوننت می‌گوید که وقتی وارد DOM شد، یک بار عمل کند. این روشی معمول برای نمایش API است. (برخی برای انجام این کار از created lifecycle  استفاده می‌کنند.)

export default {
  name: 'app',
  components: {
    EmployeeTable,
    EmployeeForm,
  },
  data() {
    return {
      employees: [],
    }
  },

  mounted() {
    this.getEmployees()
  },
}

 

خُب، حالا می‌توانیم به جای تمامی متدهای CRUD، از معادل API call آسنکرون آنها استفاده کنیم.

GET

برداشت اطلاعات از یک resource.

async getEmployees() {
  try {
    const response = await fetch('https://jsonplaceholder.typicode.com/users')
    const data = await response.json()
    this.employees = data
  } catch (error) {
    console.error(error)
  }
}

 

POST

ایجاد یک resource جدید.

async addEmployee(employee) {
  try {
    const response = await fetch('https://jsonplaceholder.typicode.com/users', {
      method: 'POST',
      body: JSON.stringify(employee),
      headers: { 'Content-type': 'application/json; charset=UTF-8' },
    })
    const data = await response.json()
    this.employees = [...this.employees, data]
  } catch (error) {
    console.error(error)
  }
}

 

PUT

به‌روزرسانی یک resource موجود.

async editEmployee(id, updatedEmployee) {
  try {
    const response = await fetch(`https://jsonplaceholder.typicode.com/users/${id}`, {
      method: 'PUT',
      body: JSON.stringify(updatedEmployee),
      headers: { 'Content-type': 'application/json; charset=UTF-8' },
    })
    const data = await response.json()
    this.employees = this.employees.map(employee => (employee.id === id ? data : employee))
  } catch (error) {
    console.error(error)
  }
}

 

DELETE

حذف یک resource موجود.

async deleteEmployee(id) {
  try {
    await fetch(`https://jsonplaceholder.typicode.com/users/${id}`, {
      method: "DELETE"
    });
    this.employees = this.employees.filter(employee => employee.id !== id);
  } catch (error) {
    console.error(error);
  }
}

 

خُب، تمامی API callها باید به‌درستی کار کنند و حالا به جای استفاده از داده‌های استاتیک خودمان، از JSON Placeholder داده می‌گیریم.

نوشتن برنامه به پایان رسید.

 

نتیجه‌گیری آموزش VUE JS

آموزشی طولانی بود. یاد گرفتیم Vue.js چیست، چگونه یک پروژه‌ی Vue را از طریق HTML استاتیک یا Vue CLI راه‌اندازی کنیم و شیوه‌ی ساخت یک برنامه‌ی CRUD را در Vue یاد گرفتیم.
درباره‌ی کامپوننت‌ها، متدها، داده‌ها، متدهای
computed، lifecycleها، دستورات شرطی، eventها، مدیریت فرم‌ها و بیلد کردن در Vue یاد گرفتیم.
اگر این آموزش vue.js را کامل کردید، حالا می‌توانید اولین برنامه‌ی خود را در
Vue از پایه بنویسید.

بعد از این می‌توانید برای مدیریت state به سراغ Vuex (مشابه Redux در ری‌اکت) و برای روتینگ فرانت‌اند (Front End Routing) به سراغ Vue Router (مشابه Router DOM در ری‌اکت) بروید.
جذاب‌ترین مسئله درباره‌ی محیط
Vue این است که کتابخانه‌هایش اختیاری هستند، اما اگر به آنها نیاز داشته باشید، کتابخانه‌های رسمی در آن موجود است.

 

دوره های مرتبط در فرانش