برنامه نویسی

دو طرفه Binding یک خیابان دو طرفه است

Summarize this content to 400 words in Persian Lang
در برخی از دایره ها، اتصال دو طرفه به عنوان آفت قسمت های جلویی مدرن در نظر گرفته می شود، در حالی که در برخی دیگر به عنوان راحتی ارگونومیک نهایی در نظر گرفته می شود. یک گروه به سختی می تواند این عبارت را بدون ظاهر انزجار بیان کند در حالی که گروه دیگر عدم گنجاندن آن را ضربه ای بزرگ به راه حل می داند.

امروز، می‌خواهم به این موضوع نگاهی بیندازم تا بتوانیم پیامدهای آن را بهتر درک کنیم و چرا برخی (از جمله خودم) به شدت نسبت به آن احساس می‌کنند.

دو طرفه Binding چیست

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

به عنوان مثال، اگر شما یک عنصر ورودی داشته باشید که یک عبارت جستجو را ذخیره می‌کند و از آن برای تولید نتایج جستجو استفاده می‌کنید. با صحافی دو طرفه. شما می توانید نشان دهید که عبارت SearchTerm با آن مرتبط است value فیلد ورودی و هر دو searchTerm و هنگام تغییر از به‌روزرسانی، ورودی همگام نگه داشته می‌شود searchTerm مستقیم یا از تایپ در ورودی.

let searchTerm = createState(“”)

input type=”text” value={searchTerm} >

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

عملاً موارد فوق معادل با:

let searchTerm = createState(“”)

input type=”text” value={searchTerm}
oninput={(e) => searchTerm = e.target.value} >

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

همانطور که می بینید، یک دسته از دیگ بخار را برای یک چیز معمولی کاهش می دهد. پس این چیز خوبی نیست؟

قدردانی از مشکل

اتصال داده‌ها قبل از اینکه به چارچوب‌های جاوا اسکریپت راه پیدا کند، بازمی‌گردد، به همین دلیل است که در اولین چارچوب‌های اعلامی نشان داده شد. Angular.js و Knockout.js آن را از سال 2010 در اختیار داشتند. این یک ابزار فوق العاده قدرتمند برای جریان به روز رسانی در برنامه شما و همگام نگه داشتن همه چیز بود.

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

بنابراین تفاوت بین جریان دو طرفه و یک طرفه چیست؟

مکانیسم اتصال دو طرفه شامل انتقال یک حالت اولیه است که هم باعث می‌شود کودک در هنگام تغییر به‌روزرسانی شود و هم کودک می‌تواند خود باعث بروز رسانی شود. راحتی از توانایی انتقال یک مقدار منفرد ناشی می شود.

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

وقتی همه چیز به طور ضمنی متصل است، ایجاد حلقه‌های “نامرئی” که در آن به‌روزرسانی‌ها در درخت رندر بالا و پایین می‌روند، نیازی به مقدار زیادی ندارد. یک رویکرد رندر از بالا به پایین (مانند VDOM یا جستجوگر کثیف) ممکن است متوجه شود که تغییری تا حدودی در چرخه به‌روزرسانی آن اتفاق افتاده است و سپس باید دوباره شروع شود. محلول‌های واکنشی ریزدانه ممکن است از کار غیر ضروری جلوگیری کنند، اما همچنان بر قابلیت ردیابی تأثیر می‌گذارد.

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

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

آیا راه حل هایی وجود دارد؟

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

1. انتخاب صریح

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

چیزی که همراه با این اتفاق می افتد این است که الگوهای توصیه شده به طور تصادفی از این محدودیت ها دور می شوند. اگر چارچوبی از سیگنال‌های واکنش‌پذیر قابل تغییر استفاده کند و آنها را به مؤلفه‌های فرزند ارسال کنید، و الگوی اتصال دوطرفه نیز شامل جهش اجزای ورودی باشد، ممکن است افراد متوجه نشوند که چه چیزی را انتخاب کرده‌اند. این امر به ویژه در صورتی مهم است که چارچوب از واکنش پذیری تودرتو از طریق پراکسی ها یا موارد دیگر پشتیبانی کند.

Svelte یک نمونه عالی از چارچوبی است که از نوشتن برای پایه‌ها برای انجام اتصال دو طرفه خود استفاده می‌کند. انجام این کار ایمن تر است زیرا Svelte واکنش پذیری عمیق ندارد. هیچ مقدار غیرمستقیم نمی تواند شما را به طور تصادفی مقداری را در فرزند تنظیم کند که وضعیت را در والد بدون انتخاب صریح به روز کند. هنوز خطر جفت شدن بیش از حد وجود دارد، اما شما کنترل کامل در هر نقطه دارید.

