Bootstrapはフロントエンドのフレームワークであり、Web開発者を解放するのに適したものです。 UIが非常にハイエンド、雰囲気があり、ハイエンドであることを示しています。理論的には、CSSのラインを書く必要はありません。適切な属性をタグに追加するだけです。
Knockoutjsは、JavaScriptが実装されたMVVMフレームワークです。とても良い。たとえば、リストデータ項目を追加または削減した後、コントロールフラグメント全体を更新したり、JSの追加と削除ノードを自分で書き留める必要はありません。構文定義を満たすテンプレートと属性を定義するだけです。簡単に言えば、データへのアクセスに注意を払う必要があります。
1。Nockout.jsの紹介
1。Nockout.jsおよびMVVM
今日、さまざまなフロントエンドフレームワークが圧倒的で眩しいです。プログラマーは本当に難しいので、学ぶべき無限のテクニックが常にあるとため息をつかなければならないことがあります。変身しない限り、いつ終了しますか!苦しみの海は無限であり、あなたが振り返るときそれが海岸であるかどうかはあなた次第です!
knockout.jsは、MVVMモードに基づく軽量のフロントエンドフレームワークです。それはどれほど軽いですか?公式ウェブサイトに表示されている最新バージョンv3.4.0によると、わずか22kbです。データモデルとインターフェイスDOMの間のバインディングを友好的に処理できます。最も重要なことは、その結合が双方向であることです。つまり、データモデルが変更された場合、インターフェイスDOMのデータもそれに応じて変更されます。逆に、インターフェイスDOMのデータが変更された場合、それに応じてデータモデルも変更されます。これにより、フロントエンドコードの量を大幅に削減し、インターフェイスを維持しやすくすることができ、多くのイベント監視データモデルとインターフェイスDOMの変更を記述する必要はなくなりました。ブロガーは、以下の使用例に基づいてこれら2つのポイントを説明します。
knockout.js公式ウェブサイト:http://knockoutjs.com
knockout.jsオープンソースアドレス:https://github.com/knockout/knockout
MVVMモード:これは、ユーザーインターフェイスを作成するための設計モデルです。 MVVMは3つのピース、つまりモデル、ビュー、ビューモデル、モデルはデータモデル、ビューは私たちのビューであり、ViewModelはビューモデルであり、データモデルとビューのDOM要素をバインドするために使用されます。 WPFとSilverlightを使用している場合、これが問題ではないはずです。それを使用していないことは問題ではありません。この記事を読んだ後、一般的な理解があります。
2。最も単純な例
一般的に言えば、Quanced.jsをゼロから使用する場合、少なくとも次の4つの部分を実行する必要があります
2.1。公式Webサイトにアクセスして、knockout.jsファイルをダウンロードし、[表示]ページに引用します。
<スクリプトsrc = "〜/scripts/knockout/knockout-3.4.0.min.js"> </script>
注:knockout.jsはjqueryサポートを必要としません。プロジェクトがjQuery関連操作を必要とする場合は、jqueryを参照してください。それ以外の場合は、上記のファイルのみを参照してください。
2.2。 ViewModelを定義します
ViewModelとは何ですか?実際、JSでは、JSONオブジェクトのように見えます。 ViewModelを定義します。
var myviewmodel = {name: "lilei"、職業: "ソフトウェアエンジニア"、};2.3。ビュービューでデータバインドにバインドするタグを定義します
<div> name:<label data-bind = "text:name"> < /label> <br /> profession:<入力型= "text" data-bind = "textinput:profession" /> < /div>
注:入力タグに対応するテキストにはテキストインプットが必要ですが、通常のタグのテキストのテキストが必要です。
2.4。結合を活性化します
上記の3つのステップを実行した後、ノックアウトのバインディングをアクティブにする必要があります
Ko.ApplyBindings(myviewmodel);
これらの4つの部分を実行することにより、最も単純なViewModelデータバインディングが基本的に実装されます。効果を得る:
十分に注意している場合は、ko.applybindings()メソッドに2つのパラメーターがあることがわかります。 1つ目は、バインドする必要があるビューモデルで、2番目のビューモデルは何ですか? ko.applybindings(myviewmodel); 2番目のパラメーターはオプションのパラメーターであり、ViewModelにバインドされたタグの範囲を表していることがわかります。たとえば、上記のコードを変更しましょう。
<div> name:<label id = "lb_name" data-bind = "text:name"> < /label> <br /> <br /> <input type = "text" data-bind = "textinput:profession" /> < /div> ko.applybindings(myviewmodel、document.getelementbyid( "lb_name");
結果を取得します:
これから、2番目のパラメーターがmyViewModelのアクション範囲を定義していることがわかります。つまり、ID = "LB_NAME"のラベルのみをバインドすることが有効になります。 2番目のパラメーターがDivなどのコンテナラベルである場合、バインディングの範囲がすべてdiv以下のサブラベルであることを意味します。
3。監視属性
上記の4つのステップの時点で、効果はわかりません。私たちが見ているのは、JSONオブジェクトのデータをHTMLタグにバインドするだけです。これを行うポイントは何ですか?単純な問題を複雑にしませんか?心配しないで、すぐに奇跡を目撃してください!上記のように、ノックアウトの最も重要な意味は双方向の結合にあります。では、双方向の結合を達成する方法は?答えは、属性の監視です。
ノックアウトでは、コアには3つの監視属性があります:観測可能性、依存装置、観測可能性。観察の意味は、観察と観察として翻訳されています。それが観測属性または観測属性であると言うのが不適切だと感じた場合、当面は監視属性と呼びます。
3.1。観測可能性:監視プロパティ
上記の例をこれに変更しましょう。
<head> <meta name = "viewport" content = "width = device-width"/> <title> index3 </title> <script src = "〜/scripts/jquery-1.9.1.min.js"> </scrip> <scrc = "〜/scripts/knockout/knockout-3.4.0.min.min.js"> </<> < data-bind = "text:name:name"> </label> <br/> profession:<input type = "text" data-bind = "textinput:frofess"/> </div> <div> <入力タイプ= "text" id = "txt_testobservable"/> </div> <script = "text/javascript"> // 1. ko.observable( "lilei")、職業:「ソフトウェアエンジニア」、}; // 2。バインディングKO.ApplyBindings(myViewModel); $(function(){// textChange event $( "#txt_testobservable"))。この文の意味は、ViewModelの名前のプロパティを監視プロパティに追加することです。名前プロパティは監視プロパティになる必要があります。魔法のことが起こります。 myviewmodelを書くときに見てみましょう。
名前は元のプロパティからメソッドに変更されました。つまり、ko.observable()が追加されると、対応するプロパティがメソッドになります。したがって、名前の値と割り当ては、myviewmodel.name()を使用して処理する必要があります。効果を見てみましょう:
コードの疑い:myviewmodel.name($(this).val());この文は、現在のテキストボックスの値を名前プロパティに割り当てます。インターフェイスは名前プロパティにバインドされるため、ラベルの値もそれに応じて変化します。または、TextChangeイベントを使用してこれを行うことができると言うでしょう。現在のテキストボックスの値がラベルタグに割り当てられている限り、この効果を達成できますが、これは何もありません。実際、執筆方法も目的を達成できますが、監視属性の重要性は、名前の値がどこでも変更されると、すべての場所のラベルタグに値を割り当てることなく、インターフェイスがそれに応じて変更されることです。 JSでは、myviewmodel.name()に焦点を合わせる必要があります。とても素晴らしいことではありません~~
3.2。 DependentObservables:依存関係のプロパティを監視します
上記の監視属性を読んだ場合、まだ満足していませんか?監視依存関係属性の使用を見てみましょう。
コードを変更して見てみましょう。
<head> <meta name = "Viewport" content = "width = device-width"/> <title> index3 </title> <script src = "〜/scripts/jquery-1.9.1.min.js"> </script> <src = "〜/scripts/knockout/nockout-3.4.0.min.js"> </spript> data-bind = "textInput:name" /> <br /> profession:<入力タイプ= "text" data-bind = "textinput:" /> <br /> />説明:<label data-bind = "text:des"> < /label> < /div> <"text /javascript"> // ko.observable( "lilei")、職業:ko.observable( "ソフトウェアエンジニア")、}; myviewmodel.des = ko.dependentobservable(function(){return "i am named-" + myviewmodel.name() + "、 - " + myviewmodel.profession();結合Ko.ApplyBindings(myViewModel); </script> </body>をアクティブにします効果を見てみましょう:
コードの疑い:監視依存関係属性ko.dependentObservserable()を追加することにより、DES属性の値を同時に名前と教授の変更に監視できます。それらのいずれかが変更された場合、DESバウンドタグは変更をトリガーします。これの最大の利点は、JSがDOMを操作する問題を回避することです。これは興味深いことです。
3.3。観察。アレイを監視します
上記の2つに加えて、KOはアレイオブジェクトの監視もサポートしています。例を見てみましょう:
<head> <meta name = "viewport" content = "width = device-width"/> <title> index3 </title> <script src = "〜/scripts/jquery-1.9.1.min.js"> </script> <scrc = "〜/scripts/knockout/nockout-3.4.0.min.js data-bind = "options:deptarr、optionstext: 'name'"> </select> </div> <div> <input type = "text" id = "txt_testobservable"/> <input type = "button" id = "btn_test" bulation名前: 'R&D部門'}、{id:2、name: 'Administrative Department'}、{id:3、name: 'Human Affairs Department'}]); var viewmodel = {deptarr:deptarr、}; {deptarr.push({id:i ++、name:$( "#txt_testobservable")。val()};});}); </script> </body>効果をチェックしてください:
コードの疑い:上記の方法ko.observablearray()は、配列オブジェクトの監視を追加します。つまり、JSのどこでも、アレイの変更がDeptarr配列オブジェクトに変更されている限り、UIはトリガーされて対応するものを提供します。注意すべきことの1つは、監視配列が実際に監視されている配列オブジェクト自体であり、配列オブジェクトの子オブジェクトプロパティの変更について監視できないことです。たとえば、クリックイベントをこれに変更します。
$(function(){$( "#btn_test")。効果:
これは、アレイ監視が実際に配列オブジェクト自体を監視し、配列内の要素の属性の変化を監視しないことを示しています。データ内のオブジェクトのプロパティの変更を実際に監視する必要がある場合は、データ内のオブジェクトのプロパティにko.observable()を使用する必要があり、2つが一緒に使用されます。興味があれば試すことができます。
4. KOの一般的なデータバインド属性
上記では、複数のデータバインド属性を使用したため、ノックアウトにはそのようなデータバインド属性がいくつありますか?ここでは、一般的に使用されるプロパティをリストします。
4.1。テキストとinputText
名前が示すように、テキストはテキストを意味します。このバインディング属性は、通常、<label>、<span>、<div>などのタグを使用してテキストを表示するために使用されます。もちろん、必要に応じて、このバインディングは任意のタグに使用できます。基本的に、それを使用することについて言うことは何もありません。 ko.observable()が使用されない場合、それは静的な結合であり、それ以外の場合は動的結合です。
入力タグのテキストであるinputTextは、入力タグの値属性に相当します。
<div> name:<label data-bind = "text:name"> </label> <br/> profession:<入力タイプ= "text" data-bind = "textinput:" profession "/> </div> //1.define viewmodelvar myviewmodel = {name:ko.observable(" lilei ")、Prosess:"ソフトウェアエンジニア "結合ko.applybindings(myviewmodel)を有効にします。4.2。価値
このバインディングプロパティは、通常、入力タグに使用されます。これは、基本的に上記の入力テキストに似ています。しかし、値はより標準化されています。
また、値で使用されるのは、パラメーターValueUpDateです。これは、値が更新されたときにインターフェイスが実行する操作を示します。 ValueUpDateの主な値には、Change/KeyUp/Keypress/AfterKeyDownなどが含まれます。テキストの変更、キーボードの縮小、キーボードの押し、キーボードの押し、キーボードの押しなどの値に対応するViewModelの値を示します。
name:<入力型= "Text" data-bind = "value:name、valueupdate: 'keyup'" /> <br /> var myviewmodel = {name:ko.observable( "lilei")、}; // 2。結合ko.applybindings(myviewmodel)を有効にします。上記のコードは、キーボードが閉じているときにテキストボックスの値属性とmyViewModelの名前属性が更新されることを示しています。
4.3。チェックしました
チェックされたバインディングは、通常、選択できるチェックボックス、ラジオ、およびその他のフォーム要素に使用され、対応する値はboolタイプです。価値の使用は基本的に似ているので、繰り返しません。
4.4。有効にする
バインディングを有効にすることは、一般にラベル要素を有効にするために使用され、一般にフォーム要素を有効および無効にするために使用されます。無効に反して、対応する値もブールタイプです。
<div> <入力タイプ= "TEXT" DATA-BIND = "ENABLE:ISMEN"/> </div> <script Type = "text/javascript"> // 1.define viewmodelvar myviewmodel = {name:ko.observable( "lilei")、職業:職業:ko.observable( "ソフトウェアエンジニア")、年齢:年齢: ko.observable(40)、ismen:ko.observable(true)}; // 2。バインディングKo.ApplyBindings(myViewModel); myViewModel.ismen(false); </script>をアクティブにしますiSmenプロパティがfalseになるため、対応するすべてのテキストボックスは無効なステータスを表示します。
4.5。無効
有効に反して、使用法は有効に類似しています。
4.6。オプション
上記では、選択タグのオプションのセットを表すSelectバインディングを使用するときにオプションが使用され、対応する値はこのドロップダウンボックスのデータソースを表す配列です。このデータソースの監視は、Observablearrayを使用して有効にできます。使用については上記を参照してください。
4.7.html
テキストバインディングは、実際にはタグInnertextの設定と値です。同様に、HTMLバインディングは、innerhtmlの設定と値でもあります。対応する値はHTMLタグです。
4.8。 CSS
CSSバインディングは、DOM要素に1つ以上のスタイル(クラス)を追加または削除することです。フォーマットを使用します:
<style type = "text/css">。testbold {background-color:powderblue;} </style> <div data-bind = "css:{testbold:myviewmodel.name()== 'lilei'}"> aaaaa </div> var myviewmodel = {name:ko.observable( "Lilei") ko.observable( "ソフトウェアエンジニア")、age:ko.observable(40)};このdivには、背景色が表示されます。
複数のスタイルを追加または削除する必要がある場合は、たとえば、少し変更するだけです。
<div data-bind = "css:{testbold:myviewmodel.name()== 'lilei'、testborder:myviewmodel.profession()== 'php Engineer'}"> aaaa </div>4.9。スタイル
CSS結合の関数がクラススタイルをタグに動的に追加または削除することである場合、スタイルバインディングの関数は、特定のスタイルをタグに動的に追加または削除することです。例えば:
<div data-bind = "css:{background-color:myviewmodel.name()== 'lilei'? 'red': 'white'}"> aaaa </div>複数を追加または削除する場合、CSSバインディングの使用方法
4.10、attr
ATTRバインディングは、主にタグに1つ以上の属性(カスタム属性を含む)を追加および削除するために使用され、CSSに似ています。
4.11。クリック
クリックバインディングとは、Clickイベント実行方法を対応するDOM要素に追加することを意味します。任意の要素で使用できます。
<div> <入力型= "ボタン"値 "値"バインディングクリック "data-bind =" click:clickfunc " /> < /div> var myviewmodel = {clickfunc:function(){alert(event.currenttarget).val();}); ko.applybindings(myviewmodel);Event.CurrentTargetは、現在クリックされているDOM要素を表します。簡単にするために、次のような匿名関数を直接使用してバインドします。
<div> <入力型= "button" value = "クリックバインディング" data-bind = "click:function(){alert( 'clicked');}" /> < /div>ただし、JSをHTMLに書き込むこの方法により、ブロガーが受け入れることが困難になり、特にクリックイベントのロジックが少し複雑な場合、維持することは比較的不便だと感じています。したがって、必要でない場合は、この匿名関数を直接記述することはお勧めしません。
4.12。その他
データバインドのすべてのバインディングについては、公式Webサイトで紹介を見ることができますが、ここには1つずつリストしません。必要なときは、公式ウェブサイトにアクセスしてチェックアウトしてください。公式ウェブサイトにリストされているすべてのバインディングを見てください。
5。JSONオブジェクトと監視属性間の変換と関係
さまざまな言語での直接的なプレゼンテーション方法を回避するために、一般に、フロントエンドとバックエンドと対話するときにJSON形式のデータを使用することがわかっています。 HTTPリクエストを通じてバックエンドから取得されたデータモデルを使用します。 KOの機能の一部を使用するには、これらの通常のデータモデルをKOの監視属性に変換する必要があります。逆に、KOの監視属性を使用し、これらの属性を通常のJSONデータに変換して背景に渡す必要がある場合があります。では、この変換を達成する方法は?
5.1。 jsonオブジェクトをviewmodelに変換します
たとえば、バックグラウンドからJSONオブジェクトを使用してから、それをViewModelに変換してから、インターフェイスDOMにバインドします。
$ .ajax({url: "/home/getData"、type: "get"、data:{}、success:function(data、status){var ojson = data;}});バックエンドにリクエストを送信し、JSONオブジェクトを取り、値をOJSONに割り当ててから、OJSONをViewModelに変換します。最も直感的な方法は、手動で変換することです。たとえば、これを行うことができます。
var myviewmodeljson = {deptname:ko.observable()、deptlevel:ko.observable()、deptdesc:ko.observable()}; ko.applybindings(myviewmodeljson);その後、Ajaxが要求した成功
成功:function(data、status){var ojson = data; myviewmodeljson.deptname(ojson.deptname); myviewmodeljson.deptlevel(ojson.detplevel); myviewmodeljson.deptdesc(ojson.deptdesc);}このようにして、手動で結合することにより、JSONオブジェクトのViewModelへの結合が実現されます。これを行うことの利点は柔軟性であり、不利な点は明らかであり、手動コードの量が大きすぎます。
幸いなことに、私たちの普遍的なオープンソースでは、より良い方法を思い付く人々が常にいます。 knockout.mappingコンポーネントを使用して、インターフェイスJSONオブジェクトをViewModelに変換するのに役立ちます。
ノックアウト。オープンソースアドレスのマッピング:ダウンロード
それがどのように使用されるか、または上記の例を簡単に見てみましょう。 ViewModelの定義を実装する必要はありません。まず、knockout.mapping.jsを参照する必要があります
<script src = "〜/scripts/knockout/knockout-3.4.0.min.js"> </script> <script src = "〜/cripts/knockout/extensions/knockout.mapping-latest.js"> </script>
注:ここでは、knock.mapping-lastest.jsはknockout-3.4.0.min.jsの後ろに配置する必要があります。
次に、成功関数で直接使用します
成功:function(data、status){var myviewmodeljson2 = ko.mapping.fromjs(data); ko.applybindings(myviewmodeljson2);}効果を見てみましょう:
コードの疑い:ajax要求を介してバックグラウンドから取得されたJSONオブジェクトは、ko.mapping.fromjs()を介してviewmodelに便利に変換されます。シャープではありませんか?もちろん、この使用法に加えて、既存のViewModelを更新して、次のように使用することもできます。
var myviewmodeljson = {deptname:ko.observable()、deptlevel:ko.observable()、deptdesc:ko.observable()}; ko.applybindings(myviewmodeljson); {}、success:function(data、status){ko.mapping.fromjs(data、myviewmodeljson)}});});成功して、データの価値に従ってMyViewModeljsonのViewModelを更新します。
5.2。 ViewModelをJSONオブジェクトに変換します
上記のJSONオブジェクトはViewModelに変換されているため、ViewModelをJSONオブジェクトに変換してバックエンドに渡す必要がある場合はどうすればよいですか?
ノックアウトには2つの方法があります。
•ko.tojs():viewmodelをjsonオブジェクトに変換します
•ko.tojson():viewmodelをシリアル化されたJSON文字列に変換します。
たとえば、コードは次のとおりです。
$(function(){var ojson1 = ko.tojs(myviewmodeljson); var ojson2 = ko.tojson(myviewmodeljson);}); var myviewmodeljson = { ko.observable( "Development Group")}; Ko.ApplyBindings(myViewModeljson);次に、OJSON1とOJSON2の値を監視しましょう。
コードの疑い:上記の写真を通して、2つの方法の違いを理解するのは簡単です。ここでは、これら2つの方法がKOに組み込まれており、マッピングコンポーネントのサポートを必要としないことに注意する必要があります。
6.独自のデータバインド属性を作成します
私は上記のことについて多くのことを話しました、そして、私はノックアウトでいくつかのバインディングと監視を紹介します。したがって、時には、次のようなデータバインドをカスタマイズする必要があります。この要件は、コンポーネントをカプセル化する場合に特に役立ちます。実装できますか?もちろん。
ノックアウトでは、KO.BindingHandlersプロパティが提供され、データバインドプロパティをカスタマイズします。その構文は次のとおりです。
ko.bindinghandlers.myselect = {init:function(element、valueaccessor、allbindingsacsess、viewmodel){}、update:function(element、valuecacesser、allbindingsacsess、viewmodel){}};このように宣言するだけで、HTMLタグでカスタムデータバインドを使用できます。
<div> <select data-bind = "myselect:$ root"> <option id = "1"> r&d department </option> <option id = "2">人事部門</option> <option id = "3">管理部門</option> </select> </div>
MySelectは、カスタムバインディングプロパティです。 $ rootは当面の間初期化として理解できます(この説明は厳格ではありませんが、より合理的な説明がある場合は、自由に修正してください)。
コードの疑い:上記のKO.BindingHandlersを使用して、カスタムバインディングプロパティを単純に実装できます。 2つのポイントを説明する必要があります。
•initは、名前が示すように、カスタムバインディングを初期化します。複数のパラメーターが含まれています。最初の2つのパラメーターは、通常、より頻繁に使用されます。最初のパラメーターは、カスタムバインディングを初期化するDOM要素を表し、2番目のパラメーターは一般に初期化されたパラメーターを渡すために使用されます。
•対応する監視属性が変更されると、この方法が入力されます。コールバックが不要な場合、この方法は宣言されていない可能性があります。
ここでは、ブロガーは、彼が共有していたドロップダウンボックスコンポーネントのミューティゼセレクトに基づいて、カスタムバインディングの使用を簡単に説明します。
6.1。最もシンプルな違い
一般的に言えば、KOを使用していくつかの一般的なコンポーネントをカプセル化する必要がある場合は、KO.BindingHandlersを使用する必要があります。ブロガーでは、それをMutiSelectコンポーネントと組み合わせて使用する方法について説明します。
最初にカスタマイズされたKO.BindingHandlersを宣言し、initメソッドでSELECTタグを初期化します
ko.bindinghandlers.myselect = {init:function(element、valueaccessor、allbindingsacsesser、viewmodel){$(element).multiselect();}、update:function(element、valueaccesser、allbindingsaccesser、viewmodel){}};次に、ページタグで使用します
<div style = "text-align:center;"> <select data-bind = "myselect:$ root"> <option id = "1"> r&d department </option> <option id = "2">人間問題部門</option> <option id = "3">管理部門</option> </select> </div>
最後の3番目の部分は、結合をアクティブにします
$(function(){var multiselect = {}; ko.applybindings(multiselect);});パラメーターを渡す必要がない場合は、空のViewModelをバインドするだけです。一部の人々は困惑していますが、第三の部分はそれが実用的であるとは感じていません。ブロガーの理解は、DOM要素がデータバインドを使用してデータをバインドする必要があり、KOバインディングを有効にする必要があることです。ここではKO.ApplyBindings()です。
効果を得る:
6.2。パラメーターの渡されます
最初のステップは、ko.bindinghandlersをカスタマイズすることです
ko.bindinghandlers.myselect = {init:function(element、valueccessor、allbindingsacsess、viewmodel){var oparam = valueaccessor(); $(element).multiselect(oparam);}、update:function(element、valueaccesss、allbindingsacsess、viewmodel、viewmodel);2番目のステップは上記と同じです。HTMLタグでこのカスタムバインディングを使用します。
ステップ3:バインディングをアクティブにするときにパラメーターを渡します
$(function(){var multiselect = {enableclickableoptgroups:true、// collapse grouping onchange:function(option、checked){alert( "select change");}}; ko.applybindings(multiselect);});これらの3つのステップを通じて、パラメーターをbutiselectの初期化に渡すことができます。
コードクエリ:INITイベントの2番目のパラメーターは、その主な機能はViewModelから送信されるパラメーターを取得することだと述べましたが、ここではメソッドとして使用する必要があります。なぜそれが使われるのか、研究されるべきものがたくさんあるのです!
2。追加、削除、変更、検索の最初の例
この時点で、基本的なことがついにレイアウトされました。私はもともと1つの記事でそれらを完成させることを計画していましたが、基本的なことがそれほど拡大されるとは思っていませんでした!次の記事には、追加、削除、変更、チェックの例が含まれています。 BootstraptableとKnockoutjsが組み合わさって、追加、削除、変更、およびチェックの機能を実現します[2]。学習してコミュニケーションをとることを歓迎します。もちろん、推奨することもできます。