× خانه ویدیو دانلود اپلیکیشن درباره ما ورود / ثبت نام

  • خانه
  • ویدیو
  • دانلود
  • اپلیکیشن
  • درباره ما
  • ورود / ثبت نام
  • خانه
  • ویدیو
  • دانلود
  • اپلیکیشن
  • درباره ما
  • ورود / ثبت نام
خانه
|
پست های javascript
|
آموزش ساخت بازی XO با استفاده از React - بخش دوم

مطالب

  • CSS
  • Git
  • HTML
  • Javascript
  • PHP
  • Web

بیشترین بازدید

  • طراحی صفحه ثبت نام و ورود کاربران HTML و CSS

    طراحی صفحه ثبت نام و ورود کاربران HTML و CSS

    با توجه به اینکه در سایت تبلیغات، کاربران جهت ارائه آگهی های خود باید ثبت نام کنند در این قسمت برای ارسال اطلاعات به سمت سرور، با استفاده از تگ های موجود در HTML فرمی را جهت ثبت نام و ورود کاربران ایجاد خواهیم کرد. در ادامه مطلب همراه من باشید. چیست و چه کاربردی دارد؟
  • ساخت وب سرویس با استفاده از PHP و SOAP

    ساخت وب سرویس با استفاده از PHP و SOAP

    به عنوان توسعه دهنده نرم افزار، توانایی توسعه نرم افزار و سرویس برای محدوده گسترده ای از پلتفرم ها یک مهارت ضروری است. اما برای تحقق این موضوع  نمی توان انتظار داشت که همه از یک پلتفرم یا یک زبان برنامه نویسی استفاده کنند یا اینکه همه پلتفرم ها و زبان ها را پوشش داد، این یک کار نشدنی است. اگر تنها یک استاندارد وجود داشت که به ما اجازه می داد تا کدهای نرم افزارمان را یکبار بنویسیم و دیگران با نرم افزارهای خودشان به آسانی از طریق شبکه با آن ارتباط برقرار می کردند چقدر عالی می شد. خب خوشبختانه وجود دارد و نامش هم  SOAP است. در ادامه مطلب همراه من باشید. چیست و چه کاربردی دارد؟
  • طراحی صفحه ثبت نام و ورود کاربران PHP و MySQL

    طراحی صفحه ثبت نام و ورود کاربران PHP و MySQL

    برای ثبت اطلاعات کاربران در پایگاه داده سایت، باید با استفاده از PHP اطلاعات ارسال شده توسط کاربر را دریافت کنیم و با استفاده از دستورات MySQL ذخیره کنیم. جهت اجرای کدهای PHP و MySQL در ویندوز باید نرم افزار WAMP یا XAMP را در سیستم خود نصب کنید. با استفاده از این نرم افزار یک لوکال هاست مجازی در سیستم شما شبیه سازی می شود تا کدهای PHP را اجرا و پایگاه داده MySQL را ایجاد کنید. در ادامه مطلب همراه من باشید. چیست و چه کاربردی دارد؟
  • ساخت وب سرویس RESTful با استفاده از PHP

    ساخت وب سرویس RESTful با استفاده از PHP

    Representational State Transfer یک سبک معماری در وب سرویس است که در آن از آدرس ها برای دستیابی به منابع استفاده می شود. داده ها و توابع در معماری RESTful منابع نامیده می شوند به این جهت که داده ها و توابع در واقع آنچیزی هستند که ما می خواهیم از طریق سرویس به آن متصل شویم. در این پست می خواهیم نشان دهیم که چطور می توان یک وب سرویس RESTful را بدون استفاده از هیچ نوع Framework خاصی در PHP ایجاد کرد. در ادامه مطلب همراه من باشید. چیست و چه کاربردی دارد؟
  • آموزش نصب و استفاده از Composer

    آموزش نصب و استفاده از Composer

    Composer ابزاری برای مدیریت وابستگی در پروژه های PHP می باشد. زمانی که شما تصمیم می گیرید تا یک پروژه PHP را ایجاد کنید قطعا با مسائلی برخورد خواهید کرد که راه حل آنها استفاده از کتابخانه ها یا پکیج های موجودی است که برای این مساله ها ارائه شده اند زیرا با این کار در فاکتور های مهمی همچون زمان و هزینه صرفه جویی کرده اید و به عبارت دیگر چرخ را از نو اختراع نمی کنید. از این دست مسائل می توان به: اعتبار سنجی کاربر مدیریت پایگاه داده مسیریابی درخواست اشاره کرد. اما در این میان کتابخانه ها یا پکیج های موجود هم دارای وابستگی های خاص خود هستند و به عنوان توسعه دهنده PHP شما باید انرژی مضاعفی را برای یافتن و تطبیق این وابستگی ها صرف کنید. در ادامه مطلب همراه من باشید. چیست و چه کاربردی دارد؟
  • ساخت WSDL با استفاده از PHP

    ساخت WSDL با استفاده از PHP

    در قسمت قبل ایجاد یک اپلیکیشن سازگار را با استفاده از پروتکل SOAP بررسی کردیم. همینطور نشان دادیم که ساخت سرور و کلاینت SOAP با کتابخانه NuSOAP چقدر آسان است اما در این قسمت می خواهیم WSDL را که در هنگام کار با SOAP حتما استفاده خواهد شد را توضیح دهیم. در اینجا ما در ارتباط با فایل های WSDL و اینکه چطور می توان از آنها استفاده کرد بحث خواهیم کرد همچنین به شما نشان می دهیم که به چه صورت می توان فایل WSDL  را با NuSOAP ایجاد کنید و آن را با مثال های سرور و کلاینت SOAP که در قسمت قبل ایجاد کردیم ترکیب کنیم. در ادامه مطلب همراه من باشید. چیست و چه کاربردی دارد؟