2. جداسازی خواندن/نوشتن داخلی

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

در عوض، آن را مستقیماً فوروارد کنید یا از طریق یک رویداد به‌روزرسانی کنید. مصرف کنندگان فقط از انتقال یک مقدار سود می برند، اما نویسندگان بدون افشای یک API قابل تغییر ضمنی، کنترل بیشتری دارند.

3. خواندن/نوشتن تفکیک در همه جا

یا اصلاً نمی توانید از اتصال دو طرفه پشتیبانی کنید. با ارائه یک رابط خواندن/نوشتن مجزا در همه اولیه‌های شما، ساده‌ترین کار این است. این رویکرد React و رویکردی است که من در Solid اتخاذ کردم.

function App() {
const [name, setName] = createSignal(“world”);

// How do you 2-way bind this? You don’t…
return Input value={name()} onUpdate={setName} />
}

function Input(props) {
return input
value={props.value}
onInput={e => props.onUpdate(e.target.value)}
/>
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

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

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

آره یا نه؟

همیشه این سوال مطرح است که آیا ما احساس می کنیم به اندازه کافی ایمن است و آیا ارزش تلاش برای حمایت را دارد یا خیر. ملاحظات ارگونومی حول روابط صریح در مقابل روابط ضمنی. آیا این دیگ بخار را به کسانی که می دانند دارند انجام می دهند مجبور می کنیم یا به گونه ای طراحی می کنیم که آن را از گزینه های معقول حذف کند؟

برای من، و با Solid، من به شدت طرف “نه” هستم. اما من همچنین روی مارکو کار کرده ام که رویکرد Vue را انجام می دهد و شبیه آن است. مؤلفه‌های سرور به افرادی منجر می‌شوند که از «فرم‌های کنترل‌نشده» استفاده می‌کنند و بیشتر آن‌ها را در تنها جایی که واقعاً سودمند است، می‌برند.

چند چیز وجود دارد که باید از نقطه نظر طراحی به عنوان پرچم قرمز بالقوه برای راه حل های اتصال دو طرفه به آنها توجه کرد.

آیا الزام آور دو طرفه ضمنی است؟
آیا ابتدایی‌ها تغییرپذیر هستند و حتی زمانی که داده‌ها متصل نیستند، توانایی خواندن/نوشتن را تشویق می‌کنند؟
آیا نوشتن را در یک سیستم با واکنش‌پذیری عمیق تشویق می‌کند؟

اما دوباره چه زمانی کسی توانسته است یک توسعه دهنده را از انجام کاری که می خواهد باز دارد؟

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

امروز، می‌خواهم به این موضوع نگاهی بیندازم تا بتوانیم پیامدهای آن را بهتر درک کنیم و چرا برخی (از جمله خودم) به شدت نسبت به آن احساس می‌کنند.


دو طرفه Binding چیست

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

به عنوان مثال، اگر شما یک عنصر ورودی داشته باشید که یک عبارت جستجو را ذخیره می‌کند و از آن برای تولید نتایج جستجو استفاده می‌کنید. با صحافی دو طرفه. شما می توانید نشان دهید که عبارت SearchTerm با آن مرتبط است value فیلد ورودی و هر دو searchTerm و هنگام تغییر از به‌روزرسانی، ورودی همگام نگه داشته می‌شود searchTerm مستقیم یا از تایپ در ورودی.

let searchTerm = createState("")

input type="text" value={searchTerm} >
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

عملاً موارد فوق معادل با:

let searchTerm = createState("")

input type="text" value={searchTerm}
  oninput={(e) => searchTerm = e.target.value} >
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

همانطور که می بینید، یک دسته از دیگ بخار را برای یک چیز معمولی کاهش می دهد. پس این چیز خوبی نیست؟


قدردانی از مشکل

توضیحات تصویر

اتصال داده‌ها قبل از اینکه به چارچوب‌های جاوا اسکریپت راه پیدا کند، بازمی‌گردد، به همین دلیل است که در اولین چارچوب‌های اعلامی نشان داده شد. Angular.js و Knockout.js آن را از سال 2010 در اختیار داشتند. این یک ابزار فوق العاده قدرتمند برای جریان به روز رسانی در برنامه شما و همگام نگه داشتن همه چیز بود.

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

بنابراین تفاوت بین جریان دو طرفه و یک طرفه چیست؟

مکانیسم اتصال دو طرفه شامل انتقال یک حالت اولیه است که هم باعث می‌شود کودک در هنگام تغییر به‌روزرسانی شود و هم کودک می‌تواند خود باعث بروز رسانی شود. راحتی از توانایی انتقال یک مقدار منفرد ناشی می شود.

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

وقتی همه چیز به طور ضمنی متصل است، ایجاد حلقه‌های “نامرئی” که در آن به‌روزرسانی‌ها در درخت رندر بالا و پایین می‌روند، نیازی به مقدار زیادی ندارد. یک رویکرد رندر از بالا به پایین (مانند VDOM یا جستجوگر کثیف) ممکن است متوجه شود که تغییری تا حدودی در چرخه به‌روزرسانی آن اتفاق افتاده است و سپس باید دوباره شروع شود. محلول‌های واکنشی ریزدانه ممکن است از کار غیر ضروری جلوگیری کنند، اما همچنان بر قابلیت ردیابی تأثیر می‌گذارد.

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

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


آیا راه حل هایی وجود دارد؟

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


1. انتخاب صریح

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

چیزی که همراه با این اتفاق می افتد این است که الگوهای توصیه شده به طور تصادفی از این محدودیت ها دور می شوند. اگر چارچوبی از سیگنال‌های واکنش‌پذیر قابل تغییر استفاده کند و آنها را به مؤلفه‌های فرزند ارسال کنید، و الگوی اتصال دوطرفه نیز شامل جهش اجزای ورودی باشد، ممکن است افراد متوجه نشوند که چه چیزی را انتخاب کرده‌اند. این امر به ویژه در صورتی مهم است که چارچوب از واکنش پذیری تودرتو از طریق پراکسی ها یا موارد دیگر پشتیبانی کند.

Svelte یک نمونه عالی از چارچوبی است که از نوشتن برای پایه‌ها برای انجام اتصال دو طرفه خود استفاده می‌کند. انجام این کار ایمن تر است زیرا Svelte واکنش پذیری عمیق ندارد. هیچ مقدار غیرمستقیم نمی تواند شما را به طور تصادفی مقداری را در فرزند تنظیم کند که وضعیت را در والد بدون انتخاب صریح به روز کند. هنوز خطر جفت شدن بیش از حد وجود دارد، اما شما کنترل کامل در هر نقطه دارید.


2. جداسازی خواندن/نوشتن داخلی

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

در عوض، آن را مستقیماً فوروارد کنید یا از طریق یک رویداد به‌روزرسانی کنید. مصرف کنندگان فقط از انتقال یک مقدار سود می برند، اما نویسندگان بدون افشای یک API قابل تغییر ضمنی، کنترل بیشتری دارند.


3. خواندن/نوشتن تفکیک در همه جا

یا اصلاً نمی توانید از اتصال دو طرفه پشتیبانی کنید. با ارائه یک رابط خواندن/نوشتن مجزا در همه اولیه‌های شما، ساده‌ترین کار این است. این رویکرد React و رویکردی است که من در Solid اتخاذ کردم.

function App() {
  const [name, setName] = createSignal("world");

  // How do you 2-way bind this? You don't...
  return Input value={name()} onUpdate={setName} />
}

function Input(props) {
  return input
    value={props.value}
    onInput={e => props.onUpdate(e.target.value)}
  />
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

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

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


آره یا نه؟

توضیحات تصویر

همیشه این سوال مطرح است که آیا ما احساس می کنیم به اندازه کافی ایمن است و آیا ارزش تلاش برای حمایت را دارد یا خیر. ملاحظات ارگونومی حول روابط صریح در مقابل روابط ضمنی. آیا این دیگ بخار را به کسانی که می دانند دارند انجام می دهند مجبور می کنیم یا به گونه ای طراحی می کنیم که آن را از گزینه های معقول حذف کند؟

برای من، و با Solid، من به شدت طرف “نه” هستم. اما من همچنین روی مارکو کار کرده ام که رویکرد Vue را انجام می دهد و شبیه آن است. مؤلفه‌های سرور به افرادی منجر می‌شوند که از «فرم‌های کنترل‌نشده» استفاده می‌کنند و بیشتر آن‌ها را در تنها جایی که واقعاً سودمند است، می‌برند.

چند چیز وجود دارد که باید از نقطه نظر طراحی به عنوان پرچم قرمز بالقوه برای راه حل های اتصال دو طرفه به آنها توجه کرد.

  • آیا الزام آور دو طرفه ضمنی است؟
  • آیا ابتدایی‌ها تغییرپذیر هستند و حتی زمانی که داده‌ها متصل نیستند، توانایی خواندن/نوشتن را تشویق می‌کنند؟
  • آیا نوشتن را در یک سیستم با واکنش‌پذیری عمیق تشویق می‌کند؟

اما دوباره چه زمانی کسی توانسته است یک توسعه دهنده را از انجام کاری که می خواهد باز دارد؟

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا