ฉันควรใช้ `this 'หรือ` $ scope'?


251

มีสองรูปแบบในการใช้งานสำหรับการเข้าถึงฟังก์ชั่นการควบคุมคือ: และthis$scope

ฉันควรใช้แบบไหนและเมื่อใด ฉันเข้าใจว่าthisถูกตั้งค่าเป็นตัวควบคุมและ$scopeเป็นวัตถุในห่วงโซ่ขอบเขตสำหรับมุมมอง แต่ด้วยไวยากรณ์ "Controller as Var" ใหม่คุณสามารถใช้งานได้อย่างง่ายดาย ดังนั้นสิ่งที่ฉันถามคือสิ่งที่ดีที่สุดและทิศทางในอนาคตคืออะไร?

ตัวอย่าง:

  1. การใช้ this

    function UserCtrl() {
      this.bye = function() { alert('....'); };
    }
    
    <body ng-controller='UserCtrl as uCtrl'>
      <button ng-click='uCtrl.bye()'>bye</button>
    
  2. การใช้ $scope

    function UserCtrl($scope) {
        $scope.bye = function () { alert('....'); };
    }
    
    <body ng-controller='UserCtrl'>
        <button ng-click='bye()'>bye</button>
    

ฉันพบว่าตัวเองนั้นthis.nameง่ายต่อสายตาและเป็นธรรมชาติมากกว่าเมื่อเปรียบเทียบกับรูปแบบ OO ของ Javascript

คำแนะนำได้ไหม


การใช้ 'this' ดูเหมือนจะใหม่เหมือน Google I / O 2013 m.youtube.com/watch?v=HCR7i5F5L8cตรวจสอบคำตอบนี้: stackoverflow.com/questions/11605917/ …
AlanW

ไวยากรณ์ "UserCtrl as uCtrl" ใหม่หรือไม่ ฉันไม่เห็นเอกสารในหน้า 1.0.6 หรือ 1.1.4 ngController
Mark Rajcok

เอาล่ะมันเป็นเอกสารที่เกี่ยวกับการใหม่ 1.1.5 หน้า
Mark Rajcok

1
คำอธิบายที่ดีที่สุดสำหรับ $ scope และ codetunnel.io/angularjs-controller-as-or-scope
Sai

คำตอบ:


229

ทั้งสองมีประโยชน์ ก่อนอื่นมีประวัติ ...

$ scope เป็นเทคนิค "คลาสสิค" ในขณะที่ "controller as" เป็นรุ่นล่าสุดมากขึ้น (เป็นเวอร์ชั่น 1.2.0 อย่างเป็นทางการแม้ว่าจะปรากฏในรุ่นก่อนวางจำหน่ายที่ไม่เสถียรก่อนหน้านี้)

ทั้งสองทำงานได้ดีอย่างสมบูรณ์และคำตอบเดียวที่ผิดคือการผสมในแอพเดียวกันโดยไม่มีเหตุผลที่ชัดเจน ตรงไปตรงมาการผสมมันจะได้ผล แต่มันจะเพิ่มความสับสน ดังนั้นเลือกหนึ่งและหมุนด้วย สิ่งที่สำคัญที่สุดคือการสอดคล้อง

อันไหน? ขึ้นอยู่กับคุณ มีตัวอย่างอีกมากมายที่มีขอบเขต $ แต่ "controller as" กำลังหยิบขึ้นมาเช่นกัน ดีกว่าอีกไหม? ที่เป็นที่ถกเถียงกัน ดังนั้นคุณจะเลือกอย่างไร

ความสบายใจ