تبلیغات

دانلودها

  • آموزش لاراول: معرفی و آموزش گام به گام Laravel
  • آموزش ساخت بازی XO با استفاده از React - بخش دوم
  • آموزش ساخت بازی XO با استفاده از React - بخش اول
  • آموزش React - قسمت سوم
  • آموزش React - قسمت دوم

سوالات

  • اضافه کردن یک ستون جدید به جدول موجود در Migration لاراول

    چطور می توانم یک ستون به جدولی که از قبل با استفاده از فریموورک لاراول ایجاد شده است اضافه کنم؟من فایل Migration رو به صورت زیر ویرایش کردم:<?php public function up() { Schema::create('users', function ($table) { $table->integer("paid"); }); }در ترمینال هم دستور php artisan migrate:install  و migrate رو اجرا کردم، اما ستون اضافه نشده است.چطور می توانم ستون مورد نظرم را اضافه کنم؟
  • چک کردن موجود بودن یک رکورد در Laravel

    من تازه کار با فریممورک Laravel رو شروع کردم. چطور می توانم بررسی کنم که یک رکورد موجود است یا خیر؟$user = User::where('email', '=', Input::get('email'));چطور می می تونم بررسی کنم که user$ شامل رکورد هست یا نه؟
  • لاراول 4: چطور می توان در Blade آدرس صفحه را دریافت کرد؟

    من از لاراول نسخه 4 استفاده می کنم، چطور می توانم آدرس یک صفحه را دریافت کنم و در if@ استفاده کنم. می دونم که  می توانم با استفاده از کد PHP زیر این کار را انجام دهم:<?php echo URL::current(); ?>اما در blade چطور می توان این کار را انجام داد؟
  • چطور می توان چندین شرط Where در Eloquent لاراول در نظر گرفت؟

    من از Query Builder لاراول برای ایجاد گزارش استفاده می کنم و گزارشم دارای چندین شرط می باشد.شرط ها را به صورت زیر اعمال کردم اما به نظرم راه جالبی نیست.$results = User::where('this', '=', 1) ->where('that', '=', 1) ->where('this_too', '=', 1) ->where('that_too', '=', 1) ->where('this_as_well', '=', 1) ->where('that_as_well', '=', 1) ->where('this_one_too', '=', 1) ->where('that_one_too', '=', 1) ->where('this_one_as_well', '=', 1) ->where('that_one_as_well', '=', 1) ->get();آیا راه بهتری برای اعمال شرط ها وجود دارد؟
  • چطور می توان گزارش SQL که Query Builder لاراول آن را ایجاد می کند مشاهده کرد؟

    کد زیر را در نظر بگیرید:DB::table('users')->get();من می خوام کد SQL که Query Builder بالا اجرا می کند را دریافت کنم به عنوان مثال در کد بالا کد SQL:SELECT * FROM usersتوسط Query builder اجرا می شود.
  • Eloquent: شمارش و تشخیص خالی بودن

    آیا راهی برای تشخیص اینکه مجموعه بازگشتی از گزارش:$result = Model::where(...)->get() خالی است یا اینکه تعداد عناصر موجود در آن چقدر است وجود دارد؟من در حال حاضر از:!$result استفاده می کنم آیا راه درستی است؟در مورد:count($result)آیا همه موارد را پوشش می دهد؟ به عنوان مثال اگر result خالی باشد؟
  • لاراول 5: نمایش HTML در Blade

    من یک رشته به صورت زیر دارم که شامل تگ HTML می باشد:$text = '<p><strong>Lorem</strong> ipsum dolor <img src="images/test.jpg"></p>'و می خواهم با استفاده از Blade نمایش بدم:{{$text}}اما خود رشته را چاپ می کند و تگ های HTML را رندر نمی کند. چطور می توانم HTML را با Blade در لاراول 5 نمایش بدم؟
  • ReactJSX: استفاده از Props بین کوتیشن

    چطور می توان در JSX از یک مقدار props به عنوان مقدار attribute استفاده کرد؟به عنوان مثال:<img className="image" src="images/{this.props.image}" />و خروجی HTML آن به صورت زیر است:<img class="image" src="images/{this.props.image}"> 
  • ارتباط بین دو کامپوننت در React

    اپلیکیشن من شامل یک لیست با فیلتر های آن و یک button برای تغییر layout می باشد. در حال حاضر از سه کامپوننت:</list></Filters></TopBar>استفاده می کنم. می خوام زمانی که تنظیمات در </Filters> تغییر کرد متدی در کامپوننت </list> برای بروزرسانی view اجرا شود.چطور میتونم بین این سه کامپوننت ارتباط برقرار کنم؟ آیا باید از مدل داده global برای انجام این کار استفاده کنم؟ 
  • Show یا Hide کردن عنصر در React

    من تازه شروع به یادگیری React کردم و دنبال راهی هستم که بتونم یک عنصر روی صفحه را show یا hide کنم.  می خوام زمانی که کلیک کردم، div مربوط به نتایج نمایش داده شود.var Search= React.createClass({ handleClick: function (event) { console.log(this.prop); }, render: function () { return ( <div className="date-range"> <input type="submit" value="Search" onClick={this.handleClick} /> </div> ); } }); var Results = React.createClass({ render: function () { return ( <div id="results" className="search-results"> Some Results </div> ); } }); React.renderComponent(<Search /> , document.body); 

