اذهب إلى المحتوى

لوحة المتصدرين

  1. فاطمة أحمد6

    فاطمة أحمد6

    الأعضاء


    • نقاط

      1

    • المساهمات

      52


  2. سارة طه

    سارة طه

    الأعضاء


    • نقاط

      1

    • المساهمات

      18


  3. Mohamad Ibrahim3

    Mohamad Ibrahim3

    الأعضاء


    • نقاط

      1

    • المساهمات

      1311


  4. E.Nourddine

    E.Nourddine

    الأعضاء


    • نقاط

      1

    • المساهمات

      1458


المحتوى الأكثر حصولًا على سمعة جيدة

المحتوى الأعلى تقييمًا في 06/30/15 في كل الموقع

  1. يعتبر React.js -على حداثته- من أقوى أطر عمل Javascript (بعضهم قد يسميه مكتبة وليس إطار عمل) لبناء الواجهات الرسومية على الويب، حيث طبّق أفكارًا جديدة في هذا المجال، جعلت شِفرة الواجهات البرمجية أكثر نظافة، سرعة وأكثر قابلية للصيانة. يسمح لك React ببناء الواجهة الرسومية في مجموعة مكونات، كل مكوّن عبارة عن سرد لهيكلة ومنطق المكون، إذا تمزج بين شِفرة HTML مخصصّة وشِفرة جافاسكربت تصف سلوك ذاك المكون، ليكون قائما بذاته وقابلا لإعادة الاستعمال. إطار عمل React مُطور من طرف شركة فيس بوك (Facebook)، وقد يكفيك ثقة ويجذب انتباهك بمجرد أن تعرف أن فيس بوك نفسها تستخدم React في واجهتها البرمجية على موقع Facebook نفسه! يمكنك فتح موقع Facebook وعرض شفرة HTML الخاصة به والبحث عن كلمة react للتأكد بنفسك. سنقوم في هذا الدرس بإنشاء مُربَّع تعليقات بسيط وفعَّال بإمكانك وضعه في مدوَّنتك، سيكون المُربَّع عبارة عن نُسخة مُجرَّدة من التعليقات الآنية التي تُقدمها لك تعليقات Disquse ،LiveFyre أو فيس بوك. ستجد في نهاية الدَّرس أنَّ لديكَ مُربَّع تعليقات يوفِّر ما يلي: عرض لجميع التعليقات.نموذج لإرسال تعليق.خُطَّافات لتوفير مُنتهى خلفي مُخصَّص custom backend.سوف يحتوي مُربَّع التعليقات كذلك على بعض المزايا اللَّطيفة: تعليق مُحسَّن: تظهر التَّعليقات في القائمة قبل أن يتمّ حفظها على الخادم وبناءً عليه تظهر التَّعليقات في التوِّ واللَّحظة.تحديثات حيَّة: تظهر تعليقات المستخدمين الآخرين في عرض التَّعليقات في نفس وقت الإرسال.هيئة Markdown: يُمكن للمستخدمين استخدام Markdown لتهيئة نصوصهم.هل ترغب في تخطِّي كل هذا ومعاينة المصدر؟ كل شيء موجود على GitHub. تشغيل الخادمرغم أنَّه ليس من الضروري أن تبدأ بهذا الجزء من الدرس إلَّا أنَّنا سنقوم في وقت لاحق بإضافة وظائف تتطلَّب المُشاركة POST إلى خادم قيد التشغيل. إذا كُنتَ واثقٌ من أنّك على دراية بهذا الأمر وترغب في إنشاء خادمك الخاص يُمكنكَ القيام بذلك. ولِمَن يُريد التَّركيز على تعلُّم React دون الحاجة إلى القلق بشأن جوانب الخادم، فلقد كتبنا خوادم بسيطة بعددٍ من اللُّغات: Python ،Ruby ،Go، Node.js و PHP. كلُّ هذا مُتاح على GitHub. يُمكن الاطِّلاع على المصدر أو تحميل ملفّ مضغوط للبدء. للبدء بتطبيق هذا الدَّرس، كلّ ما عليكَ فعله هو بداية تحرير public/index.php. البدءسنستخدم لهذا الدرس ملفَّات JavaScript سبق إنشاؤها على شبكة توصيل مُحتوى CDN. قم بفتح المُحرِّر المفضَّل لديك وقم بإنشاء مُستند HTML جديد: <!-- index.html --> <!DOCTYPE html> <html> <head> <title>Hello React</title> <script src="https://fb.me/react-0.13.3.js"></script> <script src="https://fb.me/JSXTransformer-0.13.3.js"></script> <script src="https://code.jquery.com/jquery-2.1.3.min.js"></script> </head> <body> <div id="content"></div> <script type="text/jsx"> // Your code here </script> </body> </html>سيتمّ كتابة شفرات JavaScript في وسم السكربت هذا طوال الفترة المتبقية من الدرس. مُلاحظة: قُمنا بإدراج jQuery هُنا لأننا نٌريد تبسيط الشَّفرات لاستدعاءات Ajax في المُستقبل، ولكنَّها ليست إلزاميَّة لعمل React. مُكوِّنكَ الأوَّلتتمحور الفكرة الأساسيَّة لـ React حول كل شيءٍ له علاقة بالمُكوِّنات التركيبيَّة القابلة للتَّشكيل modular, composable components. سنستخدم بنية المُكوٍّنات التالية لمثال مُربَّع التَّعليقات لهذا الدرس: - CommentBox - CommentList - Comment - CommentFormسنقوم الآن ببناء المُكوِّن CommentBox وما هو إلَّا وسم بسيط: // tutorial1.js var CommentBox = React.createClass({ render: function() { return ( <div className="commentBox"> Hello, world! I am a CommentBox. </div> ); } }); React.render( <CommentBox />, document.getElementById('content') );لاحظ أن أسماء عناصر HTML تبدأ بحرف صغير في حين أن أسماء فئات React تبدأ بحرف كبير. 1. صياغة JSXستُلاحظ أوَّل ما تلاحظ تلكَ الصياغة المُشابهة لـ XML في شفرة JavaScript. لدينا precompiler بسيط يُترجم الجُملة البسيطة Syntactic Sugar إلى شفرات JavaScript المُجرَّدة هذه: // tutorial1-raw.js var CommentBox = React.createClass({displayName: 'CommentBox', render: function() { return ( React.createElement('div', {className: "commentBox"}, "Hello, world! I am a CommentBox." ) ); } }); React.render( React.createElement(CommentBox, null), document.getElementById('content') );إنَّ استخدام صياغة JSX اختياري ولكن وجدنا أنَّها أسهل استخدامًا من شفرات JavaScript مُجرَّدة. يُمكن قراءة المزيد في مقال صياغة JSX 2. ماذا يحدث هنانقوم بتمرير بعض الوظائف في كائن JavaScript إلى دالَّة ()React.createClass لإنشاء مُكوِّن React جديد. أهم هذه الوظائف ما تُسمَّى تصيير render والتي تُعيد شجرة من مُكوِّنات React والتي في نهاية المطاف ستقوم بالتصيير عبر HTML. لا تُعتبر وسوم عُقَد نموذج كائن مُستند DOM فعليَّة، وإنَّما هي تمثيلات من مُكوِّنات div الخاصَّة بـ React. يُمكنكَ اعتبارها كوسوم أو قطع من البيانات والتي يعرف React كيفيَّة التعامل معها. React آمن. لا نقوم بتوليد سلاسل HTML لذلك فإن حماية XSS تُعتبر الافتراضيَّة. لا يجب عليكَ إعادة شفرات HTML قياسيَّة. وإنَّما يُمكنكَ إعادة شجرة من المُكوِّنات التي قُمتَ (أو شخص آخر قام) ببنائها. هذا ما يجعل React قابلة للتَّشكيل composable: وهي عقيدة أساسيَّة في الواجهات الأماميَّة القابلة للصّيانة. يقوم ()React.render بتمثيل المُكوِّن القاعدي، بدء عمل الإطار، ثم إدخال الوسوم إلى عنصر نموذج كائن مُستند خام، يتمّ تقديم تلك الوسوم كمُعطى ثاني . تركيب المُكوِّناتسنُنشيء الآن هياكل بناء لكلٍّ من المُكوِّنين CommentList وCommentForm والتي ستكون -مرَّة أخرى- عبارة عن وسوم بسيطة. أضِف هذين المُكوِّنين إلى ملفِّك مع الحفاظ على تعريف commentBox الحالي واستدعاء React.render: // tutorial2.js var CommentList = React.createClass({ render: function() { return ( <div className="commentList"> Hello, world! I am a CommentList. </div> ); } }); var CommentForm = React.createClass({ render: function() { return ( <div className="commentForm"> Hello, world! I am a CommentForm. </div> ); } });ما سنقوم بعمله الآن هو تحديث مُكوِّن CommentBox لاستخدام المُكوِّنات الجديدة: // tutorial3.js var CommentBox = React.createClass({ render: function() { return ( <div className="commentBox"> <h1>Comments</h1> <CommentList /> <CommentForm /> </div> ); } });لاحظ كيف تمَّ مزج وسوم HTML والمُكوِّنات التي قُمنا ببنائها. إنَّ مُكوِّنات HTML ما هي إلَّا مُكوِّنات React مُنتظمة، تمامًا مثل تلك التي تقوم بتعريفها ولكن مع فارق واحد. سيقوم مترجم JSX تلقائيًا بإعادة كتابة وسوم HTML إلى تعبيرات React.createElement() tagName وترك كل شيء على حدة. وهذا لمنع حدوث التَّلوّث في مساحة الاسم العموميَّة global namespace. استخدام الخصائصسنقوم الآن بانشاء مُكوِّن Comment، والذي سوف يعتمد على البيانات التي تمَّ تمريرها إليه من المُكوِّن الأساسي. يتمّ اتاحة البيانات التي تمّ تمريرها من مُكوِّن أساسي كـ "خاصيَّة" في المُكوِّن الفرعي. ويتمّ الوصول إلى هذه "الخصائص" من خلال this.props. يُمكننا باستخدام الخصائص props قراءة البيانات التي تمّ تمريرها إلى Comment من CommentList، وتصيير بعض الترميزات: // tutorial4.js var Comment = React.createClass({ render: function() { return ( <div className="comment"> <h2 className="commentAuthor"> {this.props.author} </h2> {this.props.children} </div> ); } });يُمكنكَ وضع نصّ أو مُكوِّنات React في الشَّجرة وذلك بإحاطة تعبير JavaScript بأقواس داخل JSX (إما كخاصيَّة أو كمُكوِّن فرعي). نقوم بالوصول إلى خاصيَّات مُسمَّاه تمّ تمريرها إلى عنصر كمفاتيح على this.props وأيّ عناصر مُتداخلة كما this.props.children. خصائص المُكوِّننحتاج الآن وبعد أن قمنا بتحديد مُكوِّن Comment إلى تمرير اسم الكاتب ونصّ التعليق إلى هذا المُكوِّن. يسمح لنا هذا بإعادة استخدام نفس الشَّفرة لكلِّ تعليق مُختلف. لنقوم الآن بإضافة بعض التَّعليقات داخل مُكوِّن CommentList: // tutorial5.js var CommentList = React.createClass({ render: function() { return ( <div className="commentList"> <Comment author="Pete Hunt">This is one comment</Comment> <Comment author="Jordan Walke">This is *another* comment</Comment> </div> ); } });لاحظ أنَّنا قد قُمنا بتمرير بعض البيانات من مُكوِّن CommentList الأساسي إلى مُكوِّنات Comment الفرعيَّة. مرَّرنا على سبيل المثال Pete Hunt (عن طريق خاصيَّة) وThis is one comment (عن طريق عُقدة فرعيَّة تُشبه XML) إلى Comment الأوَّل. وكما ذكرنا بالأعلى فإنَّ مُكوِّن Comment سيعمل على الوصول إلى هذه الخصائص من خلال this.props.author، وthis.props.children. إضافة MarkdownMarkdown هي طريقة بسيطة لتهيئة مُضمّنة inline لنصِّك. على سبيل المثال، احاطة النص بعلامة النجمة (*) سيقوم بتأكيده. أولًا، أضِف مكتبة الطرف الثالث marked إلى تطبيقك. Marked هي مكتبة JavaScript تقوم بأخذ نص Markdown وتُحوِّله إلى صيغة HTML خام. هذا الأمر يتطلَّب وسم سكربت في قسم head (قُمنا بادراجه بالفعل في أرضيَّة React): <!-- index.html --> <head> <title>Hello React</title> <script src="https://fb.me/react-0.13.3.js"></script> <script src="https://fb.me/JSXTransformer-0.13.3.js"></script> <script src="https://code.jquery.com/jquery-2.1.3.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/0.3.2/marked.min.js"></script> </head>سنقوم بعد ذلك بتحويل نصّ التَّعليق إلى Markdown ومن ثمَّ إخراجه: // tutorial6.js var Comment = React.createClass({ render: function() { return ( <div className="comment"> <h2 className="commentAuthor"> {this.props.author} </h2> {marked(this.props.children.toString())} </div> ); } });كل ما فعلناه هنا هو استدعاء مكتبة marked. نحتاج إلى تحويل this.props.children من نصّ React مُحاط إلى سلسلة خام يُمكن لمكتبة marked فهمها ولذلك فإننا نقوم بستدعاء دالَّة ()toString. لكن لدينا مشكلة وهي أنَّه يتمّ إظهار وسوم HTML الموجودة في التَّعليقات بالشكل التَّالي في المُتصفح: This is another comment. هذا الأمر هو حماية React لك من هجوم XSS. هُناك طريقة للالتفاف على ذلك، ولكنَّ إطار العمل يُحذِّرُكَ من استخدامها: // tutorial7.js var Comment = React.createClass({ render: function() { var rawMarkup = marked(this.props.children.toString(), {sanitize: true}); return ( <div className="comment"> <h2 className="commentAuthor"> {this.props.author} </h2> <span dangerouslySetInnerHTML={{__html: rawMarkup}} /> </div> ); } });هذه الشَّفرات هي API خاصّ والذي عمدًا يجعل من الصَّعب إدراج شفرات HTML خام، في حالتنا بالنِّسبة لمكتبة marked فإنَّنا سنقوم بالاستفادة من هذا المنفذ الخلفيّ. تذكَّر: باستخدامك لهذه الميزة فإنَّك تعتمد على مكتبة marked أن تكون آمنة. نقوم في هذه الحالة بتمرير sanitize: true التي تطلب من مكتبة marked تنفيذ أي وسم HTML في المصدر بدلًا من تمريره دون تغيير. إضافة نموذج البياناتحتَّى الآن فإنَّنا نقوم بإدراج تعليقات مُباشرة في شفرات المصدر. بدلًا من ذلك، سنقوم بتصيير بضع من بيانات JSON في قائمة التعليق. يأتي هذا من الخادم في نهاية المطاف، ولكن في الوقت الراهن سنكتبها نحن في المصدر: // tutorial8.js var data = [ {author: "Pete Hunt", text: "This is one comment"}, {author: "Jordan Walke", text: "This is *another* comment"} ];الآن نحنُ بحاجة إلى إدخال هذه البيانات في مُكوِّن CommentList بطريقة نموذجيِّة. قُم بتعديل CommentBox واستدعاء ()React.render لتمرير هذه البيانات إلى CommentList عن طريق الخصائص props: // tutorial9.js var CommentBox = React.createClass({ render: function() { return ( <div className="commentBox"> <h1>Comments</h1> <CommentList data={this.props.data} /> <CommentForm /> </div> ); } }); React.render( <CommentBox data={data} />, document.getElementById('content') );الآن حيثُ أنَّ البيانات مُتاحة في CommentList، سوف نقوم بتقديم التَّعليقات بطريقة ديناميكيَّة: // tutorial10.js var CommentList = React.createClass({ render: function() { var commentNodes = this.props.data.map(function (comment) { return ( <Comment author={comment.author}> {comment.text} </Comment> ); }); return ( <div className="commentList"> {commentNodes} </div> ); } });هذا كل شيء. الاستدعاء من الخادمسنعمل الآن على استبدال البيانات الثَّابتة ببعض البيانات الديناميكيَّة من الخادم. يتمّ ذلك بإزالة خاصيَّة البيانات data prop واستبدالها بعنوان URL للجلب: // tutorial11.js React.render( <CommentBox url="comments.json" />, document.getElementById('content') );هذا المُكوِّن مُختلف عن المُكوِّنات السَّابقة حيثُ أنَّه سيضطر إلى إعادة تصيير نفسه. لن يحتوي المُكوِّن على أيّ بيانات إلى أن يعود الطَّلب من الخادم، في هذه الحالة قد يحتاج المُكوِّن إلى تصيير بعض التَّعليقات الجديدة. الحالة التفاعليَّةقام كلّ مُكوِّن حتَّى الآن على أساس خصائصه بتصيير نفسه مرة واحدة. الخصائص props ثابتة: يتمّ تمريرها من المُكوِّن الأساسي و”مملوكة” من قبل المُكوِّن الأساسي كذلك. لتنفيذ التَّفاعلات، فإنَّنا نُقدِّم حالة قابلة للتغيير إلى المُكوِّن. حالة this.state هي خاصَّة بالمُكوِّن ويُمكن تغييرها من خلال استدعاء ()this.setState يقوم المُكوِّن بإعادة تقديم نفسه عند تحديث الحالة. وظائف ()render مكتوبة إلزاميًّا كدوال this.props وthis.state. يضمن إطار العمل أن تكون واجهة المستخدم دائمًا مُتَّسِقَة مع المُدخَلات. عندما يقوم الخادم بجلب بيانات سنقوم نحن بتغيير بيانات التعليق لدينا. لنُضيف الآن مصفوفة من بيانات التَّعليق كحالة للمُكوِّن CommentBox: // tutorial12.js var CommentBox = React.createClass({ getInitialState: function() { return {data: []}; }, render: function() { return ( <div className="commentBox"> <h1>Comments</h1> <CommentList data={this.state.data} /> <CommentForm /> </div> ); } });يتمّ تنفيذ دالَّة ()getInitialState مرَّة واحدة فقط خلال دورة حياة المُكوِّن كما أنَّها تبدأ الحالة الأوليَّة للمُكوِّن. تحديث الحالةنُريد عند إنشاء المُكوِّن لأوَّل مرَّة أن نحصل على (GET) بعض بيانات JSON من الخادم وتحديث الحالة لتعكس أحدث البيانات. هذا من شأنه أن يكون نقطة نهاية ديناميكيَّة لو كان الأمر في تطبيق حقيقي، ولكن سنستخدم لهذا المثال ملف JSON ثابت لابقاء الأمور بسيطة: // tutorial13.json [ {"author": "Pete Hunt", "text": "This is one comment"}, {"author": "Jordan Walke", "text": "This is *another* comment"} ]سنقوم باستخدام مكتبة jQuery للمساعدة في عمل طلب غير متزامن asynchronous request إلى الخادم. مُلاحظة: حيثُ أنَّ هذا الأمر أصبح تطبيق AJAX فإنَّك سوف تحتاج لتطوير تطيبقك باستخدام خادم ويب بدلًا من أن ملف موجود في نظام ملفاتك. قدَّمنا -كما هو مذكورٌ بالأعلى- العديد من الخوادم التي يُمكنكَ استخدامها على GitHub. توفر تلك الخوادم التأدية الوظيفيَّة التي تحتاجها لبقيَّة هذا الدرس. // tutorial13.js var CommentBox = React.createClass({ getInitialState: function() { return {data: []}; }, componentDidMount: function() { $.ajax({ url: this.props.url, dataType: 'json', cache: false, success: function(data) { this.setState({data: data}); }.bind(this), error: function(xhr, status, err) { console.error(this.props.url, status, err.toString()); }.bind(this) }); }, render: function() { return ( <div className="commentBox"> <h1>Comments</h1> <CommentList data={this.state.data} /> <CommentForm /> </div> ); } });وظيفة componentDidMount هنا هي وظيفة تُستدعى تلقائيًا بواسطة React عندما يتمّ تصيير مُكوِّن. مفتاح التَّحديثات الديناميكيَّة هو استدعاء دالَّة ()this.setState. نقوم باستبدال مصفوفة التَّعليقات القديمة بواحدة جديدة من الخادم وتقوم واجهة المستخدم بتحديث نفسها تلقائيًا. بسبب هذا التفاعل، يُعتبر التغيير لإضافة تحديثات حيَّة طفيفًا. سوف نستخدم أسلوب بسيط في هذا الدَّرس ولكن لكَ الحُريَّة في استخدام WebSockets أو غيرها من التكنولوجيَّات. // tutorial14.js var CommentBox = React.createClass({ loadCommentsFromServer: function() { $.ajax({ url: this.props.url, dataType: 'json', cache: false, success: function(data) { this.setState({data: data}); }.bind(this), error: function(xhr, status, err) { console.error(this.props.url, status, err.toString()); }.bind(this) }); }, getInitialState: function() { return {data: []}; }, componentDidMount: function() { this.loadCommentsFromServer(); setInterval(this.loadCommentsFromServer, this.props.pollInterval); }, render: function() { return ( <div className="commentBox"> <h1>Comments</h1> <CommentList data={this.state.data} /> <CommentForm /> </div> ); } }); React.render( <CommentBox url="comments.json" pollInterval={2000} />, document.getElementById('content') );كل ما فعلناه هنا هو نقل استدعاء AJAX إلى وظيفة مُستقلَّة واستدعائها عند تحميل المُكوِّن الأوَّل واستدعائها كلّ ثانيتين بعد ذلك. حاول تشغيل هذا في مُتصفِّحك وتغيير ملف comments.json. في غضون ثانيتين ستظهر لكَ التغييرات. إضافة تعليقات جديدةحان الآن الوقت لبناء النموذج. على مُكوِّن CommentForm أن يسأل المُستخدم عن اسمه ونصّ التَّعليق، ثم يقوم بإرسال طلب إلى الخادم لحفظ التعليق. // tutorial15.js var CommentForm = React.createClass({ render: function() { return ( <form className="commentForm"> <input type="text" placeholder="Your name" /> <input type="text" placeholder="Say something..." /> <input type="submit" value="Post" /> </form> ); } });دعونا نجعل النموذج متجاوب. عندما يقوم المُستخدم بإرسال النَّموذج، يجب علينا مسحه clear، تقديم طلب إلى الخادم، ثُمَّ تحديث قائمة التعليقات. للبدء في تنفيذ هذا، سقوم بالاستماع إلى حدث ارسال النَّموذج ومسحه. // tutorial16.js var CommentForm = React.createClass({ handleSubmit: function(e) { e.preventDefault(); var author = React.findDOMNode(this.refs.author).value.trim(); var text = React.findDOMNode(this.refs.text).value.trim(); if (!text || !author) { return; } // TODO: send request to the server React.findDOMNode(this.refs.author).value = ''; React.findDOMNode(this.refs.text).value = ''; return; }, render: function() { return ( <form className="commentForm" onSubmit={this.handleSubmit}> <input type="text" placeholder="Your name" ref="author" /> <input type="text" placeholder="Say something..." ref="text" /> <input type="submit" value="Post" /> </form> ); } });1- الأحداث Eventsتقوم React بإرفاق مُعالجات الحدث في المُكوِّنات باستخدام اتفاقية التَّسمية camelCase. نقوم بإرفاق مُعالج onSubmit إلى النَّموذج الذي يعمل على مسح حقول النَّموذج عند إرساله مع إدخال صحيح. عليكَ استدعاء ()preventDefault بالحدث لمنع الإجراء الافتراضي للمُتصفِّح من اعتماد النَّموذج. 2- المراجع Refsنستخدم خاصيَّة ref لتعيين اسم للمُكوِّن الفرعي وthis.refs لارجاع المُكوِّن. يمكن أن نستدعي (React.findDOMNode(componentعلى مُكوّن للحصول على عنصر نموذج كائن مُستند المُتصفِّح الأصلي. 3- نداءات الخصائصعندما يُرسِل المُستخدم التَّعليق، فإنَّنا سوف تحتاج إلى تحديث قائمة التَّعليقات لتشمل التَّعليق الجديد. من الطبيعي أن تفعل كل هذا في مُكوِّن CommentBox حيث أنَّ المُكوِّن يمتلك الحالة التي تُمثِّل قائمة التَّعليقات. نحن بحاجة لتمرير البيانات من نُسخة المُكوِّن الفرعي الاحتياطيَّة إلى المُكوِّن. يتمّ فعل هذا في وظيفة render الخاصَّة بالأب عن طريق تمرير رد نداء جديد (handleCommentSubmit) في الابن ثُمَّ الزامها لحدث الابن onCommentSubmit. كُلَّما تم تشغيل الحدث، سيُنفَّذ الاستدعاء: // tutorial17.js var CommentBox = React.createClass({ loadCommentsFromServer: function() { $.ajax({ url: this.props.url, dataType: 'json', cache: false, success: function(data) { this.setState({data: data}); }.bind(this), error: function(xhr, status, err) { console.error(this.props.url, status, err.toString()); }.bind(this) }); }, handleCommentSubmit: function(comment) { // TODO: submit to the server and refresh the list }, getInitialState: function() { return {data: []}; }, componentDidMount: function() { this.loadCommentsFromServer(); setInterval(this.loadCommentsFromServer, this.props.pollInterval); }, render: function() { return ( <div className="commentBox"> <h1>Comments</h1> <CommentList data={this.state.data} /> <CommentForm onCommentSubmit={this.handleCommentSubmit} /> </div> ); } });سوف نستدعي الآن النِّداء من CommentForm عندما يقوم المُستخدم بإرسال النَّموذج: // tutorial18.js var CommentForm = React.createClass({ handleSubmit: function(e) { e.preventDefault(); var author = React.findDOMNode(this.refs.author).value.trim(); var text = React.findDOMNode(this.refs.text).value.trim(); if (!text || !author) { return; } this.props.onCommentSubmit({author: author, text: text}); React.findDOMNode(this.refs.author).value = ''; React.findDOMNode(this.refs.text).value = ''; return; }, render: function() { return ( <form className="commentForm" onSubmit={this.handleSubmit}> <input type="text" placeholder="Your name" ref="author" /> <input type="text" placeholder="Say something..." ref="text" /> <input type="submit" value="Post" /> </form> ); } });الآن وبعد أن أصبح النِّداء في مكانه الصحيح، كل ما علينا القيام به هو الإرسال إلى الخادم وتحديث القائمة: // tutorial19.js var CommentBox = React.createClass({ loadCommentsFromServer: function() { $.ajax({ url: this.props.url, dataType: 'json', cache: false, success: function(data) { this.setState({data: data}); }.bind(this), error: function(xhr, status, err) { console.error(this.props.url, status, err.toString()); }.bind(this) }); }, handleCommentSubmit: function(comment) { $.ajax({ url: this.props.url, dataType: 'json', type: 'POST', data: comment, success: function(data) { this.setState({data: data}); }.bind(this), error: function(xhr, status, err) { console.error(this.props.url, status, err.toString()); }.bind(this) }); }, getInitialState: function() { return {data: []}; }, componentDidMount: function() { this.loadCommentsFromServer(); setInterval(this.loadCommentsFromServer, this.props.pollInterval); }, render: function() { return ( <div className="commentBox"> <h1>Comments</h1> <CommentList data={this.state.data} /> <CommentForm onCommentSubmit={this.handleCommentSubmit} /> </div> ); } });تحديثات مُحسَّنةمشروعنا الآن كامل الوظائف ولكن من المُمل أن نقوم بانتظار الطَّلب حتَّى يكتمل قبل ظهور تعليقك في القائمة. يُمكننا إضافة هذا التَّعليق إلى القائمة لجعل التطبيق يعمل بشكلٍ أسرع. // tutorial20.js var CommentBox = React.createClass({ loadCommentsFromServer: function() { $.ajax({ url: this.props.url, dataType: 'json', cache: false, success: function(data) { this.setState({data: data}); }.bind(this), error: function(xhr, status, err) { console.error(this.props.url, status, err.toString()); }.bind(this) }); }, handleCommentSubmit: function(comment) { var comments = this.state.data; var newComments = comments.concat([comment]); this.setState({data: newComments}); $.ajax({ url: this.props.url, dataType: 'json', type: 'POST', data: comment, success: function(data) { this.setState({data: data}); }.bind(this), error: function(xhr, status, err) { console.error(this.props.url, status, err.toString()); }.bind(this) }); }, getInitialState: function() { return {data: []}; }, componentDidMount: function() { this.loadCommentsFromServer(); setInterval(this.loadCommentsFromServer, this.props.pollInterval); }, render: function() { return ( <div className="commentBox"> <h1>Comments</h1> <CommentList data={this.state.data} /> <CommentForm onCommentSubmit={this.handleCommentSubmit} /> </div> ); } });ختامًاانتهيتَ لتوك من إنشاء مربع تعليقات في بضع خطوات بسيطة. يُمكنك الآن التَّعرُّف على المزيد حول أسباب استخدام React، أو الخوض في مراجع API وبدء العمل. ترجمة -وبتصرّف- للمقال: Tutorial | React.
    1 نقطة
  2. سنتعلم في هذا الدرس كيفية تصميم تنين ينفث النار باستخدام مجموعة من الصور والتأثيرات باستخدام برنامج فوتوشوب، حيث بإمكانك تصور اي منظر يخطر على البال وتركيب مجموعة من الصور لتحصلوا على لوحة رائعة متناسقة الألوان، أتمنى أن يعجبكم الدرس . هذه هي الصورة التي سنحصل عليها في نهاية الدرس: قبل البدء أدعوكم لتحميل الملفات المرفقة لهذا الدرس. افتح مشروعا جديدا على Photoshop بالإعدادات التالية: الدقة: 3600x2500pixels.الأبعاد: Resolution 720Dpi.نمط الألوان: Color Mode RVB8bit.نجلب الصورة التالية للمشروع – الصورة مرفقة مع الحزمة-: باستعمال الاختصار Ctrl+T للتحكم في الصورة، نديرها كما هو مبين: ثم الصورة الأخرى الخاصة بالسُحب: باستخدام أداة الممحاة ذات الاختصار (E) نزيل جنيات الصورة الثانية لنحصل على الشكل: نعيد نفس العملية –نضيف الصورة ثم نستعمل الممحاة- كما هو مبين: في طبقة جديدة - نضيفها باستعمال الاختصار Ctrl+Shift+N- نرسم بأداة الفرشاة (B) باللون الأسود على جوانب الصورة مع الإشارة إلى خفض قيمة الشفافية إلى 25: نضيف طبقة جديدة وبنفس الأداة السابقة - الفرشاة- نرسم باللون #19292c في وسط الصورة : نغير في خصائص الدمج إلى القيمة vivid Light و الشفافية إلى 35: نضيف طبقة من نوع Gradient Map من القائمة : Menu > Layer > New Layer Adjustment > Gradient Map مع نغير خصائص الدمج إلى القيمة Hard Light: نضيف طبقة أخرى من نوع Gradient Map: في طبقة جديدة وباستعمال أداة الفرشاة نضيف الكوكب كما هو مبيّن في الصورة – الفرش محملة في الحزمة-: مع بعض النجوم: من نافذة خصائص الدمج نغير ما يلي: نضيف صورة التنين للمشروع: نغير خصائص الدمج الخاصة بصورة التنين: نستعمل أداة الإضاءة ذات الاختصار(O)- نضيء بعض المناطق ونُظلم أخرى-: ثم من القائمة: Menu > Filter>Blur > Motion Blur مع تغيير خصائص الدمج إلى القيمة Color Dodge: في طبقة جديدة بأداة الفرشاة باللون الأحمر وشفافية بقيمة 80 نضفي اللون الأحمر على العينين: نجلب صورة اللهب للمشروع: نغير خصائص الدمج إلى القيمة Screen: ثم إلى القائمة: Menu > Filter > Blur > Motion Blur نغير خصائص الدمج إلى القيمة Color Dodge: يمكنك الاستفادة من هذه الصور المرفقة في الحزمة لصنع لهب النار: ننشئ طبقة جديدة وبفرشاة ذات اللون #f86300: نغير خصائص الدمج إلى القيمة Linear Burn: ثم ننشئ طبقة من نوع Curve من القائمة: Menu > Layer > New Layer Adjustment > Curve ثم من القائمة: Menu > Layer > New Layer Adjustment > Photo Filter ننشئ طبقة هي دمج لجميع الطبقات وذلك بالاختصار Ctrl+Alt+Shift+E: من القائمة: Menu > Filter > Blur > Radial Blur وهاهي ذي النتيجة النهائية لهذا الدرس: ترجمة -وبتصرّف- للدّرس: Un dragon cracheur de feu avec photoshop.
    1 نقطة
  3. غالبا ما ينظر الناس إلى موظفي "الدعم الفني" بشكل يشبه نظرتهم للكائنات أسفل السلّم الغذائي، سيل من المشكلات والمتاعب لا أكثر، من تلك النظرات على سبيل المثال: مهمّة الدعم الفني التعامل مع العملاء الحمقى.على موظفي الدعم الفني الردّ على المكالمات؛ إنها وظيفة لا يقبل بها حتى مندوبي المبيعات.موظفو الدعم الفنّي يتعاملون بهدوء مع غضب العملاء، في حين أنهم لا يملكون حلًا حقيقيًا لمشاكلهم. يبدو هذا محبطًا للغاية، إذ كيف يمكنك التعامل في موقف يضعك أمام عميل محتقن غضبًا، ورغم قدرتك على مساعدته وحل مشكلته إلا أن صلاحياتك الإدارية لا تسمح لك بذلك؟ البعض قد يرى أنها وظيفة سيئة لشخص عاطل عن العمل لم تُعرض عليه فرصٌ لأعمالٍ أفضل، هل توافق ذلك؟ إذا كانت هذه هي رؤيتك وتصوّرك عن وظيفة الدعم الفني، فهو تصوّر سلبيّ للأسف، مما يعني أنك تفوّت على نفسك أسلوبًا مهمًا في التسويق، تطوير المنتجات، وزيادة المبيعات. الوجه غير المُتوقّع لشركتكهل سبق وتعرضت لموقف ما شعرت فيه بالتناقض وعدم الانسجام ما بين صوت أحدهم وصورته، كما لو أنك كنت تتوقع صوتًا آخر له، أو صورة تناسب الصوت أكثر؟ ديفيد بيكهام لاعب الكرة الإنكليزي مثال واضح على هذا؛ القائد السابق لمنتخب إنكلترا، وزوج المغنية ومصممة الأزياء فيكتوريا بيكهام، كل هذه الكاريزما ستتلاشى عندما يفتح فمه ويبدأ بالكلام، فصوته غير متوقع على الإطلاق، إنها صدمة ستبقى مطبوعة في ذاكرتك! موقع شركتك على الإنترنت يعكس الصورة الأنيقة لك، لكن ما الذي سيحدث عندما يصدر عن الشركة ما يتناقض وصورتها الجميلة تلك؟ ماذا يحدث عندما يتصل أحدهم بمندوبي الدعم الفني؟ بالنسبة لمعظم زبائنك، فموظف الدعم الفني هو الواجهة البشرية الوحيدة التي سيتعاملون معها، وهو من سيؤكّد الصورة البرّاقة للشركة أو سينفيها، فهل ستوظف لهذه المهمة الحساسة الأشخاص الأقل كفاءةً، والأسوأ خُلقًا، بأقل الأجور الممكنة؟ الدعم الفني سرّ المبيعات العاليةلقد حققنا ملايين الدولارات في شركة Smart Bear من خلال المبيعات للأفراد والشركات ومن دون القيام بـ "مبيعات" فعلًا، على الأقل لو ابتعدنا عن المفهوم التقليدي لكلمة مبيعات، والذي يعرف عادةً على أنه "مجموعة من العمليات والأشخاص والمدراء، تركز جميعها على زيادة الإيرادات في جداول زمنية ربع سنوية". لو سألني أحدهم؛ كيف حصلنا على صفقات تزيد على المئة ألف دولار دون بذل الكثير من الجهد أو الدخول في مراهنات متهورة؟ ببساطة: موظفو الدعم الفني لدينا كانوا البائعين! يمكنك القول بأنّ مهام موظفي الدعم الفني تقتصر بالرد على المكالمات والإجابة عن الأسئلة علاوةً على تهدئة الزبائن الغاضبين، لكن ذلك لن يحقق لك تغييرًا كبيرًا، في المقابل فإنني أرى أن مهمّة الدعم الفني الأساسيّة هي جعل الزبائن مبهورين بأداء موظفيك الرائع، الأمر الذي سيعود بالفائدة على منتجك ومبيعاتك بالتأكيد. (اقتبست هذه الفكرة من كاثي سيرا، حيث أراها تنطبق على الدعم الفني إضافةً لمطوري المنتجات). وهذا يعني ألّا تقتصر على مساعدة الزبائن في إيجاد أمر ما ضمن القوائم، بل اسألهم عما يحاولون القيام به لمساعدتهم في إنجاز المطلوب. لا تكتفي أيضًا بشرح خصائص المنتج بل ساعد العملاء للحصول على النتيجة. لا تتوقف عند الاعتذار لعدم وجود الميزة التي يرغبون بها بل ساعدهم بالالتفاف حول ذلك و إتمام المطلوب بدونها. أنت تعلم منتجك جيدًا وتعرف نوع المشكلات التي فيه بشكل يفوق الزبائن، لذا لن يكون من الصعب أن تجعل تجربتهم مع المنتج أكثر نجاحًا عقب اتصالهم وتعطي تلك المكالمة قيمة مضافة. ما تقوم به من تلبية زبائنك وتمكينهم من حل المشكلات وإنجاز المطلوب ليس مهمًا لمنتجك فحسب، إنه يشمل شركتك أيضًا. أعط زبونك تجربة مذهلة مع المنتج، وهو سيبذل المال بحيث يبقى مستمرا مع هذه التجربة الرائعة. هكذا تضاعف مبيعاتك. مفاجأة سارّةللأسف فإن الصورة النمطية التي يمتلكها معظمنا عن موظفيّ الدعم الفني سلبية، هذه بعض من تجارب الناس معهم: اسأل الدعم الفني عن طريقة تغيير الخط، وسيطلبون منك إعادة إقلاع حاسوبك الشخصي.التمس من الدعم الفني تغيير العنوان الخاص بفواتيرك، وسيعرضون عليك ثلاث خدمات لا تحتاج أيًا منها.الاتصال بالدعم الفنّي يحتاج خريطة مع نظام تحديد مواقع لتستطيع التنقل في متاهات الخيارات والقوائم، المكالمات قيد الانتظار، وكتابة رقم حسابك ثلاث مرات "لأغراض أمنية"، وكأن من سيسرق رقم حسابك عاجز عن كتابته لثلاث مرات.دعنا نستفد من هذه الصورة السلبية لموظفي الدعم الفني، فعندما يتوقّع عملاؤك خدمات ذات مستوى متدنّ، ويحصلون على خدمة عالية الجودة، فستحصد نقاط قوّة نوعية، كأن يقوم المستخدمون بكتابة تغريدات حول خدماتك، أو يجرّب آخرون طلبها للمرة الأولى، وذلك بسبب الدعم الفني المتميز الذي تقدمه، كما أن الزبائن لا يكتفون بمتابعة تغريداتك أحيانًا وإنما يشجّعون متابعيهم على فعل ذلك أيضًا. مهلًا، هل لاحظت ذلك؟ هكذا يصبح الدعم الفنّي أفضل حملة إعلانية عبر وسائل التواصل الاجتماعي، بل قد يكون برنامجًا دعائيًا أكثر فاعلية من تشغيل موظفين مناوبين لنشر إعلانات لك هنا وهناك. هل يدهشك هذا؟ يقال "قدّم وعودا أقل من استطاعتك، وأعط خدمات أكثر من المتوقع"، الدعم الفني الخارق هو الأفضل بالطبع، لكن مجرّد تصرّفك بشكل بشري سيجعلك في المقدّمة حتما، حتى لو اكتفيت بالرد على رسائل البريد الإلكتروني دون استخدام مجيب تلقائي ستحرز تقدمًا بشكل ملحوظ. لماذا نفوّت فرصة سهلة كهذه في إدهاش العملاء؟ أليستْ "مفاجأة سارة" ونادرة في مجال العمل التجاري؟ ألستَ مهتما بأن تصبح شركتك معروفة كما الآخرين؟ الطريقة الأسهل لتخرج من مقر الشركة، بينما لا تزال في الداخلتضج الإنترنت بمقولة ستيف بلانك -صاحب منهجية تنمية العميل- والتي يتحدث فيها أن كل ما تحتاج معرفته عن عملائك موجود خارج مقر الشركة، ما يعني أن تنمية العميل الفعلية لا تتحقق دون الحديث المباشر مع الناس، التعرف على مشاكلهم عن قرب، مراقبة انفعالات وجوههم أثناء تقديم عروضك وأعمالك. في الحقيقة أجزم أن تنمية العميل ليست ما نمارسه في جلسات العصف الذهني على لوح أبيض في قاعة الاجتماعات، أو إضاعة الوقت حول حجم الخط المناسب في العروض التقديمية. على الرغم من ذلك، فإنه من الصعوبة بمكان تخصيص ميزانية عالية للتنقل لا سيما بالنسبة لمن لا يزالون في البدايات محاولين بناء عملهم الخاص، أو لأولئك الذين يعتمدون في عملهم على الإنترنت، بالتأكيد عليك أن تحاول بكل جهدك لأن الأمر يستحق، لكن ماذا عن الـ 94% المتبقية من وقتك، وهو الوقت الذي تمضيه في شركتك، خلف مكتبك؟ ثمّة أمور لا ينبغي أن نفرط بها، أعط الدعم الفني الأولوية الثانية هنا، الدعم الفني يوجد حيث يشتكي الناس أمورًا لا تعمل في المنتج، ميزات مفقودة رغم أنهم يحتاجونها، حيرتهم وارتباكهم تجاه أمر ما، إن كتابة دليل الاستخدام وتبويب المشكلات لن يكون كافياً معظم الوقت. البصيرة تكمن في ما وراء الأسئلة. لنقل أن أحدهم اتصل بالدعم الفني مُرتبكًا حيال أمرٍ ما، المهمة الأولى لديك هي تهدئته بالطبع، لكن انتبه إلى أنك أمام فرصة هامة لتطوير منتجك، يمكنك أن تطرح الأسئلة التالية على نفسك في محاولة لتحسين المنتج: ما الذي سبب ارتباك الزبون في المقام الأول؟هل تبدو وجهة نظر العملاء مختلفة عن وجهة نظري؟هل تتناسب مصطلحاتنا مع الزبائن؟هل نستخدم تشابيه لغوية لا توصل المطلوب؟هل أحتاج لتركيز اهتمامي على تجربة المستخدم المبتدئ عوضًا عن المتقدم؟هذه الأسئلة تكتيكية نابعة من المشكلة الحالية التي نقف أمامها، ورغم أهميتها لكنها لا يجب أن تشغلنا عن أسئلة أكثر استراتيجية وأهمية: هل أوجدت هذه المشكلة صعوبة ما لدى الزبون لم أستطع معرفتها رغم قدرتي على حلها؟هل كان هناك سوء فهم أو لبس ما لدى العميل كان يتوجب عليّ أن أوليه اهتمامًا أكبر؟ هل توجد فكرة لإبداع منتج جديد في هذه المشكلة؟إذا كان العملاء يحاولون الحصول على ميزات غير موجودة في المنتج، هل كنت أستطيع أن أؤمن لهم ما يحتاجونه من البداية؟السؤال الأخير تحديدا هو ما جعل شركة Smart Bear ترى النور، إذا لم أولي اهتماما بما وراء أسئلة الزبائن، لم تكن لتقرأ هذه السطور، نعم، الأمر بهذه الجديّة! عليك الآن أن تعود إلى الوراء، منذ البداية وحتى اليوم لتراجع مئات الرسائل الإلكترونية من العملاء لتحدد كيف كانت تجربة الزبائن ومالذي كانوا يتوقعونه وتجيب عن باقي الأسئلة السابقة، وهذا ما يحتاج إلى تفكير وتحليل معمقين بعيدًا عن التقارير الموجزة والملخصات المؤتمتة. الدعم الفني هو أكثر الفرص القريبة والممكنة لتطوير منتجاتك، وأقربها نتيجةً من ضغط "المبيعات". هنا حيث يكتشف المستخدمون منتجك ويقدمون تقاريرهم عنه. هل ستسمع النصيحة، أم ستلقيها جانبا؟ ماذا بعد؟ما الذي يمكن أن يفعله الدعم الفني أيضًا فيما لو أوليته الاهتمام وأعطيته الصلاحيات التي يستحق؟ أم أنك تعتقد بأنني مخطئ فيما قلت، وتفضّل أن تولي الدعم الفني لموظفي دولار واحد لكل ساعة ليبعدوا عنك العملاء المزعجين؟ ترجمة -وبتصرّف- للمقال Tech Support *is* sales لصاحبه Jason Cohen.
    1 نقطة
  4. عندما تبدأ العمل ككاتب حر، قد تشتري اسم نطاق، ترفع موقعك إلى شبكة الإنترنت وتنتظر ليتهافت عليه العملاء، ولكن الوقت يمرّ دون أن يحدث أي شيء. هذا ما حدث معي، وعليه قمت بمراجعة كل ما كتبت في الموقع وعلمت أن هناك خطأ ما، فذهبت لمواقع التواصل الاجتماعي واستفسرت عن الأمر، وكنت على أهبة الاستعداد للتغيير من أجل زيادة الإنتاج والكسب. ولكن هل تعرف ماذا حدث بعد ذلك؟ لم يحدث شيء. في نهاية المطاف، راجعت ما كنت أفعله و حاولت جاهداً لإيجاد مواضع الخطأ، وأخيراً اعترفت لنفسي، فالخطأ كان مؤلماً، إن موقعي كان شبه طارد للعملاء، وليس فيه عناصر جاذبة. إذا كنت كاتبًا مستقلًا وتحاول الحصول على عملاء، ولكن ذلك لم يحدث، فقد حان الوقت لمواجهة الحقيقة القاسية، وهي أن موقعك طارد لزواره، يحدث هذا حتى وإن كانت لديك الخبرات والمهارات الجاذبة، ولكن العملاء المحتملين ما إن يدخلوا موقعك الخاص حتى يولوا مُدبرين. مع أخذ ما سبق بعين الاعتبار، سأحاول وضع الخطوط العريضة للأسباب التي تجعل من موقعك موقعاً طارداً، ومن ثم أشرح ما يمكنك عمله لتغيير الأمور للأفضل. بدون موقع على الشبكةخطأ فادح، أتمنى أنك لم تقع فريسة له، ولكن الكثير من المستقلين ليس لديهم موقع على شبكة الإنترنت، فإذا كنت حتى الآن بدون موقع على الشبكة، فأنت تمارس العمل الحر بالطريقة الخطأ. أطلق موقعًا أو مدوّنة، ارفع إليه قالبًا جاهزًا، أو حتى استعن بمُصمّم لتصميم قالب لك، المهم يجب أن يكون له حضور على الإنترنت. ولكن ابتعد قدر المُستطاع عن المنصات التي تُقدم الاستضافة المجانية والتي توفر أدوات لبناء موقعك من دون برمجة،لأن الإعلانات التجارية التي تُظهرها هذه المواقع ستجعلك تبدو أقل مهنية، استثمر بعض المال لحجز استضافة، إذا كنت تريد أن تُظهر عملك أكثر احترافية. الفوضى البصريةوهي من أكبر المشاكل التي يعاني منها الكثير من المواقع، فقد تجعل من قراءة مُحتوى الموقع مهمّة صعبة جدًا، لوجود الكثير من النصوص المكدسة فوق بعضها البعض، وهناك الكثير من الصفحات التي لا داعي لها أيضاً، أو أن اختيارك للألوان اختيار غير موفق ومشتت لتفكير الزائر. فالعملاء المحتملين هم في عجلة من أمرهم في الغالب، فلا يحبذ معظمهم فكرة بذل مجهود كبير لقراءة كل النصوص الطويلة على موقعك، وبالتالي فالكرة في ملعبك الآن. فمن الأفضل دائماً: اعتماد البساطة في عرض المعلومات على الإنترنت.أن تكون الصفحات الرئيسية قليلة قدر الإمكان، تحمل عناوين واضحة، وسهلة التنقل فيما بينها.حاول جاهداً أن تكون الفقرات قصيرة، فكثير من الناس يقرأ بالمسح السريع للنص.ليتمكن العميل من العثور على المعلومة بسرعة، أجعل النص بلون غامق على خلفية بيضاء، وتأكد من وجود مساحات بيضاء أكثر من النص.أعمل على وضع الصور والرسوم بشكل مدروس وعند الحاجة إليها فقط وليس لملء الفراغات.صعوبة التواصل معكأحد أكبر الأخطاء التي يمكن أن ترتكبها على موقعك هو عدم توفير معلومات الاتصال بشكل مترافق مع الخدمات التي يمكن أن تقدمها، فقد تُكثر من كلمة "إذا" مثل: إذا كنت ترغب في الحصول على اتصال. إذا كان لديك مشكلة. إذا كنت تعتقد أنك بحاجة للمساعدة.وغيرها الكثير، ولكنك في المقابل لم تخبر العملاء المحتملين ما يجب عليهم القيام به بالضبط. قد تطرح عليهم الأسئلة ولكن تترك لهم مهمة البحث عن معلومات الاتصال للحصول على المزيد من المعلومات. فبدل من استعمال كلمة "إذا" وتترك للعميل يتخيل كيف يتصل، عليك أن تقول له ما يجب عليه القيام به بالضبط، على سبيل المثال: اتصل بي اليوم في الفترة بين كذا وكذا. يمكنك الاشتراك في قائمتي البريدية والحصول على التقرير الخاص بك مجاناً.وبعدها بشكل مباشر عليك إضافة معلومات الاتصال الخاصة بك. ويُفضل وجود رقم الهاتف في مقدمة معلومات الاتصال، ثم عنوانك البريدي، ولا تنتظر أن يقوم بملء نموذج الاتصال. لا بد أن تحتوي جميع الصّفحات نداء للإجراء call-to-action، بشكل يُسهّل على الزّائر للاتّصال بك بطريقة لا تتطلّب أي جهد من طرفه. الاستفاضة غير الضرورية في سرد المعلومات الشخصيةإذا انتابك شك حول أداء موقعك، وكنت تعتقد بأن هناك مُشكلَا فيه فأوّل ما يجب التّحقّق منه هو محتويات صفحة المعلومات الشخصية على الموقع، وطريقة سرد هذه المعلومات، لأن العميل المحتمل لن يطلب خدماتك بسبب قصّة حياتك ولكنه سيتعاقد معك إذا علم القيمة الحقيقية لما يمكن أن تقدمه له، وبالتالي فعندما تقوم بتجميع المحتوى لموقعك، تأكد من: التركيز على الزبائن وما يمكنك القيام به بالنسبة لهم.لا تكثر الحديث عن نفسك، اذكر القليل فقط (القدر الكافي الذي يُظهر جانبك الإنساني) حيث أن الإطناب سيُعطي الانطباع بأنك شخص مهووس بنفسه.لا تضع جميع الأعمال التي قمت بها، استعرض فقط أفضل العينات.حاول التركيز على المعلومات الأساسية ووضعها في الأعلى بشكل مرئي دون الحاجة للبحث المضني عنها.تزييف الحقائقعندما بدأت العمل كمستقل، أردت لموقعي أن يبدو أكثر مهنية وأكثر إثارة للإعجاب، لذلك كتبت بصيغة توحي بأنني جزء من فريق مؤسسة عريقة، ولم أدرك الخطأ الفادح الذي قمت به إلى أن تحدثت على الهاتف مع أحد العملاء وشرحت له أنني لا أستطيع القيام بالمهمة بالسرعة التي يطلبها لأنني وحدي، حيث أن الزبونة أرادت التعاقد معي على أساس الصيغة الملكية لكلمة "نحن" (والتي هي في حقيقة الأمر تتحدث عني وعن... قطتي) التي كانت واضحة في الموقع. لا حرج من استخدام صيغة جادة خاصّة إذا كانت هذه الصّيغة هي المُفضّلة لنوعية الزّبائن الذين تستهدفهم، لكن احذر من مغبة إظهار نفسك أكبر من حجمك الحقيقي، فقد يُعطي الأمر نتائج عكسية وستظهر بمظهر العامل الحُر الغبي. تجّنب الحديث عن نفسك بصيغة الغائب، أو أن تخلط ما بين صيغة المُتكلم والغائب معًا، تجّنب صيغة الجمع "نحن" وابتعد قدر الإمكان عن المُصطلحات الرّنانة واستبدلها بمُصطلحات أبسط. اكتب وكأنك تُخاطب عميلك مُباشرة، حدّثه مُباشرة وبكلمات بسيطة عن السّبب الذي يجعل من توظيفك هو الخيار الأنسب بالنّسبة له. لن يُساعد ذلك على جعلك موقعك يظهر بمظهر أفضل، بل سيُعطي الفرصة لزبائنك لمعرفة المزيد حولك ولزيادة فرص توظيفهم لك. حان الوقت لتصحيح الأمرإن أهم ما في الموضوع أن تدرك أن موقعك غير جاذب، وعندها فقط يمكنك العمل على تحديد مواقع الخلل فيه. ومع ذلك فمهمة إعادة صياغة كاملة للموقع ليست بالمهمة السهلة أبداً، وربما ستكون سببًا في صرفك النظر عن تغييره أو تأجيل هذه المهمة، يحدث ذلك حتى وإن كنت تعرف ما تريد فعله بالتحديد، فقد تجد نفسك تحدق في موقعك لمدى شهر وأنت على علم أنه غير جاذب، دون القيام بأي تغيير، لأنك لا تعلم من أين تبدأ. إذا أنتابك مثل هذا الشعور، فلا تحاول فعل كل شيء دفعة واحدة ولا أن تتجاهل المشكلة، ولكن أبدأ في التغييرات واحداً تلو الأخر حتى يتألق موقعك. وإليك بعض الأفكار التي قد تساعدك في ذلك: إقرأ النصوص الموجودة في موقعك بصوت عالِ، بذلك ستتمكن من معرفة الأماكن التي لا تتناسب وما ترُيد قوله وما يجب إبقاؤه وما يجب حذفه.اطلب من أحد أصدقائك الذين يعملون في مجال الكتابة والتّحرير، أن يطّلع على موقعك بهدف معرفة مدى سهولة قراءته.استخدم قالبًا جديداً يحتوي على المزيد من المساحات البيضاء، أو تواصل مع مصمم مواقع لمساعدتك في ذلك.حاول خفض ملف التعريف الخاص بك إلى فقرة أو اثنتين على الأكثر.أعد يومياً كتابة صفحة واحدة على الأقل من الصفحات القديمة على موقعك.أضف عنوان بريدك الإلكتروني إلى صفحة الاتصال الخاصة بك.اطلب من زملائك في المجال مراجعة عملك.إيجاد زبائن لك كمستقل هو في الغالب من أصعب التحديات، فلا تدع موقعك يجعلها أكثر صعوبة، خذ وقتاً كافياً للتأكد من سير موقعك، وأنه معك لا ضدك، وسيكون بذلك عما قريب أفضل مسوّق لك. هل تجد أي من هذه الأخطاء في موقعك؟ هل استخدمت أي من هذه النصائح لتجعل موقعك يزيد من تألقك؟ شاركنا أفكارك وتعليقاتك على الموضوع. ترجمة -وبتصرّف- للمقال: Why Your Freelance Website Stinks (Mine Did Too) and How to Fix It.
    1 نقطة
  5. تردني بين الحين والآخر أسئلة حول كيفيّة العمل في المنزل وكيف لي أن أُدير مشاريعي بجانب العائلة طوال اليوم (لدي ولدين الأوّل في عامه الثّالث والثّاني في عامه الأول فهما ليسا بعد بعمر الالتحاق بالمدرسة). أعلم أنّ هذا الموضوع لا يمت بصلة بعالم التّطوير والبرمجة، بل هو على صلة في كيفيّة إنجاز المهام على أتم وجه، وعليه ظننت أنّه من الجيّد مشاركة طريقتي في العمل على شكل تدوينة، وذلك لكي أحيل الآخرين إليها بهدف الإجابة إجابةً شافية ووافية عن كيفيّة إدارة بيئة العمل والوقت عند العمل من المنزل بدوامٍ كاملٍ. بيئة العمل (Environment)إن بيئة العمل هي خطٌ أحمر بالنسبة لي، فيجب أنّ تكون عبارة عن غرفة منعزلة ومُخصّصة للعمل، وتحتوي على جميع الأشياء الّتي قد أحتاجها، وتضمن لي تركيزي على عملي بعيدًا عن المُشتّتات، ويجب أنّ تتوفّر الغرفة على التّالي: مساحة عمل بسيطة، تحتوي على حاسب ووريقات لأسجل عليها بعض الملاحظات.القهوة، سواءً جاهزة أو آلة صنعها.نظام صوتيات مُحترَم.تلفاز، وهو للأيام الّتي أفضل بها أن تكون ضوضاء الخلفيّة (background noise) فلمًا قديمًا بدلًا من الاستماع إلى الصوتيات.أحب أيضًا الإضاءة الطبيعيّة، ولكنّي في بعض الأحيان أفضّل الظلّمة، فيوجد في غرفتي نافذتان، تكون الستائر مرفوعة في بعض الأوقات، وتكون مُغلقة في البعض الآخر، فالأمر يعتمد على مزاجي والحالة النفسيّة، ولكنّني مُتأكّد من تأثير الإضاءة على نفسيتي. التعامل مع التّشتّت (Interruptions)يقع مكتبي في الطابق الثاني من المنزل، وفي الزاوية البعيدة عن بقيّة أرجاء المنزل وما يمر به من أحداثٍ طوال اليوم، يُمكنني هذا الأمر من الاهتمام بمهامي الحاليّة، والتركيز أكثر بعيدًا عن الضوضاء. لا يكون الحال بهذه المثاليّة دائمًا، فبينما أكتب الآن، أستطيع سماع صوت أحد أولادي يلعب بألعابه في الطابق الأرضي للمنزل، ولا بأس في ذلك، فلا يوجد شيءٌ في الدنيا أجمل من أنّ تكون أبًا، وسماع صوت الأطفال يلعبون بين الفنيّة والأخرى ليس بالأمر الجَلل. وجدت صعوبة في التعامل مع التّشتّت دائمًا رغم ذلك، وهذه مشكلتي في الحقيقة وليس لها علاقة بأحد، ولذلك أحاول دائمًا إغلاق باب الغرفة، يدفع هذا الأمر زوجتي أو أولادي إلى الاستئذان قبل الدخول، مما يسمح لي بالتوقف عن ممارسة نشاطي والاهتمام بالأمور الطارئة. يحدث في بعض الأحيان وأن أترك باب الغرفة مفتوحًا، لكي أوضّح بأني مُتاح ويُمكن مقاطعتي، ويعتمد هذا الأمر على طبيعة العمل الّذي بين يدي، فعلى سبيل المثال عند تصفّح البريد الإلكتروني فلا بأس من مقاطعتي، ولكن عند كتابة شيفرة برمجيّة، أو عند التحدّث مع أحدهم هاتفيًّا أو عبر أحد برامج التواصل الصوتيّة، فمن الأفضل عدم مقاطعتي، وذلك لكي أصب كامل تركيزي على المُهمّة. التعامل مع التنبيهات (Notifications)أحاول دائمًا فصل جميع التنبيهات بشكل كامل عند حلول الساعة الخامسة مساءً، بمعنى آخر، لا بريد إلكتروني، لا رسائل نصيّة، لا تغريدات، ولا أي نوع من أنواع الاتصال، باستثناء القليل، سأتطرّق إليه لاحقًا. أحبّذ أنّ أكون ذلك الشخص الّذي يهتم بعائلته، ويفصل بين الوقت المُخصّص للعمل والوقت المُخصّص للعائلة، ففي نهاية المطاف، أنا أملك الوقت الموفّر من المواصلات اليوميّة بين المنزل ومكان العمل. تختلف الأمور بين الناس بطبيعة الحال، ولذلك ما سأقوم بمشاركته هو مُرتبط بأسلوب حياتي فقط، وليس بالضرورة أنّ يَنطبق مع الجميع: لا أملك تطبيقًا لتويتر على هاتفي أبدًا، بل هو مُنصّب على حاسوبي المكتبي فقط، وأقوم بتفحصه مرّات قليلة في اليوم.لا استخدم موقعي فيس بوك أو Instagram، بل اعتمد على زوجتي لتزويدي بأي شيء مُميّز أو مُرتبط باهتماماتي.قمت بإعداد البريد الإلكتروني على هاتفي، ولكنّي أقوم بتأجيل كل ما هو غير عاجل في جدول المهام إما إلى قائمة "غدًا" أو إلى قائمة "الأسبوع القادم".استخدم برنامج "Telegram" للتواصل مع الأقارب والأصدقاء، بحيثُ أستطيع الاستجابة إن كان الأمر جللًا، وفيما عداهم يتمّ تأجيل أمره إلى حين.احتفظ بجدول أعمالي ضمن تقويم/مُفكّرة مع تنبيهٍ لكل مُهمّة، وأتابع تنبيهات اليوم الحالي فقط لأعلم ما يجب فعله في هذا اليوم.لا أملك إلا القليل مما يربطني مع مجتمع الإنترنت ضمن أوقات الفراغ، ولكن هذا لا يمنع من وجود بعض الحالات الطارئة بين الحين والآخر، والّتي لا تَحتمل التأجيل، ولكن في مُعظم الأوقات، يَفي هذا الأسلوب من التنظيم بالغرض. يسمح لي هذا التنظيم بالتركيز فعليًّا على الأمور المُهمّة، في حياتي، ويسمح لي أيضًا بالاهتمام بأمور أخرى مثل كاميرتي/آلة التصوير لالتقاط جميع تلك اللحظات السعيدة مع عائلتي، بدلًا من إضاعة وقتي، ولنقل، على مواقع التواصل الاجتماعي مثل فيسبوك أو غيره. هذا أسلوبي فقطولكن الاختلاف هو سنّة الحياة، وكل ما سبق هو رأيٌ شخصيٌ فقط لا غير، ولا أريد التعميم بأي حالٍ من الأحوال، فعلى كل شخص معرفة ما يناسبه والتخطيط على هذا الأساس، وشاركت ما أقوم به على اعتبار أنّني قد سُئلت أكثر من مرّة حول الأمر. لم يبق لي سوى الختام، وكلي أملٌ منكم مشاركة تجربتكم في إدارة الوقت. ترجمة –وبتصرّف- للمقال Balancing Family and Work.
    1 نقطة
×
×
  • أضف...