ฉันชอบ "คอนโทรลเลอร์เป็น" เพราะฉันชอบซ่อนขอบเขต $ และเปิดเผยสมาชิกจากคอนโทรลเลอร์ไปยังมุมมองผ่านวัตถุตัวกลาง ด้วยการตั้งค่านี้ * ฉันสามารถแสดงสิ่งที่ฉันต้องการเปิดเผยจากคอนโทรลเลอร์ไปยังมุมมอง คุณสามารถทำได้ด้วย $ scope เหมือนกันฉันแค่ต้องการใช้จาวาสคริปต์มาตรฐานสำหรับสิ่งนี้ ในความเป็นจริงฉันรหัสมันเช่นนี้

var vm = this;

vm.title = 'some title';
vm.saveData = function(){ ... } ;

return vm;

สิ่งนี้ทำให้ฉันรู้สึกสะอาดและทำให้ฉันเห็นสิ่งที่ถูกมองเห็นได้ง่ายขึ้น โปรดสังเกตว่าฉันตั้งชื่อตัวแปรที่ฉันส่งคืน "vm" ซึ่งย่อมาจาก viewmodel นั่นเป็นเพียงการประชุมของฉัน

ด้วย $ scope ฉันสามารถทำสิ่งเดียวกันดังนั้นฉันจึงไม่เพิ่มหรือเบี่ยงเบนด้วยเทคนิค

$scope.title = 'some title';
$scope.saveData = function() { ... };

ดังนั้นมันขึ้นอยู่กับคุณที่นั่น

การฉีด

ด้วย $ scope ฉันต้องการฉีด $ scope เข้าไปในคอนโทรลเลอร์ ฉันไม่ต้องทำสิ่งนี้กับคอนโทรลเลอร์ยกเว้นว่าฉันต้องการเหตุผลอื่น (เช่น $ broadcast หรือ watches แม้ว่าฉันจะพยายามหลีกเลี่ยงนาฬิกาในคอนโทรลเลอร์)

อัปเดต ฉันเขียนบทความนี้เกี่ยวกับ 2 ตัวเลือก: http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/


4
โดยส่วนตัวฉันยังทำตามแนวทางของคุณโดยใช้ vm กลิ่นรหัสเดียวที่ฉันหยิบขึ้นมาคือเมื่อคุณต้องการโต้ตอบกับ $ scope เช่นการสมัครสมาชิกหรือการออกอากาศเหตุการณ์การเข้าถึงตัวแปรการตรวจสอบแบบฟอร์มภายในคอนโทรลเลอร์ของคุณ ฯลฯ สิ่งนี้นำไปสู่สภาพแวดล้อมที่ค่อนข้างผสมซึ่งคุณยังต้องฉีด $ scope แม้ว่าคุณจะใช้คอนโทรลเลอร์เป็นคุณสมบัติก็ตาม
เบเยอร์

9
ขวา. $ scope ยังคงใช้สำหรับในกรณีนั้น แต่มันถูกใช้มากกว่าเป็นบริการ เมื่อเราฉีดบริการเชิงมุม ($ scope, $ q, ฯลฯ ) พวกเขาให้คุณสมบัติบางอย่างที่เราต้องการ $ scope ช่วยให้เราสามารถดูใช้ใช้ข้อความรวมถึงการผูกข้อมูล และถึงแม้จะใช้คอนโทรลเลอร์เป็นก็ยังคงใช้ $ scope แต่เป็นนามธรรมที่ถูกต้อง
John Papa

1
var vm = this;คุณจำเป็นต้องเรียกมันว่า "vm" ในมุมมองด้วยหรือไม่ 'controller as vm' พวกเขาจะต้องเหมือนกันหรือไม่
Javid

2
@JohnPapa - ทำไมเทมเพลต SideWaffle ไม่ทำ "return vm;" เมื่อใช้คอนโทรลเลอร์เป็น?
Kevin

2
@Kevin Controllers ทำหน้าที่เป็น Ctor ได้อย่างมีประสิทธิภาพดังนั้นจึงส่งคืน "this" ไปแล้ว
John Papa

68

$scopeกำลังถูกลบใน Angular 2.0 ดังนั้นการใช้thisจะเป็นวิธีการที่คนอื่น ๆ ต้องการทำตามวันที่เปิดตัว Angular 2.0 ใกล้เข้ามา


40

ความคิดเห็นของฉันคือว่า 'นี่' ในจาวาสคริปต์มีปัญหาเพียงพอในตัวมันเองและการเพิ่มความหมาย / การใช้งานอื่นไม่ใช่ความคิดที่ดี

ฉันจะใช้ $ scope เพื่อประโยชน์ของความชัดเจน

UPDATE

ขณะนี้คือ 'การควบคุมเป็น' ไวยากรณ์กล่าวถึงที่นี่ ฉันไม่ใช่แฟน แต่ตอนนี้มันเป็น AngularJS 'ทางการ' มากกว่าที่สร้างขึ้นมาแล้วสมควรได้รับความสนใจ


10
ฉันคิดว่าเราต้องเข้าใจไวยากรณ์ "UserCtrl as uCtrl" ใหม่ก่อนที่เราจะสามารถพูดได้ว่าเราคิดว่าอะไรดีกว่า
Mark Rajcok

Re 'UserCtrl เป็น uCtrl' ฉันเห็นด้วยว่าต้องเข้าใจสิ่งนี้ ฉันคิดว่ามันเป็นความคิดที่ไม่ดีด้วยเหตุผลส่วนใหญ่เช่นเดียวกับข้อโต้แย้งที่เกิดขึ้นที่นี่: groups.google.com/forum/#!topic/angular/84selECbp1I
Roy Truelove

4
หากคุณคุ้นเคยกับoop ใน JSมันสมเหตุสมผลดี ตัวควบคุมเป็นคลาสและเชิงมุมใช้ตัวดำเนินการใหม่ทุกครั้งที่มีการสร้างตัวควบคุม คุณยินดีที่จะไม่ชอบ แต่การระบุว่ามีปัญหาในการใช้ 'this' นั้นทำให้เข้าใจผิด มันเป็นกรณีการใช้งานที่ยอมรับได้สำหรับ 'this'
MJ

$ scope ไม่เพิ่มความคมชัด ในความเป็นจริงมันอาจเป็นเรื่องยากมากที่จะรู้ว่าสิ่งที่เกิดขึ้นในมุมมองเมื่อใช้ $ scope และคุณมีขอบเขตซ้อนกัน ตัวควบคุมเป็นไวยากรณ์พร้อมกับการใช้สิ่งนี้จะเพิ่มความชัดเจนมากขึ้น ในมุมมองเป็นสิ่งที่ดีและชัดเจนว่าขอบเขตของตัวควบคุมเป็นวิธีการหรือคุณสมบัติมาจาก
ddelrio1986

1
ฉันเห็นด้วยกับ @ ddelrio1986 เพิ่งมีปัญหากับแท็บ bootstrap และ agular โดยใช้ var vm = $ scope แท็บมีขอบเขตของตนเองดังนั้นคุณจึงไม่สามารถใช้สิ่งนี้ได้ตามที่คุณคาดหวัง แต่ด้วย var vm = สิ่งนี้ทำงานได้อย่างที่คาดไว้
user441521

11

ฉันคิดว่า Controller As ดีกว่าเพราะมันช่วยให้สามารถวางขอบเขตได้ง่ายขึ้นตามที่อธิบายไว้โดย Todd Motto ที่นี่:

http://toddmotto.com/digging-into-angulars-controller-as-syntax/

นอกจากนี้ยังรับประกันว่าคุณจะมีอย่างน้อยหนึ่งเสมอ ในนิพจน์ที่มีผลผูกพันของคุณซึ่งบังคับให้คุณทำตามคำแนะนำที่ไม่ผูกมัดกับคำแนะนำดั้งเดิม

รวมทั้งคุณสามารถแยกออกจากขอบเขตซึ่งกำลังจะหายไปใน 2.0