اشتراک

آموزش ساخت بازی XO با استفاده از React - بخش دوم

آموزش ساخت بازی XO با استفاده از React - بخش دوم

۱۵ فروردین ۱۳۹۸
دانیال افشار
1129

در بخش اول آموزش ساخت بازی XO با استفاده از React، کامپوننت های Board و Square را ایجاد کردیم و دیدیم که چطور با استفاده از کامپوننت ها می توانیم UI مورد نظر خود را به قسمت های مختلف و مجزا از هم تقسیم کنیم و آن ها را توسعه دهیم. مباحث State و Props را شروع و بررسی کردیم که داده ها بین کامپوننت ها به چه صورتی در جریان هستند و کاربرد هر یک از آنها را مشاهده کردید.

حالا باید ویژیگی های بیشتری را به بازی اضافه و آن را تکمیل کنیم.

در ادامه مطلب همراه من باشید.

اعلام برنده

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

function calculateWinner(squares) {
  const lines = [
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8],
    [0, 3, 6],
    [1, 4, 7],
    [2, 5, 8],
    [0, 4, 8],
    [2, 4, 6],
  ];
  for (let i = 0; i < lines.length; i++) {
    const [a, b, c] = lines[i];
    if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
      return squares[a];
    }
  }
  return null;
}

ما تابع calculateWinner(squares) را برای بررسی اینکه کدام بازیکن برنده است در متد render کامپوننت Board فراخوانی می کنیم. اگر بازیکنی برنده باشد متن “Winner: X” یا “Winner: O” به نمایش در می آید. در متد render کامپوننت Board تغییرات زیر را اعمال می کنیم.

  render() {
    const winner = calculateWinner(this.state.squares);
    let status;
    if (winner) {
      status = 'Winner: ' + winner;
    } else {
      status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
    }

    return (
      // the rest has not changed

همچنین متد handleClick در کامپوننت Board را به صورت زیر تغییر می دهیم. اگر برنده بازی مشخص شده باشد یا خانه ای که بازیکن روی آن کلیک کرده است پر شده باشد با استفاده از به کارگیری return ادامه کار تابع متوقف می شود.

  handleClick(i) {
    const squares = this.state.squares.slice();
    if (calculateWinner(squares) || squares[i]) {
      return;
    }
    squares[i] = this.state.xIsNext ? 'X' : 'O';
    this.setState({
      squares: squares,
      xIsNext: !this.state.xIsNext,
    });
  }

ذخیره تاریخچه حرکات بازی

به عنوان آخرین ویژیگی قصد داریم تا بازگشت به حرکات قبل را در بازی پیاده سازی کنیم.

اگر ما با آرایه squares به صورت تغییر پذیر کار می کردیم و تغییرات خود را به صورت مستقیم در آن اعمال می کردیم، پیاده سازی Time travel پیچیده تر بود. تا اینجا ما با استفاده از تابع slice پس از هر حرکت در بازی، یک کپی از آرایه squares ایجاد کردیم و به صورت تغییر ناپذیر با آن کار کردیم که به ما این امکان را می دهد تا نسخه های قبلی آرایه squares را ذخیره و از آنها برای بازگشت به حرکت قبل استفاده کنیم.

در اینجا باید آرایه squares را در آرایه ای دیگر به نام history قرار دهیم. آرایه history همه state های کامپوننت Board را از ابتدا تا انتها در خود نگهداری می کند و شکل آرایه هم به صورت زیر خواهد بود:

history = [
  // Before first move
  {
    squares: [
      null, null, null,
      null, null, null,
      null, null, null,
    ]
  },
  // After first move
  {
    squares: [
      null, null, null,
      null, 'X', null,
      null, null, null,
    ]
  },
  // After second move
  {
    squares: [
      null, null, null,
      null, 'X', null,
      null, null, 'O',
    ]
  },
  // ...
]

  حالا زمان تصمیم گیری در مورد محل نگهداری آرایه history است و اینکه این آرایه باید در کدام کامپوننت قرار بگیرد.

انتقال State به سطح بالاتر

کامپوننت Game را برای نمایش لیست حرکات قبلی ایجاد می کنیم و برای انجام این کار نیاز به آرایه history خواهیم داشت بنابراین ما آرایه history را در بالاترین سطح یعنی کامپوننت Game قرار می دهیم.

با قرار گیری آرایه history در کامپوننت Game می توانیم آرایه squares را از کامپوننت فرزندش یعنی Board حذف کنیم. همانند ارسال State از کامپوننت Square به کامپوننت Board، حالا State را از Board به سطح بالاتر یعنی کامپوننت Game منتقل می کنیم و State را از Board حذف می کنیم. این کار باعث می شود تا کامپوننت Game کنترل کاملی بر داده های کامپوننت Board داشته باشد و این امکان را به کامپوننت Game می دهد تا از طریق کامپوننت Board، حرکات قبلی را از history خوانده و آن را render مجدد کند.

ابتدا در متد constructor کامپوننت Game، state اولیه را تنظیم می کنیم:

class Game extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      history: [{
        squares: Array(9).fill(null),
      }],
      xIsNext: true,
    };
  }

  render() {
    return (
      <div className="game">
        <div className="game-board">
          <Board />
        </div>
        <div className="game-info">
          <div>{/* status */}</div>
          <ol>{/* TODO */}</ol>
        </div>
      </div>
    );
  }
}

در حال حاضر کامپوننت Board، prop های squares و onClick را از کامپوننت Game دریافت می کند. به دلیل اینکه ما یک click handler برای Square ها داریم، باید موقعیت هر Square را به onClick ارسال کنیم تا مشخص کنیم که کدامیک از Square ها کلیک شده است. در اینجا مراحل لازم برای تغییر کامپوننت Board را بررسی می کنیم:

  • حذف متد constructor از کامپوننت Board

  • جایگزین کردن this.state.squares[i] به جای this.props.squares[i] در متد renderSquare کامپوننت Board

  • جایگزین کردن this.props.onClick(i) به جای this.handleClick(i) در متد renderSquare کامپوننت Board

پس از اعمال تغییرات، کامپوننت Borad به صورت زیر خواهد بود:

class Board extends React.Component {
  handleClick(i) {
    const squares = this.state.squares.slice();
    if (calculateWinner(squares) || squares[i]) {
      return;
    }
    squares[i] = this.state.xIsNext ? 'X' : 'O';
    this.setState({
      squares: squares,
      xIsNext: !this.state.xIsNext,
    });
  }

  renderSquare(i) {
    return (
      <Square
        value={this.props.squares[i]}
        onClick={() => this.props.onClick(i)}
      />
    );
  }

  render() {
    const winner = calculateWinner(this.state.squares);
    let status;
    if (winner) {
      status = 'Winner: ' + winner;
    } else {
      status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
    }

    return (
      <div>
        <div className="status">{status}</div>
        <div className="board-row">
          {this.renderSquare(0)}
          {this.renderSquare(1)}
          {this.renderSquare(2)}
        </div>
        <div className="board-row">
          {this.renderSquare(3)}
          {this.renderSquare(4)}
          {this.renderSquare(5)}
        </div>
        <div className="board-row">
          {this.renderSquare(6)}
          {this.renderSquare(7)}
          {this.renderSquare(8)}
        </div>
      </div>
    );
  }
}

برای استفاده از تاریخچه جهت تشخیص و نمایش وضعیت بازی، متد render کامپوننت Game را به صورت زیر تغییر می دهیم:

 render() {
    const history = this.state.history;
    const current = history[history.length - 1];
    const winner = calculateWinner(current.squares);

    let status;
    if (winner) {
      status = 'Winner: ' + winner;
    } else {
      status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
    }

    return (
      <div className="game">
        <div className="game-board">
          <Board
            squares={current.squares}
            onClick={(i) => this.handleClick(i)}
          />
        </div>
        <div className="game-info">
          <div>{status}</div>
          <ol>{/* TODO */}</ol>
        </div>
      </div>
    );
  }

پس از انتقال نمایش وضعیت بازی به متد render در کامپوننت ،Game می توانیم کد نمایش وضعیت بازی را از متد render کامپوننت Board حذف کنیم. پس از این کار متد render کامپوننت Board به صورت زیر خواهد بود:

 render() {
    return (
      <div>
        <div className="board-row">
          {this.renderSquare(0)}
          {this.renderSquare(1)}
          {this.renderSquare(2)}
        </div>
        <div className="board-row">
          {this.renderSquare(3)}
          {this.renderSquare(4)}
          {this.renderSquare(5)}
        </div>
        <div className="board-row">
          {this.renderSquare(6)}
          {this.renderSquare(7)}
          {this.renderSquare(8)}
        </div>
      </div>
    );
  }

در آخر ما متد handleClick را از کامپوننت Board به کامپوننت Game منتقل می کنیم. همچنین باید تغییراتی را در متد handleClick اعمال کنیم زیرا ساختار state در کامپوننت Game تغییر کرده است. در متد handleClick کامپوننت Game تاریخچه جدید را با استفاده از تابع concat به آرایه history الصاق می کنیم.

handleClick(i) {
    const history = this.state.history;
    const current = history[history.length - 1];
    const squares = current.squares.slice();
    if (calculateWinner(squares) || squares[i]) {
      return;
    }
    squares[i] = this.state.xIsNext ? 'X' : 'O';
    this.setState({
      history: history.concat([{
        squares: squares,
      }]),
      xIsNext: !this.state.xIsNext,
    });
  }

نکته:

به جای استفاده از تابع  push() از تابع  concat() استفاده می کنیم تا آرایه مورد نظر تغییر ناپذیر باقی بماند و به صورت مستقیم داده های آرایه تغییر نکند.

تا اینجا متد های renderSquare و render در کامپوننت Board و state بازی و متد handleClick در کامپوننت Game قرار دارد.

نمایش حرکات قبلی

