كيفية: استخدام ميزات الجمهور في إطار عمل Fluid
في هذا البرنامج التعليمي، ستتعرف على استخدام إطار عمل Fluid Audience مع React لإنشاء عرض توضيحي مرئي للمستخدمين المتصلين بحاوية. يحتوي كائن الجماعة المستهدفة على معلومات تتعلق بجميع المستخدمين المتصلين بالحاوية. في هذا المثال، سيتم استخدام مكتبة عميل Azure لإنشاء الحاوية والجمهور.
تعرض الصورة التالية أزرار المعرف وحقل إدخال معرف الحاوية. سيؤدي ترك حقل معرف الحاوية فارغا والنقر فوق زر معرف المستخدم إلى إنشاء حاوية جديدة والانضمام كمستخدم محدد. بدلا من ذلك، يمكن للمستخدم النهائي إدخال معرف حاوية واختيار معرف مستخدم للانضمام إلى حاوية موجودة كمستخدم محدد.
تظهر الصورة التالية عدة مستخدمين متصلين بحاوية ممثلة بمربعات. يمثل المربع الموضح باللون الأزرق المستخدم الذي يعرض العميل بينما تمثل المربعات الموضحة باللون الأسود المستخدمين المتصلين الآخرين. مع إرفاق المستخدمين الجدد بالحاوية بمعرف فريد، سيزداد عدد المربعات.
إشعار
يفترض هذا البرنامج التعليمي أنك على دراية بنظرة عامة على إطار عمل Fluid وأنك قد أكملت QuickStart. يجب أن تكون على دراية أيضا بأساسيات React، وإنشاء مشاريع React، وReact Hooks.
إنشاء مشروع
افتح موجه الأوامر وانتقل إلى المجلد الأصل حيث تريد إنشاء المشروع؛ على سبيل المثال،
C:\My Fluid Projects
.قم بتشغيل الأمر التالي في المطالبة. (لاحظ أن CLI هو npx، وليس npm. تم تثبيته عند تثبيت Node.js.)
npx create-react-app fluid-audience-tutorial
يتم إنشاء المشروع في مجلد فرعي يسمى
fluid-audience-tutorial
. انتقل إليه باستخدام الأمرcd fluid-audience-tutorial
.يستخدم المشروع مكتبات Fluid التالية:
مكتبة الوصف fluid-framework
يحتوي على بنية البيانات الموزعة SharedMap التي تزامن البيانات عبر العملاء. @fluidframework/azure-client
تعريف الاتصال بخادم خدمة Fluid وتحديد مخطط البدء لحاوية Fluid. @fluidframework/test-client-utils
تعريف InsecureTokenProvider المطلوب لإنشاء الاتصال بخدمة Fluid. قم بتشغيل الأمر التالي لتثبيت المكتبات.
npm install @fluidframework/azure-client @fluidframework/test-client-utils fluid-framework
تعليمة برمجية للمشروع
إعداد متغيرات الحالة وعرض المكون
افتح الملف
\src\App.js
في محرر التعليمات البرمجية. حذف كافة العبارات الافتراضيةimport
. ثم احذف كافة العلامات من العبارةreturn
. ثم أضف عبارات الاستيراد للمكونات وReact hooks. لاحظ أننا سننفذ مكونات AudienceDisplay وUserIdSelection المستوردة في الخطوات اللاحقة. يجب أن يبدو الملف كما يلي:import { useState, useCallback } from "react"; import { AudienceDisplay } from "./AudienceDisplay"; import { UserIdSelection } from "./UserIdSelection"; export const App = () => { // TODO 1: Define state variables to handle view changes and user input return ( // TODO 2: Return view components ); }
استبدل
TODO 1
بالتعليمات البرمجية التالية. تقوم هذه التعليمة البرمجية بتهيئة متغيرات الحالة المحلية التي سيتم استخدامها داخل التطبيق.displayAudience
تحدد القيمة ما إذا كنا نعرض مكون AudienceDisplay أو مكون UserIdSelection (راجعTODO 2
).userId
القيمة هي معرف المستخدم للاتصال بالحاوية باستخدام والقيمةcontainerId
هي الحاوية المراد تحميلها.handleSelectUser
يتم تمرير الدالتين وhandleContainerNotFound
كرد اتصال إلى العرضين وإدارة انتقالات الحالة.handleSelectUser
يتم استدعاء عند محاولة إنشاء/تحميل حاوية.handleContainerNotFound
يتم استدعاء عند فشل إنشاء/تحميل حاوية.ملاحظة، ستأتى القيم userId و containerId من مكون UserIdSelection من خلال الدالة
handleSelectUser
.const [displayAudience, setDisplayAudience] = useState(false); const [userId, setUserId] = useState(); const [containerId, setContainerId] = useState(); const handleSelectUser = useCallback((userId, containerId) => { setDisplayAudience(true) setUserId(userId); setContainerId(containerId); }, [displayAudience, userId, containerId]); const handleContainerNotFound = useCallback(() => { setDisplayAudience(false) }, [setDisplayAudience]);
استبدل
TODO 2
بالتعليمات البرمجية التالية. كما هو مذكور أعلاه،displayAudience
سيحدد المتغير ما إذا كنا نعرض مكون AudienceDisplay أو مكون UserIdSelection . أيضا، يتم تمرير الدالات لتحديث متغيرات الحالة إلى مكونات كخصائص.(displayAudience) ? <AudienceDisplay userId={userId} containerId={containerId} onContainerNotFound={handleContainerNotFound}/> : <UserIdSelection onSelectUser={handleSelectUser}/>
إعداد مكون AudienceDisplay
إنشاء ملف
\src\AudienceDisplay.js
وفتحه في محرر التعليمات البرمجية. أضف عباراتimport
التالية:import { useEffect, useState } from "react"; import { SharedMap } from "fluid-framework"; import { AzureClient } from "@fluidframework/azure-client"; import { InsecureTokenProvider } from "@fluidframework/test-client-utils";
لاحظ أن الكائنات المستوردة من مكتبة إطار عمل Fluid مطلوبة لتعريف المستخدمين والحاويات. في الخطوات التالية، سيتم استخدام AzureClient وConsentTokenProvider لتكوين خدمة العميل (راجع
TODO 1
) بينما سيتم استخدام SharedMap لتكوينcontainerSchema
الحاجة لإنشاء حاوية (راجعTODO 2
).أضف المكونات الوظيفية التالية ووظائف المساعد:
const tryGetAudienceObject = async (userId, userName, containerId) => { // TODO 1: Create container and return audience object } export const AudienceDisplay = (props) => { //TODO 2: Configure user ID, user name, and state variables //TODO 3: Set state variables and set event listener on component mount //TODO 4: Return list view } const AudienceList = (data) => { //TODO 5: Append view elements to list array for each member //TODO 6: Return list of member elements }
لاحظ أن AudienceDisplay و AudienceList هما مكونان وظيفيان يتعاملان مع الحصول على بيانات الجمهور وعرضها بينما
tryGetAudienceObject
يعالج الأسلوب إنشاء خدمات الحاوية والجمهور.
الحصول على الحاوية والجمهور
يمكنك استخدام دالة مساعد للحصول على بيانات Fluid، من كائن Audience، إلى طبقة العرض (حالة React). tryGetAudienceObject
يتم استدعاء الأسلوب عند تحميل مكون العرض بعد تحديد معرف المستخدم. يتم تعيين القيمة التي تم إرجاعها إلى خاصية حالة React.
استبدل
TODO 1
بالتعليمات البرمجية التالية. لاحظ أنه سيتم تمرير قيم منuserId
userName
containerId
مكون التطبيق. إذا لم يكنcontainerId
هناك ، يتم إنشاء حاوية جديدة. لاحظ أيضا أنcontainerId
يتم تخزين على تجزئة عنوان URL. قد يقوم المستخدم الذي يدخل جلسة عمل من مستعرض جديد بنسخ عنوان URL من مستعرض جلسة عمل موجود أو الانتقال إلىlocalhost:3000
معرف الحاوية وإدخاله يدويا. مع هذا التنفيذ، نريد تضمينgetContainer
الاستدعاء في محاولة التقاط في حالة إدخال المستخدم لمعرف حاوية غير موجود. تفضل بزيارة وثائق الحاويات لمزيد من المعلومات.const userConfig = { id: userId, name: userName, additionalDetails: { email: userName.replace(/\s/g, "") + "@example.com", date: new Date().toLocaleDateString("en-US"), }, }; const serviceConfig = { connection: { type: "local", tokenProvider: new InsecureTokenProvider("", userConfig), endpoint: "http://localhost:7070", }, }; const client = new AzureClient(serviceConfig); const containerSchema = { initialObjects: { myMap: SharedMap }, }; let container; let services; if (!containerId) { ({ container, services } = await client.createContainer(containerSchema)); const id = await container.attach(); location.hash = id; } else { try { ({ container, services } = await client.getContainer(containerId, containerSchema)); } catch (e) { return; } } return services.audience;
الحصول على الجمهور على تحميل المكون
الآن بعد أن حددنا كيفية الحصول على جمهور Fluid، نحتاج إلى إخبار React بالاتصال tryGetAudienceObject
عند تحميل مكون عرض الجمهور.
استبدل
TODO 2
بالتعليمات البرمجية التالية. لاحظ أن معرف المستخدم سيأتي من المكون الأصل إما أوuser1
user2
random
. إذا كان المعرف هوrandom
نستخدمMath.random()
لإنشاء رقم عشوائي كمعرف. بالإضافة إلى ذلك، سيتم تعيين اسم للمستخدم استنادا إلى معرفه كما هو محدد فيuserNameList
. وأخيرا، نحدد متغيرات الحالة التي ستخزن الأعضاء المتصلين بالإضافة إلى المستخدم الحالي.fluidMembers
سيقوم بتخزين قائمة بجميع الأعضاء المتصلين بالحاوية بينماcurrentMember
سيحتوي على كائن العضو الذي يمثل المستخدم الحالي الذي يعرض سياق المستعرض.const userId = props.userId == "random" ? Math.random() : props.userId; const userNameList = { "user1" : "User One", "user2" : "User Two", "random" : "Random User" }; const userName = userNameList[props.userId]; const [fluidMembers, setFluidMembers] = useState(); const [currentMember, setCurrentMember] = useState();
استبدل
TODO 3
بالتعليمات البرمجية التالية. سيؤدي هذا إلى استدعاءtryGetAudienceObject
عند تحميل المكون وتعيين أعضاء الجماعة المستهدفة التي تم إرجاعها إلىfluidMembers
وcurrentMember
. ملاحظة، نتحقق مما إذا كان يتم إرجاع كائن جماعة مستهدفة في حالة إدخال مستخدم ل containerId غير موجود ونحتاج إلى إرجاعه إلى طريقة العرض UserIdSelection (props.onContainerNotFound()
سيتعامل مع تبديل طريقة العرض). أيضا، من الممارسات الجيدة إلغاء تسجيل معالجات الأحداث عند إلغاء تحميل مكون React عن طريق إرجاعaudience.off
.useEffect(() => { tryGetAudienceObject(userId, userName, props.containerId).then(audience => { if(!audience) { props.onContainerNotFound(); alert("error: container id not found."); return; } const updateMembers = () => { setFluidMembers(audience.getMembers()); setCurrentMember(audience.getMyself()); } updateMembers(); audience.on("membersChanged", updateMembers); return () => { audience.off("membersChanged", updateMembers) }; }); }, []);
استبدل
TODO 4
بالتعليمات البرمجية التالية. ملاحظة، إذا لم تتم تهيئةfluidMembers
أوcurrentMember
، يتم عرض شاشة فارغة. سيعرض مكون AudienceList بيانات العضو مع التصميم (ليتم تنفيذه في القسم التالي).if (!fluidMembers || !currentMember) return (<div/>); return ( <AudienceList fluidMembers={fluidMembers} currentMember={currentMember}/> )
إشعار
يمكن أن تؤدي انتقالات الاتصال إلى نوافذ توقيت قصيرة حيث
getMyself
ترجعundefined
. وذلك لأنه لن تتم إضافة اتصال العميل الحالي إلى الجمهور حتى الآن، لذلك لا يمكن العثور على معرف اتصال مطابق. لمنع React من عرض صفحة بدون أعضاء جمهور، نضيف وحدة استماع للاتصالupdateMembers
علىmembersChanged
. يعمل هذا نظرا لأن جمهور الخدمة يصدر حدثاmembersChanged
عند توصيل الحاوية.
إنشاء طريقة العرض
استبدل
TODO 5
بالتعليمات البرمجية التالية. لاحظ أننا نقدم مكون قائمة لكل عضو تم تمريره من مكون AudienceDisplay . لكل عضو، نقارنmember.userId
currentMember.userId
أولا بالتحقق مما إذا كان هذا العضوisSelf
. بهذه الطريقة، يمكننا تمييز مستخدم العميل عن المستخدمين الآخرين وعرض المكون بلون مختلف. ثم ندفع مكون القائمة إلى صفيفlist
. سيعرض كل مكون بيانات الأعضاء مثلuserId
userName
وadditionalDetails
.const currentMember = data.currentMember; const fluidMembers = data.fluidMembers; const list = []; fluidMembers.forEach((member, key) => { const isSelf = (member.userId === currentMember.userId); const outlineColor = isSelf ? 'blue' : 'black'; list.push( <div style={{ padding: '1rem', margin: '1rem', display: 'flex', outline: 'solid', flexDirection: 'column', maxWidth: '25%', outlineColor }} key={key}> <div style={{fontWeight: 'bold'}}>Name</div> <div> {member.userName} </div> <div style={{fontWeight: 'bold'}}>ID</div> <div> {member.userId} </div> <div style={{fontWeight: 'bold'}}>Connections</div> { member.connections.map((data, key) => { return (<div key={key}>{data.id}</div>); }) } <div style={{fontWeight: 'bold'}}>Additional Details</div> { JSON.stringify(member.additionalDetails, null, '\t') } </div> ); });
استبدل
TODO 6
بالتعليمات البرمجية التالية. سيؤدي هذا إلى عرض كل عنصر من عناصر الأعضاء التي دفعناها إلىlist
الصفيف.return ( <div> {list} </div> );
إعداد مكون UserIdSelection
إنشاء ملف
\src\UserIdSelection.js
وفتحه في محرر التعليمات البرمجية. سيتضمن هذا المكون أزرار معرف المستخدم وحقول إدخال معرف الحاوية التي تسمح للمستخدمين النهائيين باختيار معرف المستخدم والجلسة التعاونية. أضف العبارات التاليةimport
والمكونات الوظيفية:import { useState } from 'react'; export const UserIdSelection = (props) => { // TODO 1: Define styles and handle user inputs return ( // TODO 2: Return view components ); }
استبدل
TODO 1
بالتعليمات البرمجية التالية. لاحظ أن الدالةonSelectUser
ستقوم بتحديث متغيرات الحالة في مكون التطبيق الأصل والمطالبة بتغيير طريقة العرض.handleSubmit
يتم تشغيل الأسلوب بواسطة عناصر الزر التي سيتم تنفيذها فيTODO 2
. أيضا،handleChange
يتم استخدام الأسلوب لتحديثcontainerId
متغير الحالة. سيتم استدعاء هذا الأسلوب من وحدة إصغاء حدث عنصر الإدخال التي تم تنفيذها فيTODO 2
. لاحظ أيضا أننا نقوم بتحديثcontainerId
الحصول على القيمة من عنصر HTML بالمعرفcontainerIdInput
(المحدد فيTODO 2
).const selectionStyle = { marginTop: '2rem', marginRight: '2rem', width: '150px', height: '30px', }; const [containerId, setContainerId] = (location.hash.substring(1)); const handleSubmit = (userId) => { props.onSelectUser(userId, containerId); } const handleChange = () => { setContainerId(document.getElementById("containerIdInput").value); };
استبدل
TODO 2
بالتعليمات البرمجية التالية. سيؤدي ذلك إلى عرض أزرار معرف المستخدم بالإضافة إلى حقل إدخال معرف الحاوية.<div style={{display: 'flex', flexDirection:'column'}}> <div style={{marginBottom: '2rem'}}> Enter Container Id: <input type="text" id="containerIdInput" value={containerId} onChange={() => handleChange()} style={{marginLeft: '2rem'}}></input> </div> { (containerId) ? (<div style={{}}>Select a User to join container ID: {containerId} as the user</div>) : (<div style={{}}>Select a User to create a new container and join as the selected user</div>) } <nav> <button type="submit" style={selectionStyle} onClick={() => handleSubmit("user1")}>User 1</button> <button type="submit" style={selectionStyle} onClick={() => handleSubmit("user2")}>User 2</button> <button type="submit" style={selectionStyle} onClick={() => handleSubmit("random")}>Random User</button> </nav> </div>
بدء تشغيل خادم Fluid وتشغيل التطبيق
إشعار
لمطابقة بقية هذه الكيفية، يستخدم npx
هذا القسم أوامر و npm
لبدء تشغيل خادم Fluid. ومع ذلك، يمكن تشغيل التعليمات البرمجية في هذه المقالة أيضا مقابل خادم Azure Fluid Relay. لمزيد من المعلومات، راجع كيفية: توفير خدمة Azure Fluid Relay وكيفية: الاتصال إلى خدمة Azure Fluid Relay
في موجه الأوامر، قم بتشغيل الأمر التالي لبدء تشغيل خدمة Fluid.
npx @fluidframework/azure-local-service@latest
افتح موجه أوامر جديد وانتقل إلى جذر المشروع؛ على سبيل المثال، C:/My Fluid Projects/fluid-audience-tutorial
. ابدأ تشغيل خادم التطبيق باستخدام الأمر التالي. يفتح التطبيق في المستعرض. قد تستغرق بضع دقائق.
npm run start
انتقل إلى localhost:3000
على علامة تبويب مستعرض لعرض التطبيق قيد التشغيل. لإنشاء حاوية جديدة، حدد زر معرف مستخدم أثناء ترك إدخال معرف الحاوية فارغا. لمحاكاة مستخدم جديد ينضم إلى جلسة عمل الحاوية، افتح علامة تبويب متصفح جديدة وانتقل إلى localhost:3000
. هذه المرة، أدخل قيمة معرف الحاوية التي يمكن العثور عليها من متابعة http://localhost:3000/#
عنوان url لعلامة تبويب المستعرض الأولى .
إشعار
قد تحتاج إلى تثبيت تبعية إضافية لجعل هذا العرض التوضيحي متوافقا مع Webpack 5. إذا تلقيت خطأ في التحويل البرمجي يتعلق بحزمة "مخزن مؤقت" أو "url"، فيرجى التشغيل npm install -D buffer url
والمحاولة مرة أخرى. سيتم حل هذا في إصدار مستقبلي من إطار عمل Fluid.
الخطوات التالية
- حاول توسيع العرض التوضيحي مع المزيد من أزواج المفاتيح/القيم في الحقل في
additionalDetails
userConfig
. - ضع في اعتبارك دمج الجمهور في تطبيق تعاوني يستخدم بنيات البيانات الموزعة مثل SharedMap أو SharedString.
- تعرف على المزيد حول Audience.
تلميح
عند إجراء تغييرات على التعليمات البرمجية، سيعيد المشروع إنشاءه تلقائيا وسيعيد خادم التطبيق تحميله. ومع ذلك، إذا قمت بإجراء تغييرات على مخطط الحاوية، فلن تسري إلا إذا قمت بإغلاق خادم التطبيق وإعادة تشغيله. للقيام بذلك، امنح التركيز إلى موجه الأوامر واضغط على Ctrl-C مرتين. ثم قم بتشغيل npm run start
مرة أخرى.