7

เอกสารเชิงมุมบอกให้คุณทราบอย่างชัดเจนว่าthisมีการแนะนำให้ใช้ ที่นอกเหนือไปจากความจริงที่ว่านี้จะถูกลบออกเป็นเหตุผลเพียงพอสำหรับผมที่จะไม่เคยใช้$scope$scope


4

"$ scope กำลังถูกลบใน Angular 2.0" ของ jason328 ฟังดูมีเหตุผลที่ดีสำหรับฉัน และฉันก็พบเหตุผลอีกประการหนึ่งที่ช่วยให้ฉันเลือก: อ่านได้ง่ายthisขึ้น- เมื่อฉันเห็นใน HTML ฉันรู้ได้ทันทีว่าจะหาคำจำกัดความของอะไรfooCtrl.barbar

อัปเดต: ไม่นานหลังจากเปลี่ยนไปใช้thisโซลูชันฉันเริ่มคิดถึง$scopeวิธีที่ต้องพิมพ์น้อยลง


2

ฉันชอบชุดค่าผสม

console.log อย่างง่ายของ $ scope และ 'this' หลังจากเติมข้อมูลด้วยข้อมูลจำลองจะแสดงให้คุณเห็น

$ scope อนุญาตให้เข้าถึงภายใต้ส่วนครอบคลุมของคอนโทรลเลอร์ตัวอย่างเช่น

$$ChildScope: null;
$$childHead: null;
$$childTail: null;
$$listenerCount: Object;
$$listeners: Object;
$$nextSibling: Scope;
$$prevSibling: null;
$$watchers: null;
$$watcherCount: 0;
$id: 2;
$parent: Object;
foo: 'bar';

** คุณสมบัติและวิธีการที่มี $$ ไม่แนะนำให้ยุ่งกับทีม Angular แต่ $ สามารถเป็นเกมที่ปลอดภัยสำหรับการทำสิ่งที่ยอดเยี่ยมกับ $ parent และ $ id

'นี่' ตรงไปยังจุดที่แนบข้อมูลและฟังก์ชันสองทาง คุณจะเห็นสิ่งที่คุณแนบ:

foo: 'bar';

แล้วทำไมฉันถึงชอบชุดค่าผสม?

ในแอพที่ซ้อนกันของ ui-router ฉันสามารถเข้าถึงตัวควบคุมหลักตั้งค่าและเรียกค่าสากลและฟังก์ชั่นภายในตัวควบคุมลูกได้:

ในตัวควบคุมหลัก:

// Main Controller
var mainCtrl = this;
mainCtrl.foo = 'Parent at the bar';

ใน Child Controller:

// Child Controller
var mainCtrl = $scope.$parent.mainCtrl;
var childCtrl = this;

// update the parent from within the child
childCtrl.underageDrinking = function(){
    mainCtrl.foo = 'Child at the bar';
}

// And then attach the child back to a property on the parent controller!
mainCtrl.currentCtrl = childCtrl;

ตอนนี้คุณสามารถเข้าถึงผู้ปกครองจากภายในเด็กและเด็กจากผู้ปกครอง!


1

ทำงานได้ทั้งสองอย่าง แต่ถ้าคุณใช้สิ่งที่เหมาะสมสำหรับขอบเขตกับ $ scope และถ้าคุณใช้สิ่งที่เหมาะสมสำหรับตัวควบคุมกับตัวควบคุมรหัสของคุณจะง่ายต่อการบำรุงรักษา สำหรับผู้ที่พูดว่า "ฮึใช้ขอบเขตลืมคอนโทรลเลอร์นี้เป็นไวยากรณ์" ... มันอาจทำงานเหมือนเดิม แต่ฉันสงสัยว่าคุณจะสามารถรักษาแอปพลิเคชันขนาดใหญ่ไว้ได้โดยไม่สูญเสียอะไรไป

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.