با توجه به اینکه تاریخچه بازی را ثبت کردیم، می توانیم لیست حرکات انجام شده بازیکن ها را نمایش دهیم.

پیش تر بررسی کردیم که می توان با عناصر React به صورت یک شی جاوااسکریپت برخورد کرد و از آن در سرتاسر اپلیکیشن استفاده کرد. برای render کردن چندین آیتم در React می توانیم از یک آرایه که شامل عناصر React می باشد استفاده کنیم.

آرایه ها در جاوااسکریپت دارای یک متد به نام map هستند که معمولا برای تبدیل کردن یک فرم داده به فرم دیگر استفاده می شود. به طور مثال:

const numbers = [1, 2, 3];
const doubled = numbers.map(x => x * 2); // [2, 4, 6]

در اینجا می توانیم  با استفاده از متد map، تاریخچه تغییرات را به button هایی که وظیفه  آنها برگشت حالت بازی به مراحل قبل تر است تبدیل کنیم.  

حالا آرایه history را در متد render کامپوننت Game، map می کنیم:

 render() {
    const history = this.state.history;
    const current = history[history.length - 1];
    const winner = calculateWinner(current.squares);

    const moves = history.map((step, move) => {
      const desc = move ?
        'Go to move #' + move :
        'Go to game start';
      return (
        <li>
          <button onClick={() => this.jumpTo(move)}>{desc}</button>
        </li>
      );
    });

    let status;
    if (winner) {
      status = 'Winner: ' + winner;
    } else {
      status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
    }

    return (
      <div className="game">
        <div className="game-board">
          <Board
            squares={current.squares}
            onClick={(i) => this.handleClick(i)}
          />
        </div>
        <div className="game-info">
          <div>{status}</div>
          <ol>{moves}</ol>
        </div>
      </div>
    );
  }

برای هر حرکت در تاریخچه بازی ما یک <li> که شامل یک <button> است ایجاد کردیم. هر button دارای یک onClick handler است که متد this.jumpsTo() را فراخوانی می کند که ما هنوز این متد را پیاده سازی نکردیم. در حال حاضر ما باید یک لیست از حرکت های انجام شده در بازی را مشاهده کنیم. البته یک اخطار با این مضمون که هر عنصر موجود در آرایه باید دارای کلید باشد در قسمت developer tools ایجاد می شود و در ادامه در مورد این اخطار بیشتر بحث می کنیم.

انتخاب کلید

زمانی که یک لیست را render می کنیم، React اطلاعاتی را در ارتباط با آیتم های لیست render شده ذخیره می کند. زمانی که یک لیست را به روز رسانی می کنیم، React نیاز دارد تا تشخیص دهد چه تغییری رخ داده است. در نظر بگیرید که کاربر می تواند آیتم های لیست را اضافه، حذف، به روزرسانی یا ترتیب آن را تغییر دهد.

به طور مثال تغییر زیر را در نظر بگیرید:

<li>Alexa: 7 tasks left</li>
<li>Ben: 5 tasks left</li>

به

<li>Ben: 9 tasks left</li>
<li>Claudia: 8 tasks left</li>
<li>Alexa: 5 tasks left</li>

علاوه بر به روزرسانی شمارنده، شاید کاربر بخواهد ترتیب Alexa و Ben را جا به جا کند و Claudia را بین این دو قرار دهد. با این حال React یک برنامه کامپیوتری است و چیزی در ارتباط با هدف ما نمی داند. ما باید یک کلید برای هر آیتم لیست تعریف کنیم تا از یک دیگر متمایز باشند. یک گزینه می تواند استفاده از رشته های Alexa، Ben و Claudia باشد. اگر داده ها را از database بخوانیم id های Alexa، Ben و Claudia می تواند به عنوان کلید در نظر گرفته شوند.

<li key={user.id}>{user.name}: {user.taskCount} tasks left</li>

زمانی که یک لیست render مجدد می شود، React کلید هر آیتم لیست را دریافت می کند و آیتم های لیست قبلی را برای تطابق کلید جست و جو می کند. اگر لیست جاری دارای کلیدی باشد که قبلا وجود نداشته، React یک آیتم جدید ایجاد می کند. اگر لیست جاری فاقد کلیدی باشد که در لیست قبلی موجود بوده، React، آیتم قبلی را حذف می کند. اگر دو کلید با هم تطابق داشته باشند، آیتم مربوطه منتقل می شود. کلید ها باعث می شوند تا هر آیتم هویت مشخص داشته باشد و این به React امکان می دهد تا حالت را بین render های مجدد حفظ  کند.اکر کلید آیتم تغییر کند، آیتم حذف می شود و با یک state جدید ایجاد می شود.

 Key یک ویژیگی رزرو شده در React  است (مانند ref که یک ویژیگی پیشرفته تر است). React زمانی که یک عنصر ایجاد می شود، ویژگی key را دریافت می کند و به طور مستقیم به عنصر اختصاص می دهد. هر چند که به نظر می رسد key از props قابل دسترسی است اما key نمی تواند به صورت this.props.key فراخوانی شود. React به صورت خودکار از key برای تصمیم گیری در مورد اینکه کدام کامپوننت ها باید به روز رسانی شود استفاده می کند. یک کامپوننت از کلید اختصاص داده شده به خودش اطلاعی ندارد.

