ASP.NET Core'da öğe, bileşen ve model ilişkilerini koruma Blazor
Uyarı
ASP.NET Core'un bu sürümü artık desteklenmiyor. Daha fazla bilgi için bkz . .NET ve .NET Core Destek İlkesi. Geçerli sürüm için bu makalenin .NET 8 sürümüne bakın.
Bu makalede, işleme sırasında öğe, bileşen ve model ilişkilerini korumak için yönerge özniteliğinin nasıl kullanılacağı ve öğeler veya bileşenler daha sonra değişirken nasıl kullanılacağı @key
açıklanmaktadır.
Yönerge özniteliğinin @key
kullanımı
Öğelerin veya bileşenlerin listesini oluştururken ve öğeler ya da bileşenler daha sonra değişirken, Blazor önceki öğelerden veya bileşenlerden hangisinin korunacaklarına ve model nesnelerinin bunlara nasıl eşlenmesi gerektiğine karar vermelidir. Normalde, bu işlem otomatiktir ve genel işleme için yeterlidir, ancak genellikle yönerge özniteliğini kullanarak işlemi denetlemenin @key
gerekli olduğu durumlar vardır.
kullanılarak @key
çözülen bir koleksiyon eşleme sorununu gösteren aşağıdaki örneği göz önünde bulundurun.
Aşağıdaki bileşenler için:
- Bileşen
Details
, bir<input>
öğede görüntülenen üst bileşenden (Data
) veri alır. Kullanıcı<input>
öğelerinden birini seçtiğinde, görüntülenen belirli<input>
öğesi kullanıcıdan sayfanın odağını alabilir. - Üst bileşen, bileşeni kullanarak görüntülenecek kişi nesnelerinin
Details
listesini oluşturur. Her üç saniyede bir koleksiyona yeni bir kişi eklenir.
Bu tanıtım şunları yapmanızı sağlar:
- İşlenmiş çeşitli
Details
bileşenleri arasından bir<input>
seçin. - Kişi koleksiyonu otomatik olarak büyürken sayfanın odağının davranışını inceleyin.
Details.razor
:
<input value="@Data" />
@code {
[Parameter]
public string? Data { get; set; }
}
<input value="@Data" />
@code {
[Parameter]
public string? Data { get; set; }
}
<input value="@Data" />
@code {
[Parameter]
public string? Data { get; set; }
}
<input value="@Data" />
@code {
[Parameter]
public string Data { get; set; }
}
<input value="@Data" />
@code {
[Parameter]
public string Data { get; set; }
}
Aşağıdaki üst bileşende, bir kişi OnTimerCallback
eklemenin her yinelemesi koleksiyonun tamamının yeniden oluşturulmasına neden olur Blazor . Sayfanın odağı <input>
öğelerinin aynı dizin konumunda kaldığından, her kişi eklendiğinde odak kayar. Odağın kullanıcı tarafından seçilen öğenin dışına kaydırılması istenen bir davranış değildir. Aşağıdaki bileşenin hatalı davranışı gösterildikten sonra, kullanıcının deneyimini geliştirmek için @key
yönerge özniteliği kullanılmıştır.
People.razor
:
@page "/people"
@using System.Timers
@implements IDisposable
<PageTitle>People</PageTitle>
<h1>People Example</h1>
@foreach (var person in people)
{
<Details Data="@person.Data" />
}
@code {
private Timer timer = new Timer(3000);
public List<Person> people =
new()
{
{ new Person { Data = "Person 1" } },
{ new Person { Data = "Person 2" } },
{ new Person { Data = "Person 3" } }
};
protected override void OnInitialized()
{
timer.Elapsed += (sender, eventArgs) => OnTimerCallback();
timer.Start();
}
private void OnTimerCallback()
{
_ = InvokeAsync(() =>
{
people.Insert(0,
new Person
{
Data = $"INSERTED {DateTime.Now.ToString("hh:mm:ss tt")}"
});
StateHasChanged();
});
}
public void Dispose() => timer.Dispose();
public class Person
{
public string? Data { get; set; }
}
}
PeopleExample.razor
:
@page "/people-example"
@using System.Timers
@implements IDisposable
@foreach (var person in people)
{
<Details Data="person.Data" />
}
@code {
private Timer timer = new Timer(3000);
public List<Person> people =
new()
{
{ new Person { Data = "Person 1" } },
{ new Person { Data = "Person 2" } },
{ new Person { Data = "Person 3" } }
};
protected override void OnInitialized()
{
timer.Elapsed += (sender, eventArgs) => OnTimerCallback();
timer.Start();
}
private void OnTimerCallback()
{
_ = InvokeAsync(() =>
{
people.Insert(0,
new Person
{
Data = $"INSERTED {DateTime.Now.ToString("hh:mm:ss tt")}"
});
StateHasChanged();
});
}
public void Dispose() => timer.Dispose();
public class Person
{
public string? Data { get; set; }
}
}
PeopleExample.razor
:
@page "/people-example"
@using System.Timers
@implements IDisposable
@foreach (var person in people)
{
<Details Data="person.Data" />
}
@code {
private Timer timer = new Timer(3000);
public List<Person> people =
new()
{
{ new Person { Data = "Person 1" } },
{ new Person { Data = "Person 2" } },
{ new Person { Data = "Person 3" } }
};
protected override void OnInitialized()
{
timer.Elapsed += (sender, eventArgs) => OnTimerCallback();
timer.Start();
}
private void OnTimerCallback()
{
_ = InvokeAsync(() =>
{
people.Insert(0,
new Person
{
Data = $"INSERTED {DateTime.Now.ToString("hh:mm:ss tt")}"
});
StateHasChanged();
});
}
public void Dispose() => timer.Dispose();
public class Person
{
public string? Data { get; set; }
}
}
PeopleExample.razor
:
@page "/people-example"
@using System.Timers
@implements IDisposable
@foreach (var person in people)
{
<Details Data="person.Data" />
}
@code {
private Timer timer = new Timer(3000);
public List<Person> people =
new()
{
{ new Person { Data = "Person 1" } },
{ new Person { Data = "Person 2" } },
{ new Person { Data = "Person 3" } }
};
protected override void OnInitialized()
{
timer.Elapsed += (sender, eventArgs) => OnTimerCallback();
timer.Start();
}
private void OnTimerCallback()
{
_ = InvokeAsync(() =>
{
people.Insert(0,
new Person
{
Data = $"INSERTED {DateTime.Now.ToString("hh:mm:ss tt")}"
});
StateHasChanged();
});
}
public void Dispose() => timer.Dispose();
public class Person
{
public string Data { get; set; }
}
}
PeopleExample.razor
:
@page "/people-example"
@using System.Timers
@implements IDisposable
@foreach (var person in people)
{
<Details Data="person.Data" />
}
@code {
private Timer timer = new Timer(3000);
public List<Person> people =
new List<Person>()
{
{ new Person { Data = "Person 1" } },
{ new Person { Data = "Person 2" } },
{ new Person { Data = "Person 3" } }
};
protected override void OnInitialized()
{
timer.Elapsed += (sender, eventArgs) => OnTimerCallback();
timer.Start();
}
private void OnTimerCallback()
{
_ = InvokeAsync(() =>
{
people.Insert(0,
new Person
{
Data = $"INSERTED {DateTime.Now.ToString("hh:mm:ss tt")}"
});
StateHasChanged();
});
}
public void Dispose() => timer.Dispose();
public class Person
{
public string Data { get; set; }
}
}
people
koleksiyonun içeriği eklenen, silinen veya yeniden sıralanan girdilerle değişir. Yeniden işleme, görünür davranış farklılıklarına yol açabilir. Örneğin, bir kişi koleksiyona people
her eklendiğinde kullanıcının odağı kaybolur.
Öğeleri veya bileşenleri koleksiyona eşleme işlemi @key
yönerge özniteliği ile denetlenebilir. @key
yönerge özniteliğinin kullanılması, anahtarın değerine dayanarak öğelerin veya bileşenlerin korunmasını garanti eder. Yukarıdaki örnekte yer alan Details
bileşeninde person
öğesine anahtar uygulanırsa, Blazor değişmemiş olan Details
bileşenlerinin yeniden işlenmesini yoksayar.
Üst bileşeni, yönerge özniteliğini @key
koleksiyonla people
kullanacak şekilde değiştirmek için öğesini aşağıdaki şekilde güncelleştirin <Details>
:
<Details @key="person" Data="@person.Data" />
people
koleksiyonu değiştiğinde Details
örnekleri ile person
örnekleri arasındaki ilişki korunur. Koleksiyonun başlangıcına bir Person
eklendiğinde, buna karşılık gelen konuma yeni bir Details
örneği eklenir. Diğer örnekler olduğu gibi bırakılır. Bu nedenle koleksiyona kişiler eklendikçe kullanıcının odağı kaybolmaz.
@key
yönerge özniteliği kullanıldığında diğer koleksiyon güncelleştirmeleri de aynı davranışı gösterir:
- Koleksiyondan örnek silindiğinde kullanıcı arabiriminden yalnızca silinen örneğe karşılık gelen bileşen örneği kaldırılır. Diğer örnekler olduğu gibi bırakılır.
- Koleksiyon girdileri yeniden sıralanır, kullanıcı arabiriminde bunlara karşılık gelen bileşen örnekleri korunur ve yeniden sıralanır.
Önemli
Anahtarlar her kapsayıcı öğesi veya bileşeni için yereldir. Anahtarlar belgede genel olarak karşılaştırılamaz.
@key
ne zaman kullanılmalı?
Normalde her liste işlendiğinde (örneğin bir foreach
bloğunda) ve @key
yönerge özniteliğini tanımlayacak uygun bir değer olduğunda @key
kullanmak mantıklıdır.
Ayrıca aşağıdaki örneklerde gösterildiği gibi, bir nesne değişmediğinde öğe veya bileşen alt ağacını korumak için de @key
kullanabilirsiniz.
Örnek 1:
<li @key="person">
<input value="@person.Data" />
</li>
Örnek 2:
<div @key="person">
@* other HTML elements *@
</div>
Bir person
örneği değiştiğinde @key
öznitelik yönergesi Blazor'ı şunları yapmaya zorlar:
<li>
ve<div>
öğelerinin tamamını ve bunların alt öğelerini atma.- Kullanıcı arabirimi içinde yeni öğeler ve bileşenlerle alt ağacı yeniden oluşturma.
Alt ağaç içinde koleksiyon değiştiğinde hiçbir kullanıcı arabirimi durumunun korunmadığından emin olmak için bu yararlıdır.
@key
kapsamı
@key
öznitelik yönergesinin kapsamı, üst öğesi içindeki kendi eşdüzeyleri olarak belirlenir.
Aşağıdaki örneği inceleyin. first
ile second
anahtarları, dış <div>
öğesiyle aynı kapsam içinde birbiriyle karşılaştırılır:
<div>
<div @key="first">...</div>
<div @key="second">...</div>
</div>
Aşağıdaki örnek first
ile second
anahtarlarını kendi kapsamlarında, birbirleriyle ilişkisiz olarak ve birbirlerini etkilemeyecek şekilde gösterir. Her @key
kapsamı yalnızca kendi üst <div>
öğesine uygulanır; üst <div>
öğeleri arasında uygulanmaz:
<div>
<div @key="first">...</div>
</div>
<div>
<div @key="second">...</div>
</div>
Daha önce gösterilen Details
bileşeni için, aşağıdaki örnekler aynı @key
kapsamı içinde person
verilerini işler ve @key
için tipik kullanım örneklerini gösterir:
<div>
@foreach (var person in people)
{
<Details @key="person" Data="@person.Data" />
}
</div>
@foreach (var person in people)
{
<div @key="person">
<Details Data="@person.Data" />
</div>
}
<ol>
@foreach (var person in people)
{
<li @key="person">
<Details Data="@person.Data" />
</li>
}
</ol>
Aşağıdaki örneklerde @key
kapsamı yalnızca her Details
bileşen örneğini çevreleyen <div>
veya <li>
öğesidir. Bu nedenle people
koleksiyonunun her üyesinin person
verilerine, işlenen Details
bileşenleri genelindeki her person
örneğinde anahtar uygulanmaz. @key
kullanırken aşağıdaki desenlerden kaçının:
@foreach (var person in people)
{
<div>
<Details @key="person" Data="@person.Data" />
</div>
}
<ol>
@foreach (var person in people)
{
<li>
<Details @key="person" Data="@person.Data" />
</li>
}
</ol>
@key
ne zaman kullanılmamalı?
@key
ile işlemenin performans maliyeti vardır. Performans maliyeti yüksek değildir ama @key
yönerge özniteliğini yalnızca öğeyi veya bileşeni korumanın uygulama açısından faydalı olacağı durumlarda belirtin.
@key
kullanılmasa bile Blazor alt öğe ve bileşen örneklerini mümkün olduğunca korur. @key
kullanmanın tek avantajı, model örneklerinin korunan bileşen örneklerine nasıl eşleneceğini Blazor'ın seçmesi yerine bu eşleme üzerinde denetim sahibi olmaktır.
@key
için kullanılacak değerler
Genellikle @key
için aşağıdaki değerlerden birini sağlamak mantıklı olur:
- Model nesnesi örnekleri. Örneğin yukarıdaki örnekte
Person
örneği (person
) kullanılmıştı. Bu, nesne başvurusu eşitliği temelinde koruma sağlar. - Benzersiz tanımlayıcılar. Örneğin benzersiz tanımlayıcılar
int
,string
veyaGuid
türündeki birincil anahtar değerlerini temel alabilir.
@key
için kullanılan değerlerin çakışmadığından emin olun. Aynı üst öğede çakışan değerler algılanırsa, Blazor eski öğeleri veya bileşenleri belirleyici bir şekilde yeni öğelere veya bileşenlere eşleyemediğinden bir özel durum oluşturur. Yalnızca nesne örnekleri veya birincil anahtar değerleri gibi farklı değerler kullanın.
ASP.NET Core
Geri Bildirim
https://aka.ms/ContentUserFeedback.
Çok yakında: 2024 boyunca, içerik için geri bildirim mekanizması olarak GitHub Sorunları’nı kullanımdan kaldıracak ve yeni bir geri bildirim sistemiyle değiştireceğiz. Daha fazla bilgi için bkz.Gönderin ve geri bildirimi görüntüleyin