پیشنهاد می کنیم در زمان ساخت لیست های پویا از کلید های مناسب استفاده کنید.

اگر هیچ کلیدی مشخص نشود، React اخطار می دهد و به طور پیش فرض از index آرایه به عنوان کلید استفاده می کند. استفاده از index آرایه زمانی که می خواهیم آرایه را مجدد مرتب کنیم یا آیتمی را اضافه یا حذف کنیم باعث ایجاد مشکل می شود. اگر هم کلید را به صورت key={i} مشخص کنیم با اینکه اخطاری ایجاد نمی شود اما باعث ایجاد مشکل های مشابه با تعیین index آرایه به عنوان کلید می شود و در اغلب موارد توصیه نمی شود.

کلید ها نیازی به اینکه به صورت کلی منحصر به فرد باشند ندارند، آنها فقط باید در سطحی که هستند (به عنوان مثال در یک آرایه) منحصر به فرد باشند.

پیاده سازی تاریخچه بازی

در تاریخچه بازی XO هر حرکتی که انجام شده است دارای یک ID منحصر به فرد و مرتبط با خودش است که در واقع عدد متوالی حرکت ها می باشد. حرکات هیچ وقت حذف یا در میانه لیست اضافه یا مجدد مرتب نمی شوند بنابراین استفاده از index حرکت به عنوان کلید قابل اطمینان می باشد.

در متد render کامپوننت Game می توانیم کلید را به صورت <li key={move}> اضافه کنیم و اخطار ایجاد شده توسط React را برطرف کنیم.

    const moves = history.map((step, move) => {
      const desc = move ?
        'Go to move #' + move :
        'Go to game start';
      return (
        <li key={move}>
          <button onClick={() => this.jumpTo(move)}>{desc}</button>
        </li>
      );
    });

با کلیک روی آیتم های button لیست یک خطا مبنی بر اینکه متد jumpTo تعریف نشده است نمایش داده می شود. اما قبل از پیاده سازی jumpTo ما stepNumber را به state کامپوننت Game اضافه می کنیم تا مشخص کنیم در حال حاضر در کدام گام قرار داریم.

ابتدا stepNumber : 0 را به state اولیه در constructor کامپوننت Game اضافه می کنیم:

class Game extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      history: [{
        squares: Array(9).fill(null),
      }],
      stepNumber: 0,
      xIsNext: true,
    };
  }

سپس متد jumpTo را برای بروزرسانی stepNumber در کامپوننت Game تعریف می کنیم. ما همچنین مقدار xIsNext را با توجه به مقدار stepNumber تغییر می دهیم به این صورت که اگر مقدار stepNumber زوج بود xIsNext برابر با true و در غیر اینصورت برابر با false خواهد بود.

 handleClick(i) {
    // this method has not changed
  }

  jumpTo(step) {
    this.setState({
      stepNumber: step,
      xIsNext: (step % 2) === 0,
    });
  }

  render() {
    // this method has not changed
  }

حالا باید چند تغییر در متد handleClick کامپوننت Game که زمان کلیک کاربر روی Square اجرا می شود اعمال کنیم.

stepNumber که در state اضافه کردیم تعداد حرکات را به کاربر نشان می دهد. پس از اینکه یک حرکت جدید انجام شد، نیاز داریم تا stepNumber را که بخشی از this.setState می باشد با اضافه کردن stepNumber: history.length به روز رسانی کنیم.

همچنین خواندن history را که به صورت this.state.history به this.state.history.slice(0, this.state.stepNumber + 1) تغییر می دهیم:

  handleClick(i) {
    const history = this.state.history.slice(0, this.state.stepNumber + 1);
    const current = history[history.length - 1];
    const squares = current.squares.slice();
    if (calculateWinner(squares) || squares[i]) {
      return;
    }
    squares[i] = this.state.xIsNext ? 'X' : 'O';
    this.setState({
      history: history.concat([{
        squares: squares
      }]),
      stepNumber: history.length,
      xIsNext: !this.state.xIsNext,
    });
  }

در آخر متد render کامپوننت Game را از حالتی که همیشه آخرین حرکت را render می کند به حالتی که تغییر انتخابی را طبق stepNumber، render کند تغییر می دهیم:

  render() {
    const history = this.state.history;
    const current = history[this.state.stepNumber];
    const winner = calculateWinner(current.squares);

    // the rest has not changed

اگر روی هر گام از تاریخچه بازی کلیک کنیم، Board بازی باید بلافاصله به شکلی که در آن گام بوده است به روز شود.

می توانید فایل های آموزش را از این لینک دریافت کنید.

منبع: reactjs.org

ReactJavascript

مطالب مرتبط

آموزش ساخت بازی XO با استفاده از React - بخش اول
مشاهده

آموزش ساخت بازی XO با استفاده از React - بخش اول

آموزش React - قسمت سوم
مشاهده

آموزش React - قسمت سوم

آموزش React - قسمت دوم
مشاهده

آموزش React - قسمت دوم



نظر شما

مطالب

  • CSS
  • Git
  • HTML
  • Javascript
  • PHP
  • Web

بیشترین بازدید

  • طراحی صفحه ثبت نام و ورود کاربران HTML و CSS

    طراحی صفحه ثبت نام و ورود کاربران HTML و CSS

    با توجه به اینکه در سایت تبلیغات، کاربران جهت ارائه آگهی های خود باید ثبت نام کنند در این قسمت برای ارسال اطلاعات به سمت سرور، با استفاده از تگ های موجود در HTML فرمی را جهت ثبت نام و ورود کاربران ایجاد خواهیم کرد. در ادامه مطلب همراه من باشید. چیست و چه کاربردی دارد؟
  • ساخت وب سرویس با استفاده از PHP و SOAP

    ساخت وب سرویس با استفاده از PHP و SOAP

    به عنوان توسعه دهنده نرم افزار، توانایی توسعه نرم افزار و سرویس برای محدوده گسترده ای از پلتفرم ها یک مهارت ضروری است. اما برای تحقق این موضوع  نمی توان انتظار داشت که همه از یک پلتفرم یا یک زبان برنامه نویسی استفاده کنند یا اینکه همه پلتفرم ها و زبان ها را پوشش داد، این یک کار نشدنی است. اگر تنها یک استاندارد وجود داشت که به ما اجازه می داد تا کدهای نرم افزارمان را یکبار بنویسیم و دیگران با نرم افزارهای خودشان به آسانی از طریق شبکه با آن ارتباط برقرار می کردند چقدر عالی می شد. خب خوشبختانه وجود دارد و نامش هم  SOAP است. در ادامه مطلب همراه من باشید. چیست و چه کاربردی دارد؟
  • طراحی صفحه ثبت نام و ورود کاربران PHP و MySQL

    طراحی صفحه ثبت نام و ورود کاربران PHP و MySQL

    برای ثبت اطلاعات کاربران در پایگاه داده سایت، باید با استفاده از PHP اطلاعات ارسال شده توسط کاربر را دریافت کنیم و با استفاده از دستورات MySQL ذخیره کنیم. جهت اجرای کدهای PHP و MySQL در ویندوز باید نرم افزار WAMP یا XAMP را در سیستم خود نصب کنید. با استفاده از این نرم افزار یک لوکال هاست مجازی در سیستم شما شبیه سازی می شود تا کدهای PHP را اجرا و پایگاه داده MySQL را ایجاد کنید. در ادامه مطلب همراه من باشید. چیست و چه کاربردی دارد؟
  • ساخت وب سرویس RESTful با استفاده از PHP

    ساخت وب سرویس RESTful با استفاده از PHP

    Representational State Transfer یک سبک معماری در وب سرویس است که در آن از آدرس ها برای دستیابی به منابع استفاده می شود. داده ها و توابع در معماری RESTful منابع نامیده می شوند به این جهت که داده ها و توابع در واقع آنچیزی هستند که ما می خواهیم از طریق سرویس به آن متصل شویم. در این پست می خواهیم نشان دهیم که چطور می توان یک وب سرویس RESTful را بدون استفاده از هیچ نوع Framework خاصی در PHP ایجاد کرد. در ادامه مطلب همراه من باشید. چیست و چه کاربردی دارد؟
  • آموزش نصب و استفاده از Composer

    آموزش نصب و استفاده از Composer

    Composer ابزاری برای مدیریت وابستگی در پروژه های PHP می باشد. زمانی که شما تصمیم می گیرید تا یک پروژه PHP را ایجاد کنید قطعا با مسائلی برخورد خواهید کرد که راه حل آنها استفاده از کتابخانه ها یا پکیج های موجودی است که برای این مساله ها ارائه شده اند زیرا با این کار در فاکتور های مهمی همچون زمان و هزینه صرفه جویی کرده اید و به عبارت دیگر چرخ را از نو اختراع نمی کنید. از این دست مسائل می توان به: اعتبار سنجی کاربر مدیریت پایگاه داده مسیریابی درخواست اشاره کرد. اما در این میان کتابخانه ها یا پکیج های موجود هم دارای وابستگی های خاص خود هستند و به عنوان توسعه دهنده PHP شما باید انرژی مضاعفی را برای یافتن و تطبیق این وابستگی ها صرف کنید. در ادامه مطلب همراه من باشید. چیست و چه کاربردی دارد؟
  • ساخت WSDL با استفاده از PHP

    ساخت WSDL با استفاده از PHP

    در قسمت قبل ایجاد یک اپلیکیشن سازگار را با استفاده از پروتکل SOAP بررسی کردیم. همینطور نشان دادیم که ساخت سرور و کلاینت SOAP با کتابخانه NuSOAP چقدر آسان است اما در این قسمت می خواهیم WSDL را که در هنگام کار با SOAP حتما استفاده خواهد شد را توضیح دهیم. در اینجا ما در ارتباط با فایل های WSDL و اینکه چطور می توان از آنها استفاده کرد بحث خواهیم کرد همچنین به شما نشان می دهیم که به چه صورت می توان فایل WSDL  را با NuSOAP ایجاد کنید و آن را با مثال های سرور و کلاینت SOAP که در قسمت قبل ایجاد کردیم ترکیب کنیم. در ادامه مطلب همراه من باشید. چیست و چه کاربردی دارد؟

دانلودها

  • آموزش لاراول: معرفی و آموزش گام به گام Laravel
  • آموزش ساخت بازی XO با استفاده از React - بخش دوم
  • آموزش ساخت بازی XO با استفاده از React - بخش اول
  • آموزش React - قسمت سوم
  • آموزش React - قسمت دوم

سوالات

  • اضافه کردن یک ستون جدید به جدول موجود در Migration لاراول

    چطور می توانم یک ستون به جدولی که از قبل با استفاده از فریموورک لاراول ایجاد شده است اضافه کنم؟من فایل Migration رو به صورت زیر ویرایش کردم:<?php public function up() { Schema::create('users', function ($table) { $table->integer("paid"); }); }در ترمینال هم دستور php artisan migrate:install  و migrate رو اجرا کردم، اما ستون اضافه نشده است.چطور می توانم ستون مورد نظرم را اضافه کنم؟
  • چک کردن موجود بودن یک رکورد در Laravel

    من تازه کار با فریممورک Laravel رو شروع کردم. چطور می توانم بررسی کنم که یک رکورد موجود است یا خیر؟$user = User::where('email', '=', Input::get('email'));چطور می می تونم بررسی کنم که user$ شامل رکورد هست یا نه؟
  • لاراول 4: چطور می توان در Blade آدرس صفحه را دریافت کرد؟

    من از لاراول نسخه 4 استفاده می کنم، چطور می توانم آدرس یک صفحه را دریافت کنم و در if@ استفاده کنم. می دونم که  می توانم با استفاده از کد PHP زیر این کار را انجام دهم:<?php echo URL::current(); ?>اما در blade چطور می توان این کار را انجام داد؟
  • چطور می توان چندین شرط Where در Eloquent لاراول در نظر گرفت؟

    من از Query Builder لاراول برای ایجاد گزارش استفاده می کنم و گزارشم دارای چندین شرط می باشد.شرط ها را به صورت زیر اعمال کردم اما به نظرم راه جالبی نیست.$results = User::where('this', '=', 1) ->where('that', '=', 1) ->where('this_too', '=', 1) ->where('that_too', '=', 1) ->where('this_as_well', '=', 1) ->where('that_as_well', '=', 1) ->where('this_one_too', '=', 1) ->where('that_one_too', '=', 1) ->where('this_one_as_well', '=', 1) ->where('that_one_as_well', '=', 1) ->get();آیا راه بهتری برای اعمال شرط ها وجود دارد؟
  • چطور می توان گزارش SQL که Query Builder لاراول آن را ایجاد می کند مشاهده کرد؟

    کد زیر را در نظر بگیرید:DB::table('users')->get();من می خوام کد SQL که Query Builder بالا اجرا می کند را دریافت کنم به عنوان مثال در کد بالا کد SQL:SELECT * FROM usersتوسط Query builder اجرا می شود.
  • Eloquent: شمارش و تشخیص خالی بودن

    آیا راهی برای تشخیص اینکه مجموعه بازگشتی از گزارش:$result = Model::where(...)->get() خالی است یا اینکه تعداد عناصر موجود در آن چقدر است وجود دارد؟من در حال حاضر از:!$result استفاده می کنم آیا راه درستی است؟در مورد:count($result)آیا همه موارد را پوشش می دهد؟ به عنوان مثال اگر result خالی باشد؟
  • لاراول 5: نمایش HTML در Blade

    من یک رشته به صورت زیر دارم که شامل تگ HTML می باشد:$text = '<p><strong>Lorem</strong> ipsum dolor <img src="images/test.jpg"></p>'و می خواهم با استفاده از Blade نمایش بدم:{{$text}}اما خود رشته را چاپ می کند و تگ های HTML را رندر نمی کند. چطور می توانم HTML را با Blade در لاراول 5 نمایش بدم؟
  • ReactJSX: استفاده از Props بین کوتیشن

    چطور می توان در JSX از یک مقدار props به عنوان مقدار attribute استفاده کرد؟به عنوان مثال:<img className="image" src="images/{this.props.image}" />و خروجی HTML آن به صورت زیر است:<img class="image" src="images/{this.props.image}"> 
  • ارتباط بین دو کامپوننت در React

    اپلیکیشن من شامل یک لیست با فیلتر های آن و یک button برای تغییر layout می باشد. در حال حاضر از سه کامپوننت:</list></Filters></TopBar>استفاده می کنم. می خوام زمانی که تنظیمات در </Filters> تغییر کرد متدی در کامپوننت </list> برای بروزرسانی view اجرا شود.چطور میتونم بین این سه کامپوننت ارتباط برقرار کنم؟ آیا باید از مدل داده global برای انجام این کار استفاده کنم؟ 
  • Show یا Hide کردن عنصر در React

    من تازه شروع به یادگیری React کردم و دنبال راهی هستم که بتونم یک عنصر روی صفحه را show یا hide کنم.  می خوام زمانی که کلیک کردم، div مربوط به نتایج نمایش داده شود.var Search= React.createClass({ handleClick: function (event) { console.log(this.prop); }, render: function () { return ( <div className="date-range"> <input type="submit" value="Search" onClick={this.handleClick} /> </div> ); } }); var Results = React.createClass({ render: function () { return ( <div id="results" className="search-results"> Some Results </div> ); } }); React.renderComponent(<Search /> , document.body); 

اشتراک

منو
خانه
ویدئو
دانلود
اپلیکیشن
درباره ما
خدمات
قالب سایت
خدمات
ما را دنبال کنید
Android Logo
Github Logo
© 2015 - 2023 All rights reserved