Aracılığıyla paylaş


ASP.NET Core'da .NET yöntemlerinden JavaScript işlevlerini çağırma Blazor

Not

Bu, bu makalenin en son sürümü değildir. Geçerli sürüm için bu makalenin .NET 9 sürümüne bakın.

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 9 sürümüne bakın.

Önemli

Bu bilgiler, ticari olarak piyasaya sürülmeden önce önemli ölçüde değiştirilebilen bir yayın öncesi ürünle ilgilidir. Burada verilen bilgilerle ilgili olarak Microsoft açık veya zımni hiçbir garanti vermez.

Geçerli sürüm için bu makalenin .NET 9 sürümüne bakın.

Bu makalede. .NET'ten JavaScript (JS) işlevlerini çağırma açıklanmaktadır.

ASP.NET Core'da JavaScript işlevlerinden JS .NET yöntemlerini çağırma hakkında bilgi için Blazor'e bakın.

İşlevleri çağırın JS

IJSRuntime, Blazor çerçevesi tarafından kaydedilir. .NET'ten JS çağrısı yapmak için IJSRuntime soyutlamasını ekleyin ve aşağıdaki yöntemlerden birini çağırın.

Daha önce bahsedilen .NET yöntemlerinin JS işlevlerini çağırdığı durumlar için:

  • İşlev tanımlayıcısı (String), genel kapsama () göredirwindow. window.someScope.someFunction çağrısı yapmak için, tanımlayıcı someScope.someFunction. çağrılmadan önce işlevi kaydetmeye gerek yoktur.
  • Object[] içinde JSON serileştirilebilen herhangi bir sayıdaki bağımsız değişkeni bir JS işlevine geçirin.
  • İptal belirteci (CancellationToken), işlemlerin iptal edilmesi gerektiğini belirten bir bildirim yar.
  • TimeSpan bir işlemin zaman sınırını JS temsil eder.
  • Dönüş TValue türü de JSON serileştirilebilir olmalıdır. TValue döndürülen JSON türüyle en iyi eşleyen .NET türüyle eşleşmelidir.
  • JS Promise yöntemleri için bir InvokeAsync döndürülür. InvokeAsync Promise açar ve Promise tarafından beklenen değeri döndürür.

Önceden işleme etkinleştirilmiş ve bu sunucu tarafı uygulamalar için varsayılan olan uygulamalar için, önceden işleme sırasında Blazor çağrı yapılamaz. Daha fazla bilgi için Prerendering bölümüne bakın.

Aşağıdaki örnek, TextDecoder tabanlı bir JS kod çözücüye dayanır. Örnek, bir gereksinimi geliştirici kodundan mevcut bir JS API'ye aktaran bir C# yöntemi üzerinden bir JS işlevinin nasıl çağrılabileceğini göstermektedir. JS işlevi bir C# yönteminden bayt dizisini kabul eder, dizinin kodunu çözer ve metni görüntülemek üzere bileşene döndürür.

<script>
  window.convertArray = (win1251Array) => {
    var win1251decoder = new TextDecoder('windows-1251');
    var bytes = new Uint8Array(win1251Array);
    var decodedArray = win1251decoder.decode(bytes);
    return decodedArray;
  };
</script>

Not

Genel JS konumu hakkında yönergeler ve üretim uygulamalarına yönelik önerilerimiz için ASP.NET Core Blazor uygulamalarında JavaScript konumu bölümüne bakın.

Aşağıdaki bileşen:

  • convertArray JS işlevi, bir düğme (InvokeAsync) seçerken Convert Array ile birlikte çağrılır.
  • JS İşlev çağrıldıktan sonra geçirilen dizi bir dizeye dönüştürülür. Görüntülenmesi için dize, bileşene (text) döndürülür.

CallJs1.razor:

@page "/call-js-1"
@inject IJSRuntime JS

<PageTitle>Call JS 1</PageTitle>

<h1>Call JS Example 1</h1>

<p>
    <button @onclick="ConvertArray">Convert Array</button>
</p>

<p>
    @text
</p>

<p>
    Quote ©2005 <a href="https://www.uphe.com">Universal Pictures</a>: 
    <a href="https://www.uphe.com/movies/serenity-2005">Serenity</a><br>
    <a href="https://www.imdb.com/name/nm0472710/">David Krumholtz on IMDB</a>
</p>

@code {
    private MarkupString text;

    private uint[] quoteArray = 
        new uint[]
        {
            60, 101, 109, 62, 67, 97, 110, 39, 116, 32, 115, 116, 111, 112, 32,
            116, 104, 101, 32, 115, 105, 103, 110, 97, 108, 44, 32, 77, 97,
            108, 46, 60, 47, 101, 109, 62, 32, 45, 32, 77, 114, 46, 32, 85, 110,
            105, 118, 101, 114, 115, 101, 10, 10,
        };

    private async Task ConvertArray() => 
        text = new(await JS.InvokeAsync<string>("convertArray", quoteArray));
}

CallJs1.razor:

@page "/call-js-1"
@inject IJSRuntime JS

<PageTitle>Call JS 1</PageTitle>

<h1>Call JS Example 1</h1>

<p>
    <button @onclick="ConvertArray">Convert Array</button>
</p>

<p>
    @text
</p>

<p>
    Quote ©2005 <a href="https://www.uphe.com">Universal Pictures</a>: 
    <a href="https://www.uphe.com/movies/serenity-2005">Serenity</a><br>
    <a href="https://www.imdb.com/name/nm0472710/">David Krumholtz on IMDB</a>
</p>

@code {
    private MarkupString text;

    private uint[] quoteArray = 
        new uint[]
        {
            60, 101, 109, 62, 67, 97, 110, 39, 116, 32, 115, 116, 111, 112, 32,
            116, 104, 101, 32, 115, 105, 103, 110, 97, 108, 44, 32, 77, 97,
            108, 46, 60, 47, 101, 109, 62, 32, 45, 32, 77, 114, 46, 32, 85, 110,
            105, 118, 101, 114, 115, 101, 10, 10,
        };

    private async Task ConvertArray() => 
        text = new(await JS.InvokeAsync<string>("convertArray", quoteArray));
}

CallJsExample1.razor:

@page "/call-js-example-1"
@inject IJSRuntime JS

<h1>Call JS <code>convertArray</code> Function</h1>

<p>
    <button @onclick="ConvertArray">Convert Array</button>
</p>

<p>
    @text
</p>

<p>
    Quote ©2005 <a href="https://www.uphe.com">Universal Pictures</a>: 
    <a href="https://www.uphe.com/movies/serenity-2005">Serenity</a><br>
    <a href="https://www.imdb.com/name/nm0472710/">David Krumholtz on IMDB</a>
</p>

@code {
    private MarkupString text;

    private uint[] quoteArray = 
        new uint[]
        {
            60, 101, 109, 62, 67, 97, 110, 39, 116, 32, 115, 116, 111, 112, 32,
            116, 104, 101, 32, 115, 105, 103, 110, 97, 108, 44, 32, 77, 97,
            108, 46, 60, 47, 101, 109, 62, 32, 45, 32, 77, 114, 46, 32, 85, 110,
            105, 118, 101, 114, 115, 101, 10, 10,
        };

    private async Task ConvertArray()
    {
        text = new(await JS.InvokeAsync<string>("convertArray", quoteArray));
    }
}

CallJsExample1.razor:

@page "/call-js-example-1"
@inject IJSRuntime JS

<h1>Call JS <code>convertArray</code> Function</h1>

<p>
    <button @onclick="ConvertArray">Convert Array</button>
</p>

<p>
    @text
</p>

<p>
    Quote ©2005 <a href="https://www.uphe.com">Universal Pictures</a>: 
    <a href="https://www.uphe.com/movies/serenity-2005">Serenity</a><br>
    <a href="https://www.imdb.com/name/nm0472710/">David Krumholtz on IMDB</a>
</p>

@code {
    private MarkupString text;

    private uint[] quoteArray = 
        new uint[]
        {
            60, 101, 109, 62, 67, 97, 110, 39, 116, 32, 115, 116, 111, 112, 32,
            116, 104, 101, 32, 115, 105, 103, 110, 97, 108, 44, 32, 77, 97,
            108, 46, 60, 47, 101, 109, 62, 32, 45, 32, 77, 114, 46, 32, 85, 110,
            105, 118, 101, 114, 115, 101, 10, 10,
        };

    private async Task ConvertArray()
    {
        text = new(await JS.InvokeAsync<string>("convertArray", quoteArray));
    }
}

CallJsExample1.razor:

@page "/call-js-example-1"
@inject IJSRuntime JS

<h1>Call JS <code>convertArray</code> Function</h1>

<p>
    <button @onclick="ConvertArray">Convert Array</button>
</p>

<p>
    @text
</p>

<p>
    Quote ©2005 <a href="https://www.uphe.com">Universal Pictures</a>: 
    <a href="https://www.uphe.com/movies/serenity-2005">Serenity</a><br>
    <a href="https://www.imdb.com/name/nm0472710/">David Krumholtz on IMDB</a>
</p>

@code {
    private MarkupString text;

    private uint[] quoteArray = 
        new uint[]
        {
            60, 101, 109, 62, 67, 97, 110, 39, 116, 32, 115, 116, 111, 112, 32,
            116, 104, 101, 32, 115, 105, 103, 110, 97, 108, 44, 32, 77, 97,
            108, 46, 60, 47, 101, 109, 62, 32, 45, 32, 77, 114, 46, 32, 85, 110,
            105, 118, 101, 114, 115, 101, 10, 10,
        };

    private async Task ConvertArray()
    {
        text = new(await JS.InvokeAsync<string>("convertArray", quoteArray));
    }
}

CallJsExample1.razor:

@page "/call-js-example-1"
@inject IJSRuntime JS

<h1>Call JS <code>convertArray</code> Function</h1>

<p>
    <button @onclick="ConvertArray">Convert Array</button>
</p>

<p>
    @text
</p>

<p>
    Quote ©2005 <a href="https://www.uphe.com">Universal Pictures</a>: 
    <a href="https://www.uphe.com/movies/serenity-2005">Serenity</a><br>
    <a href="https://www.imdb.com/name/nm0472710/">David Krumholtz on IMDB</a>
</p>

@code {
    private MarkupString text;

    private uint[] quoteArray = 
        new uint[]
        {
            60, 101, 109, 62, 67, 97, 110, 39, 116, 32, 115, 116, 111, 112, 32,
            116, 104, 101, 32, 115, 105, 103, 110, 97, 108, 44, 32, 77, 97,
            108, 46, 60, 47, 101, 109, 62, 32, 45, 32, 77, 114, 46, 32, 85, 110,
            105, 118, 101, 114, 115, 101, 10, 10,
        };

    private async Task ConvertArray()
    {
        text = new MarkupString(await JS.InvokeAsync<string>("convertArray", 
            quoteArray));
    }
}

Kullanıcı hareketleriyle sınırlı JavaScript API'si

Bu bölüm sunucu tarafı bileşenleri için geçerlidir.

Bazı tarayıcı JavaScript (JS) API'leri yalnızca bir kullanıcı hareketi bağlamında (örneğin, kullanılarak Fullscreen API) yürütülebilir. Bu API'ler, kullanıcı arabirimi olayları zaman uyumsuz olarak işlendiği ve genellikle kullanıcı hareketi bağlamında artık gerçekleşmediği için JS birlikte çalışma mekanizması aracılığıyla sunucu tarafı bileşenlerde çağrılamaz. Uygulamanın ui olayını tamamen JavaScript'te işlemesi gerekir, bu nedenle 'nin onclick yönerge özniteliği yerine Blazorkullanın@onclick.

Döndürülen değeriInvokeVoidAsync () okumadan JavaScript işlevlerini çağırma

Şu durumlarda kullanın InvokeVoidAsync :

  • JavaScript (JS) çağrısının sonucunu okumak için .NET gerekli değildir.
  • JSişlevleri void(0)/void 0 veya undefined döndürür.

Bir displayTickerAlert1JS işlev sağlayın. İşlev InvokeVoidAsync ile çağrılır ve bir değer döndürmez.

<script>
  window.displayTickerAlert1 = (symbol, price) => {
    alert(`${symbol}: $${price}!`);
  };
</script>

Not

Genel JS konumu hakkında yönergeler ve üretim uygulamalarına yönelik önerilerimiz için ASP.NET Core Blazor uygulamalarında JavaScript konumu bölümüne bakın.

Bileşen (.razor) örneği (InvokeVoidAsync)

TickerChanged, aşağıdaki bileşende handleTickerChanged1 yöntemini çağırır.

CallJs2.razor:

@page "/call-js-2"
@inject IJSRuntime JS

<PageTitle>Call JS 2</PageTitle>

<h1>Call JS Example 2</h1>

<p>
    <button @onclick="SetStock">Set Stock</button>
</p>

@if (stockSymbol is not null)
{
    <p>@stockSymbol price: @price.ToString("c")</p>
}

@code {
    private string? stockSymbol;
    private decimal price;

    private async Task SetStock()
    {
        stockSymbol = 
            $"{(char)('A' + Random.Shared.Next(0, 26))}" +
            $"{(char)('A' + Random.Shared.Next(0, 26))}";
        price = Random.Shared.Next(1, 101);
        await JS.InvokeVoidAsync("displayTickerAlert1", stockSymbol, price);
    }
}

CallJs2.razor:

@page "/call-js-2"
@inject IJSRuntime JS

<PageTitle>Call JS 2</PageTitle>

<h1>Call JS Example 2</h1>

<p>
    <button @onclick="SetStock">Set Stock</button>
</p>

@if (stockSymbol is not null)
{
    <p>@stockSymbol price: @price.ToString("c")</p>
}

@code {
    private string? stockSymbol;
    private decimal price;

    private async Task SetStock()
    {
        stockSymbol = 
            $"{(char)('A' + Random.Shared.Next(0, 26))}" +
            $"{(char)('A' + Random.Shared.Next(0, 26))}";
        price = Random.Shared.Next(1, 101);
        await JS.InvokeVoidAsync("displayTickerAlert1", stockSymbol, price);
    }
}

CallJsExample2.razor:

@page "/call-js-example-2"
@inject IJSRuntime JS

<h1>Call JS Example 2</h1>

<p>
    <button @onclick="SetStock">Set Stock</button>
</p>

@if (stockSymbol is not null)
{
    <p>@stockSymbol price: @price.ToString("c")</p>
}

@code {
    private string? stockSymbol;
    private decimal price;

    private async Task SetStock()
    {
        stockSymbol = 
            $"{(char)('A' + Random.Shared.Next(0, 26))}{(char)('A' + Random.Shared.Next(0, 26))}";
        price = Random.Shared.Next(1, 101);
        await JS.InvokeVoidAsync("displayTickerAlert1", stockSymbol, price);
    }
}

CallJsExample2.razor:

@page "/call-js-example-2"
@inject IJSRuntime JS

<h1>Call JS Example 2</h1>

<p>
    <button @onclick="SetStock">Set Stock</button>
</p>

@if (stockSymbol is not null)
{
    <p>@stockSymbol price: @price.ToString("c")</p>
}

@code {
    private string? stockSymbol;
    private decimal price;

    private async Task SetStock()
    {
        stockSymbol = 
            $"{(char)('A' + Random.Shared.Next(0, 26))}{(char)('A' + Random.Shared.Next(0, 26))}";
        price = Random.Shared.Next(1, 101);
        await JS.InvokeVoidAsync("displayTickerAlert1", stockSymbol, price);
    }
}

CallJsExample2.razor:

@page "/call-js-example-2"
@inject IJSRuntime JS

<h1>Call JS Example 2</h1>

<p>
    <button @onclick="SetStock">Set Stock</button>
</p>

@if (stockSymbol is not null)
{
    <p>@stockSymbol price: @price.ToString("c")</p>
}

@code {
    private Random r = new();
    private string stockSymbol;
    private decimal price;

    private async Task SetStock()
    {
        stockSymbol = 
            $"{(char)('A' + r.Next(0, 26))}{(char)('A' + r.Next(0, 26))}";
        price = r.Next(1, 101);
        await JS.InvokeVoidAsync("displayTickerAlert1", stockSymbol, price);
    }
}

CallJsExample2.razor:

@page "/call-js-example-2"
@inject IJSRuntime JS

<h1>Call JS Example 2</h1>

<p>
    <button @onclick="SetStock">Set Stock</button>
</p>

@if (stockSymbol != null)
{
    <p>@stockSymbol price: @price.ToString("c")</p>
}

@code {
    private Random r = new Random();
    private string stockSymbol;
    private decimal price;

    private async Task SetStock()
    {
        stockSymbol = 
            $"{(char)('A' + r.Next(0, 26))}{(char)('A' + r.Next(0, 26))}";
        price = r.Next(1, 101);
        await JS.InvokeVoidAsync("displayTickerAlert1", stockSymbol, price);
    }
}

Sınıf (.cs) örneği (InvokeVoidAsync)

JsInteropClasses1.cs:

using Microsoft.JSInterop;

namespace BlazorSample;

public class JsInteropClasses1(IJSRuntime js) : IDisposable
{
    private readonly IJSRuntime js = js;

    public async ValueTask TickerChanged(string symbol, decimal price) => 
        await js.InvokeVoidAsync("displayTickerAlert1", symbol, price);

    // Calling SuppressFinalize(this) prevents derived types that introduce 
    // a finalizer from needing to re-implement IDisposable.
    public void Dispose() => GC.SuppressFinalize(this);
}
using Microsoft.JSInterop;

namespace BlazorSample;

public class JsInteropClasses1(IJSRuntime js) : IDisposable
{
    private readonly IJSRuntime js = js;

    public async ValueTask TickerChanged(string symbol, decimal price) => 
        await js.InvokeVoidAsync("displayTickerAlert1", symbol, price);

    // Calling SuppressFinalize(this) prevents derived types that introduce 
    // a finalizer from needing to re-implement IDisposable.
    public void Dispose() => GC.SuppressFinalize(this);
}
using Microsoft.JSInterop;

public class JsInteropClasses1 : IDisposable
{
    private readonly IJSRuntime js;

    public JsInteropClasses1(IJSRuntime js)
    {
        this.js = js;
    }

    public async ValueTask TickerChanged(string symbol, decimal price)
    {
        await js.InvokeVoidAsync("displayTickerAlert1", symbol, price);
    }

    public void Dispose()
    {
    }
}
using Microsoft.JSInterop;

public class JsInteropClasses1 : IDisposable
{
    private readonly IJSRuntime js;

    public JsInteropClasses1(IJSRuntime js)
    {
        this.js = js;
    }

    public async ValueTask TickerChanged(string symbol, decimal price)
    {
        await js.InvokeVoidAsync("displayTickerAlert1", symbol, price);
    }

    public void Dispose()
    {
    }
}
using System;
using System.Threading.Tasks;
using Microsoft.JSInterop;

public class JsInteropClasses1 : IDisposable
{
    private readonly IJSRuntime js;

    public JsInteropClasses1(IJSRuntime js)
    {
        this.js = js;
    }

    public async ValueTask TickerChanged(string symbol, decimal price)
    {
        await js.InvokeVoidAsync("displayTickerAlert1", symbol, price);
    }

    public void Dispose()
    {
    }
}
using System;
using System.Threading.Tasks;
using Microsoft.JSInterop;

public class JsInteropClasses1 : IDisposable
{
    private readonly IJSRuntime js;

    public JsInteropClasses1(IJSRuntime js)
    {
        this.js = js;
    }

    public async ValueTask TickerChanged(string symbol, decimal price)
    {
        await js.InvokeVoidAsync("displayTickerAlert1", symbol, price);
    }

    public void Dispose()
    {
    }
}

TickerChanged, aşağıdaki bileşende handleTickerChanged1 yöntemini çağırır.

CallJs3.razor:

@page "/call-js-3"
@implements IDisposable
@inject IJSRuntime JS

<PageTitle>Call JS 3</PageTitle>

<h1>Call JS Example 3</h1>

<p>
    <button @onclick="SetStock">Set Stock</button>
</p>

@if (stockSymbol is not null)
{
    <p>@stockSymbol price: @price.ToString("c")</p>
}

@code {
    private string? stockSymbol;
    private decimal price;
    private JsInteropClasses1? jsClass;

    protected override void OnInitialized() => jsClass = new(JS);

    private async Task SetStock()
    {
        if (jsClass is not null)
        {
            stockSymbol = 
                $"{(char)('A' + Random.Shared.Next(0, 26))}" +
                $"{(char)('A' + Random.Shared.Next(0, 26))}";
            price = Random.Shared.Next(1, 101);
            await jsClass.TickerChanged(stockSymbol, price);
        }
    }

    public void Dispose() => jsClass?.Dispose();
}

CallJs3.razor:

@page "/call-js-3"
@implements IDisposable
@inject IJSRuntime JS

<PageTitle>Call JS 3</PageTitle>

<h1>Call JS Example 3</h1>

<p>
    <button @onclick="SetStock">Set Stock</button>
</p>

@if (stockSymbol is not null)
{
    <p>@stockSymbol price: @price.ToString("c")</p>
}

@code {
    private string? stockSymbol;
    private decimal price;
    private JsInteropClasses1? jsClass;

    protected override void OnInitialized() => jsClass = new(JS);

    private async Task SetStock()
    {
        if (jsClass is not null)
        {
            stockSymbol = 
                $"{(char)('A' + Random.Shared.Next(0, 26))}" +
                $"{(char)('A' + Random.Shared.Next(0, 26))}";
            price = Random.Shared.Next(1, 101);
            await jsClass.TickerChanged(stockSymbol, price);
        }
    }

    public void Dispose() => jsClass?.Dispose();
}

CallJsExample3.razor:

@page "/call-js-example-3"
@implements IDisposable
@inject IJSRuntime JS

<h1>Call JS Example 3</h1>

<p>
    <button @onclick="SetStock">Set Stock</button>
</p>

@if (stockSymbol is not null)
{
    <p>@stockSymbol price: @price.ToString("c")</p>
}

@code {
    private string? stockSymbol;
    private decimal price;
    private JsInteropClasses1? jsClass;

    protected override void OnInitialized()
    {
        jsClass = new(JS);
    }

    private async Task SetStock()
    {
        if (jsClass is not null)
        {
            stockSymbol = 
                $"{(char)('A' + Random.Shared.Next(0, 26))}{(char)('A' + Random.Shared.Next(0, 26))}";
            price = Random.Shared.Next(1, 101);
            await jsClass.TickerChanged(stockSymbol, price);
        }
    }

    public void Dispose() => jsClass?.Dispose();
}

CallJsExample3.razor:

@page "/call-js-example-3"
@implements IDisposable
@inject IJSRuntime JS

<h1>Call JS Example 3</h1>

<p>
    <button @onclick="SetStock">Set Stock</button>
</p>

@if (stockSymbol is not null)
{
    <p>@stockSymbol price: @price.ToString("c")</p>
}

@code {
    private string? stockSymbol;
    private decimal price;
    private JsInteropClasses1? jsClass;

    protected override void OnInitialized()
    {
        jsClass = new(JS);
    }

    private async Task SetStock()
    {
        if (jsClass is not null)
        {
            stockSymbol = 
                $"{(char)('A' + Random.Shared.Next(0, 26))}{(char)('A' + Random.Shared.Next(0, 26))}";
            price = Random.Shared.Next(1, 101);
            await jsClass.TickerChanged(stockSymbol, price);
        }
    }

    public void Dispose() => jsClass?.Dispose();
}

CallJsExample3.razor:

@page "/call-js-example-3"
@implements IDisposable
@inject IJSRuntime JS

<h1>Call JS Example 3</h1>

<p>
    <button @onclick="SetStock">Set Stock</button>
</p>

@if (stockSymbol is not null)
{
    <p>@stockSymbol price: @price.ToString("c")</p>
}

@code {
    private Random r = new();
    private string stockSymbol;
    private decimal price;
    private JsInteropClasses1 jsClass;

    protected override void OnInitialized()
    {
        jsClass = new(JS);
    }

    private async Task SetStock()
    {
        stockSymbol = 
            $"{(char)('A' + r.Next(0, 26))}{(char)('A' + r.Next(0, 26))}";
        price = r.Next(1, 101);
        await jsClass.TickerChanged(stockSymbol, price);
    }

    public void Dispose() => jsClass?.Dispose();
}

CallJsExample3.razor:

@page "/call-js-example-3"
@implements IDisposable
@inject IJSRuntime JS

<h1>Call JS Example 3</h1>

<p>
    <button @onclick="SetStock">Set Stock</button>
</p>

@if (stockSymbol != null)
{
    <p>@stockSymbol price: @price.ToString("c")</p>
}

@code {
    private Random r = new Random();
    private string stockSymbol;
    private decimal price;
    private JsInteropClasses1 jsClass;

    protected override void OnInitialized()
    {
        jsClass = new JsInteropClasses1(JS);
    }

    private async Task SetStock()
    {
        stockSymbol = 
            $"{(char)('A' + r.Next(0, 26))}{(char)('A' + r.Next(0, 26))}";
        price = r.Next(1, 101);
        await jsClass.TickerChanged(stockSymbol, price);
    }

    public void Dispose() => jsClass?.Dispose();
}

JavaScript işlevlerini çağırma ve döndürülen bir değeri okuma (InvokeAsync)

.NET'in bir JavaScript (InvokeAsync) çağrısının sonucunu okuması gerektiğinde kullanınJS.

Bir displayTickerAlert2JS işlev sağlayın. Aşağıdaki örnek, çağıranın görüntülemesi için bir dize döndürür:

<script>
  window.displayTickerAlert2 = (symbol, price) => {
    if (price < 20) {
      alert(`${symbol}: $${price}!`);
      return "User alerted in the browser.";
    } else {
      return "User NOT alerted.";
    }
  };
</script>

Not

Genel JS konumu hakkında yönergeler ve üretim uygulamalarına yönelik önerilerimiz için ASP.NET Core Blazor uygulamalarında JavaScript konumu bölümüne bakın.

Bileşen (.razor) örneği (InvokeAsync)

TickerChanged handleTickerChanged2 yöntemini çağırır ve döndürülen dizeyi aşağıdaki bileşende görüntüler.

CallJs4.razor:

@page "/call-js-4"
@inject IJSRuntime JS

<PageTitle>Call JS 4</PageTitle>

<h1>Call JS Example 4</h1>

<p>
    <button @onclick="SetStock">Set Stock</button>
</p>

@if (stockSymbol is not null)
{
    <p>@stockSymbol price: @price.ToString("c")</p>
}

@if (result is not null)
{
    <p>@result</p>
}

@code {
    private string? stockSymbol;
    private decimal price;
    private string? result;

    private async Task SetStock()
    {
        stockSymbol = 
            $"{(char)('A' + Random.Shared.Next(0, 26))}" +
            $"{(char)('A' + Random.Shared.Next(0, 26))}";
        price = Random.Shared.Next(1, 101);
        var interopResult = 
            await JS.InvokeAsync<string>("displayTickerAlert2", stockSymbol, price);
        result = $"Result of TickerChanged call for {stockSymbol} at " +
            $"{price.ToString("c")}: {interopResult}";
    }
}

CallJs4.razor:

@page "/call-js-4"
@inject IJSRuntime JS

<PageTitle>Call JS 4</PageTitle>

<h1>Call JS Example 4</h1>

<p>
    <button @onclick="SetStock">Set Stock</button>
</p>

@if (stockSymbol is not null)
{
    <p>@stockSymbol price: @price.ToString("c")</p>
}

@if (result is not null)
{
    <p>@result</p>
}

@code {
    private string? stockSymbol;
    private decimal price;
    private string? result;

    private async Task SetStock()
    {
        stockSymbol = 
            $"{(char)('A' + Random.Shared.Next(0, 26))}" +
            $"{(char)('A' + Random.Shared.Next(0, 26))}";
        price = Random.Shared.Next(1, 101);
        var interopResult = 
            await JS.InvokeAsync<string>("displayTickerAlert2", stockSymbol, price);
        result = $"Result of TickerChanged call for {stockSymbol} at " +
            $"{price.ToString("c")}: {interopResult}";
    }
}

CallJsExample4.razor:

@page "/call-js-example-4"
@inject IJSRuntime JS

<h1>Call JS Example 4</h1>

<p>
    <button @onclick="SetStock">Set Stock</button>
</p>

@if (stockSymbol is not null)
{
    <p>@stockSymbol price: @price.ToString("c")</p>
}

@if (result is not null)
{
    <p>@result</p>
}

@code {
    private string? stockSymbol;
    private decimal price;
    private string? result;

    private async Task SetStock()
    {
        stockSymbol = 
            $"{(char)('A' + Random.Shared.Next(0, 26))}{(char)('A' + Random.Shared.Next(0, 26))}";
        price = Random.Shared.Next(1, 101);
        var interopResult = 
            await JS.InvokeAsync<string>("displayTickerAlert2", stockSymbol, price);
        result = $"Result of TickerChanged call for {stockSymbol} at " +
            $"{price.ToString("c")}: {interopResult}";
    }
}

CallJsExample4.razor:

@page "/call-js-example-4"
@inject IJSRuntime JS

<h1>Call JS Example 4</h1>

<p>
    <button @onclick="SetStock">Set Stock</button>
</p>

@if (stockSymbol is not null)
{
    <p>@stockSymbol price: @price.ToString("c")</p>
}

@if (result is not null)
{
    <p>@result</p>
}

@code {
    private string? stockSymbol;
    private decimal price;
    private string? result;

    private async Task SetStock()
    {
        stockSymbol = 
            $"{(char)('A' + Random.Shared.Next(0, 26))}{(char)('A' + Random.Shared.Next(0, 26))}";
        price = Random.Shared.Next(1, 101);
        var interopResult = 
            await JS.InvokeAsync<string>("displayTickerAlert2", stockSymbol, price);
        result = $"Result of TickerChanged call for {stockSymbol} at " +
            $"{price.ToString("c")}: {interopResult}";
    }
}

CallJsExample4.razor:

@page "/call-js-example-4"
@inject IJSRuntime JS

<h1>Call JS Example 4</h1>

<p>
    <button @onclick="SetStock">Set Stock</button>
</p>

@if (stockSymbol is not null)
{
    <p>@stockSymbol price: @price.ToString("c")</p>
}

@if (result is not null)
{
    <p>@result</p>
}

@code {
    private Random r = new();
    private string stockSymbol;
    private decimal price;
    private string result;

    private async Task SetStock()
    {
        stockSymbol = 
            $"{(char)('A' + r.Next(0, 26))}{(char)('A' + r.Next(0, 26))}";
        price = r.Next(1, 101);
        var interopResult = 
            await JS.InvokeAsync<string>("displayTickerAlert2", stockSymbol, price);
        result = $"Result of TickerChanged call for {stockSymbol} at " +
            $"{price.ToString("c")}: {interopResult}";
    }
}

CallJsExample4.razor:

@page "/call-js-example-4"
@inject IJSRuntime JS

<h1>Call JS Example 4</h1>

<p>
    <button @onclick="SetStock">Set Stock</button>
</p>

@if (stockSymbol != null)
{
    <p>@stockSymbol price: @price.ToString("c")</p>
}

@if (result != null)
{
    <p>@result</p>
}

@code {
    private Random r = new Random();
    private string stockSymbol;
    private decimal price;
    private string result;

    private async Task SetStock()
    {
        stockSymbol = 
            $"{(char)('A' + r.Next(0, 26))}{(char)('A' + r.Next(0, 26))}";
        price = r.Next(1, 101);
        var interopResult = 
            await JS.InvokeAsync<string>("displayTickerAlert2", stockSymbol, price);
        result = $"Result of TickerChanged call for {stockSymbol} at " +
            $"{price.ToString("c")}: {interopResult}";
    }
}

Sınıf (.cs) örneği (InvokeAsync)

JsInteropClasses2.cs:

using Microsoft.JSInterop;

namespace BlazorSample;

public class JsInteropClasses2(IJSRuntime js) : IDisposable
{
    private readonly IJSRuntime js = js;

    public async ValueTask<string> TickerChanged(string symbol, decimal price) => 
        await js.InvokeAsync<string>("displayTickerAlert2", symbol, price);

    // Calling SuppressFinalize(this) prevents derived types that introduce 
    // a finalizer from needing to re-implement IDisposable.
    public void Dispose() => GC.SuppressFinalize(this);
}
using Microsoft.JSInterop;

namespace BlazorSample;

public class JsInteropClasses2(IJSRuntime js) : IDisposable
{
    private readonly IJSRuntime js = js;

    public async ValueTask<string> TickerChanged(string symbol, decimal price) => 
        await js.InvokeAsync<string>("displayTickerAlert2", symbol, price);

    // Calling SuppressFinalize(this) prevents derived types that introduce 
    // a finalizer from needing to re-implement IDisposable.
    public void Dispose() => GC.SuppressFinalize(this);
}
using Microsoft.JSInterop;

public class JsInteropClasses2 : IDisposable
{
    private readonly IJSRuntime js;

    public JsInteropClasses2(IJSRuntime js)
    {
        this.js = js;
    }

    public async ValueTask<string> TickerChanged(string symbol, decimal price)
    {
        return await js.InvokeAsync<string>("displayTickerAlert2", symbol, price);
    }

    public void Dispose()
    {
    }
}
using Microsoft.JSInterop;

public class JsInteropClasses2 : IDisposable
{
    private readonly IJSRuntime js;

    public JsInteropClasses2(IJSRuntime js)
    {
        this.js = js;
    }

    public async ValueTask<string> TickerChanged(string symbol, decimal price)
    {
        return await js.InvokeAsync<string>("displayTickerAlert2", symbol, price);
    }

    public void Dispose()
    {
    }
}
using System;
using System.Threading.Tasks;
using Microsoft.JSInterop;

public class JsInteropClasses2 : IDisposable
{
    private readonly IJSRuntime js;

    public JsInteropClasses2(IJSRuntime js)
    {
        this.js = js;
    }

    public async ValueTask<string> TickerChanged(string symbol, decimal price)
    {
        return await js.InvokeAsync<string>("displayTickerAlert2", symbol, price);
    }

    public void Dispose()
    {
    }
}
using System;
using System.Threading.Tasks;
using Microsoft.JSInterop;

public class JsInteropClasses2 : IDisposable
{
    private readonly IJSRuntime js;

    public JsInteropClasses2(IJSRuntime js)
    {
        this.js = js;
    }

    public async ValueTask<string> TickerChanged(string symbol, decimal price)
    {
        return await js.InvokeAsync<string>("displayTickerAlert2", symbol, price);
    }

    public void Dispose()
    {
    }
}

TickerChanged handleTickerChanged2 yöntemini çağırır ve döndürülen dizeyi aşağıdaki bileşende görüntüler.

CallJs5.razor:

@page "/call-js-5"
@implements IDisposable
@inject IJSRuntime JS

<PageTitle>Call JS 5</PageTitle>

<h1>Call JS Example 5</h1>

<p>
    <button @onclick="SetStock">Set Stock</button>
</p>

@if (stockSymbol is not null)
{
    <p>@stockSymbol price: @price.ToString("c")</p>
}

@if (result is not null)
{
    <p>@result</p>
}

@code {
    private string? stockSymbol;
    private decimal price;
    private JsInteropClasses2? jsClass;
    private string? result;

    protected override void OnInitialized() => jsClass = new(JS);

    private async Task SetStock()
    {
        if (jsClass is not null)
        {
            stockSymbol = 
                $"{(char)('A' + Random.Shared.Next(0, 26))}" +
                $"{(char)('A' + Random.Shared.Next(0, 26))}";
            price = Random.Shared.Next(1, 101);
            var interopResult = await jsClass.TickerChanged(stockSymbol, price);
            result = $"Result of TickerChanged call for {stockSymbol} at " +
                $"{price.ToString("c")}: {interopResult}";
        }
    }

    public void Dispose() => jsClass?.Dispose();
}

CallJs5.razor:

@page "/call-js-5"
@implements IDisposable
@inject IJSRuntime JS

<PageTitle>Call JS 5</PageTitle>

<h1>Call JS Example 5</h1>

<p>
    <button @onclick="SetStock">Set Stock</button>
</p>

@if (stockSymbol is not null)
{
    <p>@stockSymbol price: @price.ToString("c")</p>
}

@if (result is not null)
{
    <p>@result</p>
}

@code {
    private string? stockSymbol;
    private decimal price;
    private JsInteropClasses2? jsClass;
    private string? result;

    protected override void OnInitialized() => jsClass = new(JS);

    private async Task SetStock()
    {
        if (jsClass is not null)
        {
            stockSymbol = 
                $"{(char)('A' + Random.Shared.Next(0, 26))}" +
                $"{(char)('A' + Random.Shared.Next(0, 26))}";
            price = Random.Shared.Next(1, 101);
            var interopResult = await jsClass.TickerChanged(stockSymbol, price);
            result = $"Result of TickerChanged call for {stockSymbol} at " +
                $"{price.ToString("c")}: {interopResult}";
        }
    }

    public void Dispose() => jsClass?.Dispose();
}

CallJsExample5.razor:

@page "/call-js-example-5"
@implements IDisposable
@inject IJSRuntime JS

<h1>Call JS Example 5</h1>

<p>
    <button @onclick="SetStock">Set Stock</button>
</p>

@if (stockSymbol is not null)
{
    <p>@stockSymbol price: @price.ToString("c")</p>
}

@if (result is not null)
{
    <p>@result</p>
}

@code {
    private string? stockSymbol;
    private decimal price;
    private JsInteropClasses2? jsClass;
    private string? result;

    protected override void OnInitialized()
    {
        jsClass = new(JS);
    }

    private async Task SetStock()
    {
        if (jsClass is not null)
        {
            stockSymbol = 
                $"{(char)('A' + Random.Shared.Next(0, 26))}{(char)('A' + Random.Shared.Next(0, 26))}";
            price = Random.Shared.Next(1, 101);
            var interopResult = await jsClass.TickerChanged(stockSymbol, price);
            result = $"Result of TickerChanged call for {stockSymbol} at " +
                $"{price.ToString("c")}: {interopResult}";
        }
    }

    public void Dispose() => jsClass?.Dispose();
}

CallJsExample5.razor:

@page "/call-js-example-5"
@implements IDisposable
@inject IJSRuntime JS

<h1>Call JS Example 5</h1>

<p>
    <button @onclick="SetStock">Set Stock</button>
</p>

@if (stockSymbol is not null)
{
    <p>@stockSymbol price: @price.ToString("c")</p>
}

@if (result is not null)
{
    <p>@result</p>
}

@code {
    private string? stockSymbol;
    private decimal price;
    private JsInteropClasses2? jsClass;
    private string? result;

    protected override void OnInitialized()
    {
        jsClass = new(JS);
    }

    private async Task SetStock()
    {
        if (jsClass is not null)
        {
            stockSymbol = 
                $"{(char)('A' + Random.Shared.Next(0, 26))}{(char)('A' + Random.Shared.Next(0, 26))}";
            price = Random.Shared.Next(1, 101);
            var interopResult = await jsClass.TickerChanged(stockSymbol, price);
            result = $"Result of TickerChanged call for {stockSymbol} at " +
                $"{price.ToString("c")}: {interopResult}";
        }
    }

    public void Dispose() => jsClass?.Dispose();
}

CallJsExample5.razor:

@page "/call-js-example-5"
@implements IDisposable
@inject IJSRuntime JS

<h1>Call JS Example 5</h1>

<p>
    <button @onclick="SetStock">Set Stock</button>
</p>

@if (stockSymbol is not null)
{
    <p>@stockSymbol price: @price.ToString("c")</p>
}

@if (result is not null)
{
    <p>@result</p>
}

@code {
    private Random r = new();
    private string stockSymbol;
    private decimal price;
    private JsInteropClasses2 jsClass;
    private string result;

    protected override void OnInitialized()
    {
        jsClass = new(JS);
    }

    private async Task SetStock()
    {
        stockSymbol = 
            $"{(char)('A' + r.Next(0, 26))}{(char)('A' + r.Next(0, 26))}";
        price = r.Next(1, 101);
        var interopResult = await jsClass.TickerChanged(stockSymbol, price);
        result = $"Result of TickerChanged call for {stockSymbol} at " +
            $"{price.ToString("c")}: {interopResult}";
    }

    public void Dispose() => jsClass?.Dispose();
}

CallJsExample5.razor:

@page "/call-js-example-5"
@implements IDisposable
@inject IJSRuntime JS

<h1>Call JS Example 5</h1>

<p>
    <button @onclick="SetStock">Set Stock</button>
</p>

@if (stockSymbol != null)
{
    <p>@stockSymbol price: @price.ToString("c")</p>
}

@if (result != null)
{
    <p>@result</p>
}

@code {
    private Random r = new Random();
    private string stockSymbol;
    private decimal price;
    private JsInteropClasses2 jsClass;
    private string result;

    protected override void OnInitialized()
    {
        jsClass = new JsInteropClasses2(JS);
    }

    private async Task SetStock()
    {
        stockSymbol = 
            $"{(char)('A' + r.Next(0, 26))}{(char)('A' + r.Next(0, 26))}";
        price = r.Next(1, 101);
        var interopResult = await jsClass.TickerChanged(stockSymbol, price);
        result = $"Result of TickerChanged call for {stockSymbol} at " +
            $"{price.ToString("c")}: {interopResult}";
    }

    public void Dispose() => jsClass?.Dispose();
}

Dinamik içerik oluşturma senaryoları

BuildRenderTree ile dinamik içerik oluşturma için şu özniteliği kullanın[Inject]:

[Inject]
IJSRuntime JS { get; set; }

Önceden İşleme

Bu bölüm, bileşenleri önceden Razor oluşturan sunucu tarafı uygulamalar için geçerlidir. Prerendering, Prerender ASP.NET Core bileşenlerinde Razor kapsanmıştır.

Not

'de etkileşimli yönlendirmeBlazor Web Appiç gezinti, sunucudan yeni sayfa içeriği istemeyi içermez. Bu nedenle, iç sayfa istekleri için ön kayıt gerçekleşmez. Uygulama etkileşimli yönlendirmeyi benimsediyse, önyükleme davranışını gösteren bileşen örnekleri için tam sayfa yeniden yükleme gerçekleştirin. Daha fazla bilgi için bkz . Prerender ASP.NET Core Razor bileşenleri.

Bu bölüm, sunucu tarafı uygulamalar ve önceden Blazor WebAssembly bileşenlerini barındıran Razor uygulamalar için geçerlidir. Prerendering, ASP.NET Core Razor bileşenlerini MVC veya Razor Pages ile tümleştirme bölümünde ele alınmıştır.

Ön kayıt sırasında JavaScript'e (JS) çağrı yapılamaz. Aşağıdaki örnek, bir bileşenin başlatma mantığının bir parçası olarak JS etkileşimin, önceden render etme ile uyumlu bir şekilde nasıl kullanılabileceğini göstermektedir.

Aşağıdaki scrollElementIntoView işlev:

window.scrollElementIntoView = (element) => {
  element.scrollIntoView();
  return element.getBoundingClientRect().top;
}

Bileşen kodunda IJSRuntime.InvokeAsync işlevi çağırıldığı yerlerde, bileşen işlenene kadar HTML DOM öğesi bulunmadığından, JS sadece ElementReference içinde kullanılır ve önceki yaşam döngüsü yöntemlerinde kullanılmaz.

StateHasChanged (başvuru kaynağı), JS birlikte çalışma çağrısından alınan yeni durum ile bileşeni yeniden işleme kuyruğuna almak için çağrılır (daha fazla bilgi için bkz. ASP.NET Core Razor bileşeni işleme). Sonsuz döngü oluşturulmaz çünkü StateHasChanged, scrollPosition olduğunda yalnızca null çağrılır.

PrerenderedInterop.razor:

@page "/prerendered-interop"
@using Microsoft.AspNetCore.Components
@using Microsoft.JSInterop
@inject IJSRuntime JS

<PageTitle>Prerendered Interop</PageTitle>

<h1>Prerendered Interop Example</h1>

<div @ref="divElement" style="margin-top:2000px">
    Set value via JS interop call: <strong>@scrollPosition</strong>
</div>

@code {
    private ElementReference divElement;
    private double? scrollPosition;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender && scrollPosition is null)
        {
            scrollPosition = await JS.InvokeAsync<double>(
                "scrollElementIntoView", divElement);

            StateHasChanged();
        }
    }
}
@page "/prerendered-interop"
@using Microsoft.AspNetCore.Components
@using Microsoft.JSInterop
@inject IJSRuntime JS

<h1>Prerendered Interop Example</h1>

<div @ref="divElement" style="margin-top:2000px">
    Set value via JS interop call: <strong>@scrollPosition</strong>
</div>

@code {
    private ElementReference divElement;
    private double? scrollPosition;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender && scrollPosition is null)
        {
            scrollPosition = await JS.InvokeAsync<double>(
                "scrollElementIntoView", divElement);

            StateHasChanged();
        }
    }
}
@page "/prerendered-interop"
@using Microsoft.AspNetCore.Components
@using Microsoft.JSInterop
@inject IJSRuntime JS

<h1>Prerendered Interop Example</h1>

<div @ref="divElement" style="margin-top:2000px">
    Set value via JS interop call: <strong>@scrollPosition</strong>
</div>

@code {
    private ElementReference divElement;
    private double? scrollPosition;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender && scrollPosition is null)
        {
            scrollPosition = await JS.InvokeAsync<double>(
                "scrollElementIntoView", divElement);

            StateHasChanged();
        }
    }
}
@page "/prerendered-interop"
@using Microsoft.AspNetCore.Components
@using Microsoft.JSInterop
@inject IJSRuntime JS

<h1>Prerendered Interop Example</h1>

<div @ref="divElement" style="margin-top:2000px">
    Set value via JS interop call: <strong>@scrollPosition</strong>
</div>

@code {
    private ElementReference divElement;
    private double? scrollPosition;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender && scrollPosition is null)
        {
            scrollPosition = await JS.InvokeAsync<double>(
                "scrollElementIntoView", divElement);

            StateHasChanged();
        }
    }
}
@page "/prerendered-interop"
@using Microsoft.AspNetCore.Components
@using Microsoft.JSInterop
@inject IJSRuntime JS

<h1>Prerendered Interop Example</h1>

<div @ref="divElement" style="margin-top:2000px">
    Set value via JS interop call: <strong>@scrollPosition</strong>
</div>

@code {
    private ElementReference divElement;
    private double? scrollPosition;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender && scrollPosition is null)
        {
            scrollPosition = await JS.InvokeAsync<double>(
                "scrollElementIntoView", divElement);

            StateHasChanged();
        }
    }
}

Yukarıdaki örnek, istemciyi bir global fonksiyon ile kirletiyor. Üretim uygulamalarında daha iyi bir yaklaşım için bkz . JavaScript modüllerinde JavaScript yalıtımı.

İstemci tarafı bileşenlerinde senkron JS birlikte çalışma

Bu bölüm yalnızca istemci tarafı bileşenleri için geçerlidir.

JS birlikte çalışma çağrıları, çağrılan kodun zaman uyumlu veya zaman uyumsuz olmasına bakılmaksızın zaman uyumsuzdur. Çağrılar, bileşenlerin sunucu tarafı ve istemci tarafı işleme modları arasında uyumlu olduğundan emin olmak için zaman uyumsuz olarak yapılır. Sunucuda, tüm JS birlikte çalışma çağrıları bir ağ bağlantısı üzerinden gönderildiğinden asenkron olmalıdır.

Bileşeninizin yalnızca WebAssembly üzerinde çalıştığından eminseniz, zaman uyumlu birlikte çalışma çağrıları yapmayı tercih edebilirsiniz. Bu, zaman uyumsuz çağrılar yapmaktan biraz daha az işlem yüküne sahiptir ve sonuçları beklerken ara durum olmadığından daha az render döngüsüne neden olabilir.

İstemci tarafı bileşeninde .NET'ten JavaScript'e zaman uyumlu bir çağrı yapmak için IJSRuntime öğesini IJSInProcessRuntime öğesine yayın yaparak JS birlikte çalışmayı çağırın.

@inject IJSRuntime JS

...

@code {
    protected override void HandleSomeEvent()
    {
        var jsInProcess = (IJSInProcessRuntime)JS;
        var value = jsInProcess.Invoke<string>("javascriptFunctionIdentifier");
    }
}

.NET 5 veya sonraki istemci tarafı bileşenleriyle IJSObjectReference çalışırken, bunun yerine IJSInProcessObjectReference'i zaman uyumlu olarak kullanabilirsiniz. IJSInProcessObjectReference IAsyncDisposable / IDisposable uygular ve aşağıdaki örnekte gösterildiği gibi bellek sızıntısını önlemek için çöp toplama için atılmalıdır:

@inject IJSRuntime JS
@implements IDisposable

...

@code {
    ...
    private IJSInProcessObjectReference? module;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            var jsInProcess = (IJSInProcessRuntime)JS;
            module = await jsInProcess.Invoke<IJSInProcessObjectReference>("import", 
                "./scripts.js");
            var value = module.Invoke<string>("javascriptFunctionIdentifier");
        }
    }

    ...

    void IDisposable.Dispose()
    {
        if (module is not null)
        {
            await module.Dispose();
        }
    }
}

Önceki örnekte, bir JSDisconnectedException uygulamada kaybedilecek bir BlazorSignalR devresi olmadığından modül atma sırasında bir etkilenme söz konusu değildir. Daha fazla bilgi için bkz. ASP.NET Core Blazor JavaScript birlikte çalışabilirliği (JSbirlikte çalışma).

Oluşturucu işlevi kullanarak nesne JS örneği oluşturma

Oluşturucu işlevi kullanarak bir JS nesne örneği oluşturun ve aşağıdaki API ile örneğe başvurmak için IJSObjectReference/IJSInProcessObjectReference .NET tanıtıcısını alın:

  • InvokeNewAsync (zaman uyumsuz)
  • InvokeNew (zaman uyumlu)

Bu bölümdeki örneklerde, oluşturucu işleviyle TestClass ABC çağrıları (constructor(text)) gösterilmektedir.

window.TestClass = class {
  constructor(text) {
    this.text = text;
  }

  getTextLength() {
    return this.text.length;
  }
}

Asenkron InvokeNewAsync

Belirtilen InvokeNewAsync(string identifier, object?[]? args) oluşturucu işlevini zaman uyumsuz olarak çağırmak için IJSRuntime ve IJSObjectReference üzerinde JS kullanın. İşlev, new işleciyle çağrılır. Aşağıdaki örnekte, TestClass bir oluşturucu işlevi içerir ve classRef bir IJSObjectReference'dir.

var classRef = await JSRuntime.InvokeNewAsync("TestClass", "Blazor!");
var text = await classRef.GetValueAsync<string>("text");
var textLength = await classRef.InvokeAsync<int>("getTextLength");

CancellationToken bağımsız değişkeni veya TimeSpan zaman aşımı bağımsız değişkeni alan bir aşırı yükleme kullanılabilir.

Eşzamanlı InvokeNew

InvokeNew(string identifier, object?[]? args) oluşturucu işlevini eşzamanlı olarak çağırmak için IJSInProcessRuntime, IJSInProcessObjectReference ve JS kullanın. İşlev, new işleciyle çağrılır. Aşağıdaki örnekte, TestClass bir oluşturucu işlevi içerir ve classRef bir IJSInProcessObjectReference'dir:

var inProcRuntime = ((IJSInProcessRuntime)JSRuntime);
var classRef = inProcRuntime.InvokeNew("TestClass", "Blazor!");
var text = classRef.GetValue<string>("text");
var textLength = classRef.Invoke<int>("getTextLength");

CancellationToken bağımsız değişkeni veya TimeSpan zaman aşımı bağımsız değişkeni alan bir aşırı yükleme kullanılabilir.

Nesne özelliğinin JS değerini okuma veya değiştirme

Aşağıdaki API ile hem veri hem de erişimci özellikleri olan nesne JS özelliğinin değerini okuyun veya değiştirin:

  • GetValueAsync / SetValueAsync (zaman uyumsuz)
  • GetValue / SetValue (zaman uyumlu)

Bu bölümdeki örneklerde aşağıdaki JS nesneye (testObject) sahip API çağrıları gösterilmektedir:

window.testObject = {
  num: 10
}

Eşzamansız GetValueAsync ve SetValueAsync

Belirtilen GetValueAsync<TValue>(string identifier) özelliğin değerini zaman uyumsuz olarak okumak için kullanınJS. Eğer JSException özelliği mevcut değilse veya set-sadece bir özellikse, bir istisna fırlatılır. Aşağıdaki örnekte (10) değeri testObject.num içinde valueFromDataPropertyAsyncdepolanır:

var valueFromDataPropertyAsync = 
    await JSRuntime.GetValueAsync<int>("testObject.num");

Belirtilen SetValueAsync<TValue>(string identifier, TValue value) özelliğin değerini zaman uyumsuz olarak güncelleştirmek için kullanınJS. Özellik hedef nesnede tanımlanmamışsa, özelliği oluşturulur. JSException özelliği varsa ancak yazılabilir değilse veya nesneye yeni bir özellik eklenemiyorsa atılır. Aşağıdaki örnekte, testObject.num 20 olarak ayarlanır ve num2 üzerinde testObject30 değeriyle oluşturulur:

await JSRuntime.SetValueAsync("testObject.num", 20);
await JSRuntime.SetValueAsync("testObject.num2", 30);

Senkron GetValue ve SetValue

Belirtilen GetValue<TValue>(string identifier) özelliğin değerini zaman uyumlu olarak okumak için kullanınJS. Eğer JSException özelliği mevcut değilse veya set-sadece bir özellikse, bir istisna fırlatılır. Aşağıdaki örnekte (10) değeri testObject.num içinde valueFromDataPropertydepolanır:

var inProcRuntime = ((IJSInProcessRuntime)JSRuntime);
var valueFromDataProperty = inProcRuntime.GetValue<int>("testObject.num");

Belirtilen SetValue<TValue>(string identifier, TValue value) özelliğin değerini zaman uyumlu olarak güncelleştirmek için kullanınJS. Özellik yalnızca bir get özelliği olamaz. Özellik hedef nesnede tanımlanmamışsa, özelliği oluşturulur. JSException özelliği varsa ancak yazılabilir değilse veya nesneye yeni bir özellik eklenemiyorsa atılır. Aşağıdaki örnekte, testObject.num 20 olarak ayarlanır ve num2 üzerinde testObject30 değeriyle oluşturulur:

var inProcRuntime = ((IJSInProcessRuntime)JSRuntime);
inProcRuntime.SetValue("testObject.num", 20);
inProcRuntime.SetValue("testObject.num2", 30);

JavaScript konumu

JavaScript (JS) kodunu, JavaScript konumlandırma makalesinde açıklanan yaklaşımlardan herhangi birini kullanarak yükleyin.

Modüllerdeki JS hakkında bilgi için JavaScript modüllerinde JavaScript yalıtımı bölümüne bakın.

Uyarı

Etiket dinamik olarak güncelleştirilemediğinden, yalnızca bileşenin statik sunucu tarafı işlemeyi (statik SSR) benimsemesi garanti edilirse bir bileşen dosyasına (<script>) etiket yerleştirin.razor.<script>

Uyarı

Etiket dinamik olarak güncelleştirilemediğinden <script> bir etiketi bileşen dosyasına (.razor) yerleştirmeyin<script>.

JavaScript modüllerinde JavaScript yalıtımı

Blazor, standart JavaScript (JS) modüllerinde () JavaScript izolasyonunu etkinleştirir (ECMAScript belirtimi). JavaScript modülü yükleme işlemi, diğer web uygulaması türleriyle aynı şekilde Blazor çalışır ve modüllerin uygulamanızda nasıl tanımlandığını özelleştirebilirsiniz. JavaScript modüllerini kullanma kılavuzu için bkz . MDN Web Belgeleri: JavaScript modülleri.

JS yalıtımı aşağıdaki avantajları sağlar:

  • İçeri aktarılan JS artık genel ad alanını kirletmez.
  • Kütüphane ve bileşen kullanıcılarının ilgili JS'yi dışarıdan yüklemesi gerekmez.

işleciyle import() dinamik içeri aktarma, ASP.NET Core ve Blazorile desteklenir:

if ({CONDITION}) import("/additionalModule.js");

Önceki örnekte, {CONDITION} yer tutucusu, modülün yüklenip yüklenmeyeceğini belirlemek için koşullu bir denetimi temsil eder.

Tarayıcı uyumluluğu için bkz . Kullanabilir miyim: JavaScript modülleri: dinamik içeri aktarma.

Sunucu tarafı senaryolarında, JS bağlantı hattı kesildikten sonra BlazorSignalR birlikte çalışma çağrıları düzenlenemez. Bileşenin atılması sırasında veya başka bir zamanda bir bağlantı hattı olmadığında, aşağıdaki yöntem çağrıları başarısız olur ve bağlantı hattının bağlantısının kesildiğini belirten bir JSDisconnectedExceptionileti kaydeder:

Sunucu tarafında JSDisconnectedException günlüğe kaydetmeyi Blazor önlemek veya özelleştirilmiş bilgiyi günlüğe kaydetmek için, bir deneme-yakalama bloğunda try-catch istisnayı yakalayın.

Aşağıdaki bileşenin elden çıkarılması örneği için:

  • Sunucu tarafı bileşeni, IAsyncDisposable'i uygular.
  • module bir IJSObjectReference modülü için JS'tir.
  • JSDisconnectedException yakalanmış ve günlüğe kaydedilmemiş.
  • İsteğe bağlı olarak, catch ifadesinde istediğiniz log seviyesinde özel bilgiler kaydedebilirsiniz. Aşağıdaki örnek özel bilgileri günlüğe kaydetmez. Kod, geliştiricinin bileşen elden çıkarma sırasında devrelerin ne zaman veya nerede kesildiğini umursamadığını varsayar.
async ValueTask IAsyncDisposable.DisposeAsync()
{
    try
    {
        if (module is not null)
        {
            await module.DisposeAsync();
        }
    }
    catch (JSDisconnectedException)
    {
    }
}

Sunucu tarafı bir JS uygulamasında bir bağlantı hattı kaybolduktan sonra, kendi JS nesnelerinizi temizlemeniz veya istemcide başka Blazor kod yürütmeniz gerekiyorsa, istemcide MutationObserver içinde JS desenini kullanın. Desen, MutationObserver DOM'dan bir öğe kaldırıldığında kod yürütmenize JS olanak tanır.

Daha fazla bilgi için aşağıdaki makaleleri inceleyin:

Aşağıdaki JS modül, tarayıcı JS penceresi istemini göstermek için bir işlevi dışarı aktarır. Aşağıdaki JS kodu bir dış JS dosyaya yerleştirin.

wwwroot/scripts.js:

export function showPrompt(message) {
  return prompt(message, 'Type anything here');
}

Önceki JS modülünü wwwroot klasöründe bir statik web varlığı olarak bir uygulamaya veya sınıf kitaplığına ekleyin ve ardından InvokeAsync örneğinde IJSRuntime çağrısını yaparak modülü .NET koduna dahil edin.

IJSRuntime modülü IJSObjectReferenceolarak içeri aktarır. Bu, .NET kodundan bir JS nesneye başvuruyu temsil eder. Modülden dışarı aktarılan IJSObjectReference işlevleri çağırmak için komutunu JS kullanın.

CallJs6.razor:

@page "/call-js-6"
@implements IAsyncDisposable
@inject IJSRuntime JS

<PageTitle>Call JS 6</PageTitle>

<h1>Call JS Example 6</h1>

<p>
    <button @onclick="TriggerPrompt">Trigger browser window prompt</button>
</p>

<p>
    @result
</p>

@code {
    private IJSObjectReference? module;
    private string? result;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            module = await JS.InvokeAsync<IJSObjectReference>("import",
                "./scripts.js");
        }
    }

    private async Task TriggerPrompt() => result = await Prompt("Provide text");

    public async ValueTask<string?> Prompt(string message) =>
        module is not null ? 
            await module.InvokeAsync<string>("showPrompt", message) : null;

    async ValueTask IAsyncDisposable.DisposeAsync()
    {
        if (module is not null)
        {
            try
            {
                await module.DisposeAsync();
            }
            catch (JSDisconnectedException)
            {
            }
        }
    }
}

CallJs6.razor:

@page "/call-js-6"
@implements IAsyncDisposable
@inject IJSRuntime JS

<PageTitle>Call JS 6</PageTitle>

<h1>Call JS Example 6</h1>

<p>
    <button @onclick="TriggerPrompt">Trigger browser window prompt</button>
</p>

<p>
    @result
</p>

@code {
    private IJSObjectReference? module;
    private string? result;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            module = await JS.InvokeAsync<IJSObjectReference>("import",
                "./scripts.js");
        }
    }

    private async Task TriggerPrompt() => result = await Prompt("Provide text");

    public async ValueTask<string?> Prompt(string message) =>
        module is not null ? 
            await module.InvokeAsync<string>("showPrompt", message) : null;

    async ValueTask IAsyncDisposable.DisposeAsync()
    {
        if (module is not null)
        {
            try
            {
                await module.DisposeAsync();
            }
            catch (JSDisconnectedException)
            {
            }
        }
    }
}

CallJsExample6.razor:

@page "/call-js-example-6"
@implements IAsyncDisposable
@inject IJSRuntime JS

<h1>Call JS Example 6</h1>

<p>
    <button @onclick="TriggerPrompt">Trigger browser window prompt</button>
</p>

<p>
    @result
</p>

@code {
    private IJSObjectReference? module;
    private string? result;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            module = await JS.InvokeAsync<IJSObjectReference>("import", 
                "./scripts.js");
        }
    }

    private async Task TriggerPrompt()
    {
        result = await Prompt("Provide some text");
    }

    public async ValueTask<string?> Prompt(string message) =>
        module is not null ? 
            await module.InvokeAsync<string>("showPrompt", message) : null;

    async ValueTask IAsyncDisposable.DisposeAsync()
    {
        if (module is not null)
        {
            await module.DisposeAsync();
        }
    }
}

CallJsExample6.razor:

@page "/call-js-example-6"
@implements IAsyncDisposable
@inject IJSRuntime JS

<h1>Call JS Example 6</h1>

<p>
    <button @onclick="TriggerPrompt">Trigger browser window prompt</button>
</p>

<p>
    @result
</p>

@code {
    private IJSObjectReference? module;
    private string? result;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            module = await JS.InvokeAsync<IJSObjectReference>("import", 
                "./scripts.js");
        }
    }

    private async Task TriggerPrompt()
    {
        result = await Prompt("Provide some text");
    }

    public async ValueTask<string?> Prompt(string message) =>
        module is not null ? 
            await module.InvokeAsync<string>("showPrompt", message) : null;

    async ValueTask IAsyncDisposable.DisposeAsync()
    {
        if (module is not null)
        {
            await module.DisposeAsync();
        }
    }
}

CallJsExample6.razor:

@page "/call-js-example-6"
@implements IAsyncDisposable
@inject IJSRuntime JS

<h1>Call JS Example 6</h1>

<p>
    <button @onclick="TriggerPrompt">Trigger browser window prompt</button>
</p>

<p>
    @result
</p>

@code {
    private IJSObjectReference module;
    private string result;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            module = await JS.InvokeAsync<IJSObjectReference>("import", 
                "./scripts.js");
        }
    }

    private async Task TriggerPrompt()
    {
        result = await Prompt("Provide some text");
    }

    public async ValueTask<string> Prompt(string message)
    {
        return await module.InvokeAsync<string>("showPrompt", message);
    }

    async ValueTask IAsyncDisposable.DisposeAsync()
    {
        if (module is not null)
        {
            await module.DisposeAsync();
        }
    }
}

Yukarıdaki örnekte:

  • Kural gereği import tanımlayıcı, bir JS modülünü içeri aktarmak için spesifik olarak kullanılan özel bir tanımlayıcıdır.
  • Modülün dış JS dosyasını kararlı statik web varlığı yolunu kullanarak belirtin: ./{SCRIPT PATH AND FILE NAME (.js)}burada:
    • ./ dosyasının doğru statik varlık yolunu oluşturabilmek için geçerli dizinin yol segmenti (JS) gereklidir.
    • {SCRIPT PATH AND FILE NAME (.js)} yer tutucusu, wwwroot altındaki yol ve dosya adıdır.
  • Çöp toplama için IJSObjectReference'yi içinde atar.
  • <script> çağrıldığında modül yüklenip önbelleğe otomatik olarak alınacağından, Blazor sonrasına betik için etiketi yerleştirmeyin.

Bir modülü dinamik olarak içeri aktarmak için bir ağ isteği gerekir, bu nedenle yalnızca InvokeAsync çağrılarak zaman uyumsuz bir şekilde gerçekleştirilebilir.

IJSInProcessObjectReference , işlevleri istemci tarafı bileşenlerinde zaman uyumlu olarak çağrılabilen bir JS nesneye başvuru temsil eder. Daha fazla bilgi için istemci tarafı bileşenlerinde zaman uyumlu JS birlikte çalışma bölümüne bakın.

Not

Dış JS dosya bir Razor sınıf kitaplığı tarafından sağlandığında, modülün JS dosyasını kararlı statik web varlığı yolunu kullanarak belirtin: : ./_content/{PACKAGE ID}/{SCRIPT PATH AND FILE NAME (.js)}

  • ./ dosyasının doğru statik varlık yolunu oluşturabilmek için geçerli dizinin yol segmenti (JS) gereklidir.
  • {PACKAGE ID} yer tutucusu, kitaplığın paket kimliğidir. Proje dosyasında <PackageId> belirtilmediyse varsayılan olarak projenin derleme adı paket kimliği olur. Aşağıdaki örnekte, ComponentLibrary kitaplığın derleme adıdır ve kitaplığın proje dosyasında <PackageId> belirtilmemiştir.
  • {SCRIPT PATH AND FILE NAME (.js)} yer tutucusu, wwwroot altındaki yol ve dosya adıdır. Aşağıdaki örnekte, dış JS dosya (script.js) sınıf kitaplığının wwwroot klasörüne yerleştirilir.
  • module, bileşen sınıfı IJSObjectReference'nin özel null atanabilir private IJSObjectReference? module; değeridir.
module = await js.InvokeAsync<IJSObjectReference>(
    "import", "./_content/ComponentLibrary/scripts.js");

Daha fazla bilgi için bkz. Razor sınıf kitaplığından (RCL) ASP.NET Core Razor bileşenlerini kullanma.

Belgeler boyunca Blazor, örnekler .js dosya uzantısını modül dosyaları için kullanır, yeni .mjs dosya uzantısını (RFC 9239) değil. Belgelerimiz, Mozilla Foundation belgelerinin .js dosya uzantısını kullanmaya devam etmesiyle aynı nedenlerle dosya uzantısını .js kullanmaya devam ediyor. Daha fazla bilgi için bkz. Aside — .mjs versus .js (MDN belgeleri).

Öğelere atıfları yakalama

Bazı JavaScript (JS) birlikte çalışma senaryolarında HTML öğelerine başvurular gerekir. Örneğin, kullanıcı arabirimi kitaplığı başlatma için bir öğe başvurusu gerektirebilir veya veya clickgibi play bir öğede komut benzeri API'leri çağırmanız gerekebilir.

Aşağıdaki yaklaşımı kullanarak bir bileşendeki HTML öğelerine yönelik başvuruları yakalayın:

  • HTML öğesine bir @ref öznitelik ekleyin.
  • Adı özniteliğin değeriyle ElementReference eşleşen türde @ref bir alan tanımlayın.

Aşağıdaki örnek, username<input> öğesine bir başvuru yakalamayı göstermektedir:

<input @ref="username" ... />

@code {
    private ElementReference username;
}

Uyarı

yalnızca Blazor ile etkileşimde bulunmayan boş bir öğenin içeriğini değiştirmek için bir öğe referansı kullanın. Bu senaryo, bir üçüncü taraf API öğeye içerik sağladığında kullanışlıdır. Blazor öğesiyle etkileşim kurmadığından, öğesinin gösterimi ile DOM arasında Blazorçakışma olasılığı yoktur.

Aşağıdaki örnekte, interop kullanarak ul ile sırasız listenin (MyList) içeriğini değiştirmek JSdir çünkü Blazor nesneden (<li>) bu öğenin liste öğelerini (Todos) doldurmak için DOM ile etkileşime girer.

<ul @ref="MyList">
    @foreach (var item in Todos)
    {
        <li>@item.Text</li>
    }
</ul>

MyList Yalnızca DOM içeriğini okumak veya bir olayı tetiklemek için öğe başvurusunun kullanılması desteklenir.

Eğer JS etkileşim öğenin içeriğini değiştirirse, ve MyList öğeye farkları uygulamaya çalışırsa Blazor, farklar DOM ile eşleşmeyecektir. JS interop ile MyList öğesi referansı aracılığıyla listenin içeriğinin değiştirilmesi desteklenmez.

Daha fazla bilgi için bkz. ASP.NET Core Blazor JavaScript birlikte çalışabilirliği (JSbirlikte çalışma).

Bir ElementReference, JS birlikte çalışabilirliği aracılığıyla JS koduna iletilir. Kod JS , normal DOM API'leriyle kullanabileceği bir HTMLElement örnek alır. Örneğin, aşağıdaki kod bir öğeye fare tıklaması göndermeyi sağlayan bir .NET uzantısı yöntemini (TriggerClickEvent) tanımlar.

Fonksiyon JS, geçirilen HTML öğesi (clickElement) üzerinde bir click olayı oluşturur (element):

window.interopFunctions = {
  clickElement : function (element) {
    element.click();
  }
}

Değer döndürmeyen bir JS işlevi çağırmak için kullanın JSRuntimeExtensions.InvokeVoidAsync. Aşağıdaki kod, yakalanan click kullanarak önceki JS işlevini çağırarak istemci tarafı ElementReference olayını tetikler.

@inject IJSRuntime JS

<button @ref="exampleButton">Example Button</button>

<button @onclick="TriggerClick">
    Trigger click event on <code>Example Button</code>
</button>

@code {
    private ElementReference exampleButton;

    public async Task TriggerClick()
    {
        await JS.InvokeVoidAsync(
            "interopFunctions.clickElement", exampleButton);
    }
}

Uzantı yöntemi kullanmak için, IJSRuntime örneğini kullanacak olan statik bir uzantı yöntemi oluşturun.

public static async Task TriggerClickEvent(this ElementReference elementRef, 
    IJSRuntime js)
{
    await js.InvokeVoidAsync("interopFunctions.clickElement", elementRef);
}

clickElement yöntemi doğrudan nesne üzerinde çağrılır. Aşağıdaki örnek, TriggerClickEvent yönteminin JsInteropClasses ad alanında mevcut olduğunu varsayar:

@inject IJSRuntime JS
@using JsInteropClasses

<button @ref="exampleButton">Example Button</button>

<button @onclick="TriggerClick">
    Trigger click event on <code>Example Button</code>
</button>

@code {
    private ElementReference exampleButton;

    public async Task TriggerClick()
    {
        await exampleButton.TriggerClickEvent(JS);
    }
}

Önemli

exampleButton Değişken yalnızca bileşen işlendikten sonra doldurulur. Doldurulmamış ElementReference, bir kod parçasına geçirilirse, JS kodu JS değerini alır. Bileşenin işlenmesi tamamlandıktan sonra öğe referanslarını düzenlemek için bileşen yaşam döngüsü yöntemlerini kullanın: OnAfterRenderAsync veya OnAfterRender.

Genel türlerle çalışırken ve bir değer döndürürken kullanın ValueTask<TResult>:

public static ValueTask<T> GenericMethod<T>(
        this ElementReference elementRef, IJSRuntime js) => 
    js.InvokeAsync<T>("{JAVASCRIPT FUNCTION}", elementRef);

{JAVASCRIPT FUNCTION} yer tutucu, JS işlev tanımlayıcısıdır.

GenericMethod belirli bir türü olan nesne üzerinde doğrudan çağrılır. Aşağıdaki örnekte, GenericMethod ad alanı JsInteropClasses aracılığıyla kullanılabilir olduğu varsayılır:

@inject IJSRuntime JS
@using JsInteropClasses

<input @ref="username" />

<button @onclick="OnClickMethod">Do something generic</button>

<p>
    returnValue: @returnValue
</p>

@code {
    private ElementReference username;
    private string? returnValue;

    private async Task OnClickMethod()
    {
        returnValue = await username.GenericMethod<string>(JS);
    }
}
@inject IJSRuntime JS
@using JsInteropClasses

<input @ref="username" />

<button @onclick="OnClickMethod">Do something generic</button>

<p>
    returnValue: @returnValue
</p>

@code {
    private ElementReference username;
    private string? returnValue;

    private async Task OnClickMethod()
    {
        returnValue = await username.GenericMethod<string>(JS);
    }
}
@inject IJSRuntime JS
@using JsInteropClasses

<input @ref="username" />

<button @onclick="OnClickMethod">Do something generic</button>

<p>
    returnValue: @returnValue
</p>

@code {
    private ElementReference username;
    private string returnValue;

    private async Task OnClickMethod()
    {
        returnValue = await username.GenericMethod<string>(JS);
    }
}

Bileşenler arasında başvuru öğeleri

ElementReference Bileşenler arasında geçirilemiyor çünkü:

Bir üst bileşenin bir öğe başvuruyu diğer bileşenler için kullanılabilir hale getirmesi için, üst bileşen şunları yapabilir:

  • Alt bileşenlerin geri çağırmaları kaydetmesine izin verin.
  • Aktarılmış öğe referansıyla, OnAfterRender olayı sırasında kayıtlı geri çağırmaları çağırın. Dolaylı olarak, bu yaklaşım alt bileşenlerin ebeveyn öğenin referansıyla etkileşim kurmasına olanak tanır.
<style>
    .red { color: red }
</style>
<script>
  function setElementClass(element, className) {
    var myElement = element;
    myElement.classList.add(className);
  }
</script>

Not

Genel JS konumu hakkında yönergeler ve üretim uygulamalarına yönelik önerilerimiz için ASP.NET Core Blazor uygulamalarında JavaScript konumu bölümüne bakın.

CallJs7.razor (üst bileşen):

@page "/call-js-7"

<PageTitle>Call JS 7</PageTitle>

<h1>Call JS Example 7</h1>

<h2 @ref="title">Hello, world!</h2>

Welcome to your new app.

<SurveyPrompt Parent="this" Title="How is Blazor working for you?" />

CallJs7.razor (üst bileşen):

@page "/call-js-7"

<PageTitle>Call JS 7</PageTitle>

<h1>Call JS Example 7</h1>

<h2 @ref="title">Hello, world!</h2>

Welcome to your new app.

<SurveyPrompt Parent="this" Title="How is Blazor working for you?" />

CallJsExample7.razor (üst bileşen):

@page "/call-js-example-7"

<h1>Call JS Example 7</h1>

<h2 @ref="title">Hello, world!</h2>

Welcome to your new app.

<SurveyPrompt Parent="this" Title="How is Blazor working for you?" />

CallJsExample7.razor (üst bileşen):

@page "/call-js-example-7"

<h1>Call JS Example 7</h1>

<h2 @ref="title">Hello, world!</h2>

Welcome to your new app.

<SurveyPrompt Parent="this" Title="How is Blazor working for you?" />

CallJsExample7.razor (üst bileşen):

@page "/call-js-example-7"

<h1>Call JS Example 7</h1>

<h2 @ref="title">Hello, world!</h2>

Welcome to your new app.

<SurveyPrompt Parent="this" Title="How is Blazor working for you?" />

CallJsExample7.razor (üst bileşen):

@page "/call-js-example-7"

<h1>Call JS Example 7</h1>

<h2 @ref="title">Hello, world!</h2>

Welcome to your new app.

<SurveyPrompt Parent="this" Title="How is Blazor working for you?" />

CallJs7.razor.cs:

using Microsoft.AspNetCore.Components;

namespace BlazorSample.Pages;

public partial class CallJs7 : 
    ComponentBase, IObservable<ElementReference>, IDisposable
{
    private bool disposing;
    private readonly List<IObserver<ElementReference>> subscriptions = [];
    private ElementReference title;

    protected override void OnAfterRender(bool firstRender)
    {
        base.OnAfterRender(firstRender);

        foreach (var subscription in subscriptions)
        {
            subscription.OnNext(title);
        }
    }

    public void Dispose()
    {
        disposing = true;

        foreach (var subscription in subscriptions)
        {
            try
            {
                subscription.OnCompleted();
            }
            catch (Exception)
            {
            }
        }

        subscriptions.Clear();

        // The following prevents derived types that introduce a
        // finalizer from needing to re-implement IDisposable.
        GC.SuppressFinalize(this);
    }

    public IDisposable Subscribe(IObserver<ElementReference> observer)
    {
        if (disposing)
        {
            throw new InvalidOperationException("Parent being disposed");
        }

        subscriptions.Add(observer);

        return new Subscription(observer, this);
    }

    private class Subscription(IObserver<ElementReference> observer,
        CallJs7 self) : IDisposable
    {
        public IObserver<ElementReference> Observer { get; } = observer;
        public CallJs7 Self { get; } = self;

        public void Dispose() => Self.subscriptions.Remove(Observer);
    }
}

CallJs7.razor.cs:

using Microsoft.AspNetCore.Components;

namespace BlazorSample.Pages;

public partial class CallJs7 : 
    ComponentBase, IObservable<ElementReference>, IDisposable
{
    private bool disposing;
    private readonly List<IObserver<ElementReference>> subscriptions = [];
    private ElementReference title;

    protected override void OnAfterRender(bool firstRender)
    {
        base.OnAfterRender(firstRender);

        foreach (var subscription in subscriptions)
        {
            subscription.OnNext(title);
        }
    }

    public void Dispose()
    {
        disposing = true;

        foreach (var subscription in subscriptions)
        {
            try
            {
                subscription.OnCompleted();
            }
            catch (Exception)
            {
            }
        }

        subscriptions.Clear();

        // The following prevents derived types that introduce a
        // finalizer from needing to re-implement IDisposable.
        GC.SuppressFinalize(this);
    }

    public IDisposable Subscribe(IObserver<ElementReference> observer)
    {
        if (disposing)
        {
            throw new InvalidOperationException("Parent being disposed");
        }

        subscriptions.Add(observer);

        return new Subscription(observer, this);
    }

    private class Subscription(IObserver<ElementReference> observer,
        CallJs7 self) : IDisposable
    {
        public IObserver<ElementReference> Observer { get; } = observer;
        public CallJs7 Self { get; } = self;

        public void Dispose() => Self.subscriptions.Remove(Observer);
    }
}

CallJsExample7.razor.cs:

using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Components;

namespace BlazorSample.Pages;

public partial class CallJsExample7 : 
    ComponentBase, IObservable<ElementReference>, IDisposable
{
    private bool disposing;
    private IList<IObserver<ElementReference>> subscriptions = 
        new List<IObserver<ElementReference>>();
    private ElementReference title;

    protected override void OnAfterRender(bool firstRender)
    {
        base.OnAfterRender(firstRender);

        foreach (var subscription in subscriptions)
        {
            subscription.OnNext(title);
        }
    }

    public void Dispose()
    {
        disposing = true;

        foreach (var subscription in subscriptions)
        {
            try
            {
                subscription.OnCompleted();
            }
            catch (Exception)
            {
            }
        }

        subscriptions.Clear();
    }

    public IDisposable Subscribe(IObserver<ElementReference> observer)
    {
        if (disposing)
        {
            throw new InvalidOperationException("Parent being disposed");
        }

        subscriptions.Add(observer);

        return new Subscription(observer, this);
    }

    private class Subscription : IDisposable
    {
        public Subscription(IObserver<ElementReference> observer, 
            CallJsExample7 self)
        {
            Observer = observer;
            Self = self;
        }

        public IObserver<ElementReference> Observer { get; }
        public CallJsExample7 Self { get; }

        public void Dispose()
        {
            Self.subscriptions.Remove(Observer);
        }
    }
}

CallJsExample7.razor.cs:

using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Components;

namespace BlazorSample.Pages;

public partial class CallJsExample7 : 
    ComponentBase, IObservable<ElementReference>, IDisposable
{
    private bool disposing;
    private IList<IObserver<ElementReference>> subscriptions = 
        new List<IObserver<ElementReference>>();
    private ElementReference title;

    protected override void OnAfterRender(bool firstRender)
    {
        base.OnAfterRender(firstRender);

        foreach (var subscription in subscriptions)
        {
            subscription.OnNext(title);
        }
    }

    public void Dispose()
    {
        disposing = true;

        foreach (var subscription in subscriptions)
        {
            try
            {
                subscription.OnCompleted();
            }
            catch (Exception)
            {
            }
        }

        subscriptions.Clear();
    }

    public IDisposable Subscribe(IObserver<ElementReference> observer)
    {
        if (disposing)
        {
            throw new InvalidOperationException("Parent being disposed");
        }

        subscriptions.Add(observer);

        return new Subscription(observer, this);
    }

    private class Subscription : IDisposable
    {
        public Subscription(IObserver<ElementReference> observer, 
            CallJsExample7 self)
        {
            Observer = observer;
            Self = self;
        }

        public IObserver<ElementReference> Observer { get; }
        public CallJsExample7 Self { get; }

        public void Dispose()
        {
            Self.subscriptions.Remove(Observer);
        }
    }
}

CallJsExample7.razor.cs:

using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Components;

namespace BlazorSample.Pages
{
    public partial class CallJsExample7 : 
        ComponentBase, IObservable<ElementReference>, IDisposable
    {
        private bool disposing;
        private IList<IObserver<ElementReference>> subscriptions = 
            new List<IObserver<ElementReference>>();
        private ElementReference title;

        protected override void OnAfterRender(bool firstRender)
        {
            base.OnAfterRender(firstRender);

            foreach (var subscription in subscriptions)
            {
                subscription.OnNext(title);
            }
        }

        public void Dispose()
        {
            disposing = true;

            foreach (var subscription in subscriptions)
            {
                try
                {
                    subscription.OnCompleted();
                }
                catch (Exception)
                {
                }
            }

            subscriptions.Clear();
        }

        public IDisposable Subscribe(IObserver<ElementReference> observer)
        {
            if (disposing)
            {
                throw new InvalidOperationException("Parent being disposed");
            }

            subscriptions.Add(observer);

            return new Subscription(observer, this);
        }

        private class Subscription : IDisposable
        {
            public Subscription(IObserver<ElementReference> observer, 
                CallJsExample7 self)
            {
                Observer = observer;
                Self = self;
            }

            public IObserver<ElementReference> Observer { get; }
            public CallJsExample7 Self { get; }

            public void Dispose()
            {
                Self.subscriptions.Remove(Observer);
            }
        }
    }
}

CallJsExample7.razor.cs:

using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Components;

namespace BlazorSample.Pages
{
    public partial class CallJsExample7 : 
        ComponentBase, IObservable<ElementReference>, IDisposable
    {
        private bool disposing;
        private IList<IObserver<ElementReference>> subscriptions = 
            new List<IObserver<ElementReference>>();
        private ElementReference title;

        protected override void OnAfterRender(bool firstRender)
        {
            base.OnAfterRender(firstRender);

            foreach (var subscription in subscriptions)
            {
                subscription.OnNext(title);
            }
        }

        public void Dispose()
        {
            disposing = true;

            foreach (var subscription in subscriptions)
            {
                try
                {
                    subscription.OnCompleted();
                }
                catch (Exception)
                {
                }
            }

            subscriptions.Clear();
        }

        public IDisposable Subscribe(IObserver<ElementReference> observer)
        {
            if (disposing)
            {
                throw new InvalidOperationException("Parent being disposed");
            }

            subscriptions.Add(observer);

            return new Subscription(observer, this);
        }

        private class Subscription : IDisposable
        {
            public Subscription(IObserver<ElementReference> observer, 
                CallJsExample7 self)
            {
                Observer = observer;
                Self = self;
            }

            public IObserver<ElementReference> Observer { get; }
            public CallJsExample7 Self { get; }

            public void Dispose()
            {
                Self.subscriptions.Remove(Observer);
            }
        }
    }
}

Yukarıdaki örnekte, uygulamanın ad alanı şeklindedir BlazorSample. Kodu yerel olarak test ediyorsanız ad alanını güncelleştirin.

SurveyPrompt.razor (çocuk bileşen):

<div class="alert alert-secondary mt-4">
    <span class="oi oi-pencil me-2" aria-hidden="true"></span>
    <strong>@Title</strong>

    <span class="text-nowrap">
        Please take our
        <a target="_blank" class="font-weight-bold link-dark" href="https://go.microsoft.com/fwlink/?linkid=2186158">brief survey</a>
    </span>
    and tell us what you think.
</div>

@code {
    // Demonstrates how a parent component can supply parameters
    [Parameter]
    public string? Title { get; set; }
}
<div class="alert alert-secondary mt-4">
    <span class="oi oi-pencil me-2" aria-hidden="true"></span>
    <strong>@Title</strong>

    <span class="text-nowrap">
        Please take our
        <a target="_blank" class="font-weight-bold link-dark" href="https://go.microsoft.com/fwlink/?linkid=2186158">brief survey</a>
    </span>
    and tell us what you think.
</div>

@code {
    // Demonstrates how a parent component can supply parameters
    [Parameter]
    public string? Title { get; set; }
}
<div class="alert alert-secondary mt-4">
    <span class="oi oi-pencil me-2" aria-hidden="true"></span>
    <strong>@Title</strong>

    <span class="text-nowrap">
        Please take our
        <a target="_blank" class="font-weight-bold link-dark" href="https://go.microsoft.com/fwlink/?linkid=2186157">brief survey</a>
    </span>
    and tell us what you think.
</div>

@code {
    // Demonstrates how a parent component can supply parameters
    [Parameter]
    public string? Title { get; set; }
}
<div class="alert alert-secondary mt-4" role="alert">
    <span class="oi oi-pencil mr-2" aria-hidden="true"></span>
    <strong>@Title</strong>

    <span class="text-nowrap">
        Please take our
        <a target="_blank" class="font-weight-bold" 
            href="https://go.microsoft.com/fwlink/?linkid=2109206">brief survey</a>
    </span>
    and tell us what you think.
</div>

@code {
    [Parameter]
    public string? Title { get; set; }
}
<div class="alert alert-secondary mt-4" role="alert">
    <span class="oi oi-pencil mr-2" aria-hidden="true"></span>
    <strong>@Title</strong>

    <span class="text-nowrap">
        Please take our
        <a target="_blank" class="font-weight-bold" 
            href="https://go.microsoft.com/fwlink/?linkid=2109206">brief survey</a>
    </span>
    and tell us what you think.
</div>

@code {
    [Parameter]
    public string Title { get; set; }
}
<div class="alert alert-secondary mt-4" role="alert">
    <span class="oi oi-pencil mr-2" aria-hidden="true"></span>
    <strong>@Title</strong>

    <span class="text-nowrap">
        Please take our
        <a target="_blank" class="font-weight-bold" 
            href="https://go.microsoft.com/fwlink/?linkid=2109206">brief survey</a>
    </span>
    and tell us what you think.
</div>

@code {
    [Parameter]
    public string Title { get; set; }
}

SurveyPrompt.razor.cs:

using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;

namespace BlazorSample.Components;

public partial class SurveyPrompt : 
    ComponentBase, IObserver<ElementReference>, IDisposable
{
    private IDisposable? subscription = null;

    [Parameter]
    public IObservable<ElementReference>? Parent { get; set; }

    [Inject]
    public IJSRuntime? JS {get; set;}

    protected override void OnParametersSet()
    {
        base.OnParametersSet();

        subscription?.Dispose();
        subscription = Parent?.Subscribe(this);
    }

    public void OnCompleted() => subscription = null;

    public void OnError(Exception error) => subscription = null;

    public void OnNext(ElementReference value) =>
        _ = (JS?.InvokeAsync<object>("setElementClass", [ value, "red" ]));

    public void Dispose()
    {
        subscription?.Dispose();

        // The following prevents derived types that introduce a
        // finalizer from needing to re-implement IDisposable.
        GC.SuppressFinalize(this);
    }
}
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;

namespace BlazorSample.Components;

public partial class SurveyPrompt : 
    ComponentBase, IObserver<ElementReference>, IDisposable
{
    private IDisposable? subscription = null;

    [Parameter]
    public IObservable<ElementReference>? Parent { get; set; }

    [Inject]
    public IJSRuntime? JS {get; set;}

    protected override void OnParametersSet()
    {
        base.OnParametersSet();

        subscription?.Dispose();
        subscription = Parent?.Subscribe(this);
    }

    public void OnCompleted() => subscription = null;

    public void OnError(Exception error) => subscription = null;

    public void OnNext(ElementReference value) =>
        _ = (JS?.InvokeAsync<object>("setElementClass", [ value, "red" ]));

    public void Dispose()
    {
        subscription?.Dispose();

        // The following prevents derived types that introduce a
        // finalizer from needing to re-implement IDisposable.
        GC.SuppressFinalize(this);
    }
}
using System;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;

namespace BlazorSample.Shared;

public partial class SurveyPrompt : 
    ComponentBase, IObserver<ElementReference>, IDisposable
{
    private IDisposable? subscription = null;

    [Parameter]
    public IObservable<ElementReference>? Parent { get; set; }

    [Inject]
    public IJSRuntime? JS {get; set;}

    protected override void OnParametersSet()
    {
        base.OnParametersSet();

        subscription?.Dispose();
        subscription = 
            Parent is not null ? Parent.Subscribe(this) : null;
    }

    public void OnCompleted()
    {
        subscription = null;
    }

    public void OnError(Exception error)
    {
        subscription = null;
    }

    public void OnNext(ElementReference value)
    {
        JS?.InvokeAsync<object>(
            "setElementClass", new object[] { value, "red" });
    }

    public void Dispose()
    {
        subscription?.Dispose();
    }
}
using System;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;

namespace BlazorSample.Shared;

public partial class SurveyPrompt : 
    ComponentBase, IObserver<ElementReference>, IDisposable
{
    private IDisposable? subscription = null;

    [Parameter]
    public IObservable<ElementReference>? Parent { get; set; }

    [Inject]
    public IJSRuntime? JS {get; set;}

    protected override void OnParametersSet()
    {
        base.OnParametersSet();

        subscription?.Dispose();
        subscription = 
            Parent is not null ? Parent.Subscribe(this) : null;
    }

    public void OnCompleted()
    {
        subscription = null;
    }

    public void OnError(Exception error)
    {
        subscription = null;
    }

    public void OnNext(ElementReference value)
    {
        JS?.InvokeAsync<object>(
            "setElementClass", new object[] { value, "red" });
    }

    public void Dispose()
    {
        subscription?.Dispose();
    }
}
using System;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;

namespace BlazorSample.Shared
{
    public partial class SurveyPrompt : 
        ComponentBase, IObserver<ElementReference>, IDisposable
    {
        private IDisposable subscription = null;

        [Parameter]
        public IObservable<ElementReference> Parent { get; set; }

        [Inject]
        public IJSRuntime JS {get; set;}

        protected override void OnParametersSet()
        {
            base.OnParametersSet();

            subscription?.Dispose();
            subscription = Parent.Subscribe(this);
        }

        public void OnCompleted()
        {
            subscription = null;
        }

        public void OnError(Exception error)
        {
            subscription = null;
        }

        public void OnNext(ElementReference value)
        {
            JS?.InvokeAsync<object>(
                "setElementClass", new object[] { value, "red" });
        }

        public void Dispose()
        {
            subscription?.Dispose();
        }
    }
}
using System;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;

namespace BlazorSample.Shared
{
    public partial class SurveyPrompt : 
        ComponentBase, IObserver<ElementReference>, IDisposable
    {
        private IDisposable subscription = null;

        [Parameter]
        public IObservable<ElementReference> Parent { get; set; }

        [Inject]
        public IJSRuntime JS {get; set;}

        protected override void OnParametersSet()
        {
            base.OnParametersSet();

            subscription?.Dispose();
            subscription = Parent.Subscribe(this);
        }

        public void OnCompleted()
        {
            subscription = null;
        }

        public void OnError(Exception error)
        {
            subscription = null;
        }

        public void OnNext(ElementReference value)
        {
            JS?.InvokeAsync<object>(
                "setElementClass", new object[] { value, "red" });
        }

        public void Dispose()
        {
            subscription?.Dispose();
        }
    }
}

Önceki örnekte, uygulamanın ad alanı BlazorSample, paylaşılan bileşenler ise Shared klasöründe bulunur. Kodu yerel olarak test ediyorsanız ad alanını güncelleştirin.

JavaScript birlikte çalışma çağrılarını sağlamlaştırma

Bu bölüm yalnızca Etkileşimli Sunucu bileşenleri için geçerlidir, ancak koşullar uygunsa istemci tarafı bileşenleri birlikte çalışma zaman aşımları da ayarlayabilir JS .

Sunucu etkileşimi olan sunucu tarafı uygulamalarda JavaScript (JS) birlikte çalışma ağ hataları nedeniyle başarısız olabilir ve güvenilir değil olarak değerlendirilmelidir. Blazor uygulamalar birlikte çalışma çağrıları için JS bir dakikalık zaman aşımı kullanır. Bir uygulama daha agresif bir zaman aşımına dayanabiliyorsa, aşağıdaki yaklaşımlardan birini kullanarak zaman aşımını ayarlayın.

İçinde Program.cs, CircuitOptions.JSInteropDefaultCallTimeout ile genel bir zaman aşımı ayarlayın.

builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents(options => 
        options.JSInteropDefaultCallTimeout = {TIMEOUT});
builder.Services.AddServerSideBlazor(
    options => options.JSInteropDefaultCallTimeout = {TIMEOUT});

Startup.ConfigureServices metodunda Startup.cs, CircuitOptions.JSInteropDefaultCallTimeout ile genel bir zaman aşımı ayarlayın.

services.AddServerSideBlazor(
    options => options.JSInteropDefaultCallTimeout = {TIMEOUT});

Yer {TIMEOUT} tutucu bir TimeSpan 'dir (örneğin, TimeSpan.FromSeconds(80)).

Bileşen kodunda çağrı başına zaman aşımı ayarlayın. Belirtilen zaman aşımı, JSInteropDefaultCallTimeout tarafından ayarlanan genel zaman aşımını geçersiz kılar.

var result = await JS.InvokeAsync<string>("{ID}", {TIMEOUT}, [ "Arg1" ]);
var result = await JS.InvokeAsync<string>("{ID}", {TIMEOUT}, new[] { "Arg1" });

Yukarıdaki örnekte:

  • Yer {TIMEOUT} tutucu bir TimeSpan 'dir (örneğin, TimeSpan.FromSeconds(80)).
  • {ID} yer tutucu, çağrılacak işlevin tanımlayıcısıdır. Örneğin, someScope.someFunction değeri window.someScope.someFunction işlevini çağırır.

Birlikte çalışma hatalarının yaygın nedenlerinden biri sunucu tarafı bileşenlerdeki ağ hataları olsa da, istemci-tarafı bileşenleri için birlikte çalışma çağrılarında her bir çağrı için zaman aşımı ayarlanabilir. İstemci tarafı bileşeni için bir Blazor-SignalR devre mevcut olmasa da, JS birlikte çalışma çağrıları geçerli olan diğer nedenlerden dolayı başarısız olabilir.

Kaynak tükenmesi hakkında daha fazla bilgi için bkz . ASP.NET Core Blazor etkileşimli sunucu tarafı işleme için tehdit azaltma kılavuzu.

Döngüsel nesne başvurularından kaçının

Döngüsel referanslar içeren nesneler, istemcide aşağıdaki nedenlerden dolayı seri hale getirilemez:

  • .NET yöntemi çağrıları.
  • Dönüş türü döngüsel başvurulara sahip olduğunda JavaScript yöntemi C# dilinden çağrılar.

Kullanıcı arabirimini işleyen JavaScript kitaplıkları

Bazen tarayıcı DOM'sinde görünür kullanıcı arabirimi öğeleri üreten JavaScript (JS) kitaplıkları kullanmak isteyebilirsiniz. İlk bakışta, bu zor görünebilir çünkü Blazor'nin diffing sistemi, DOM öğeleri ağacının üzerinde denetim sahibi olmaya dayanır ve bazı dış kodlar DOM ağacını değiştirip farkları uygulama mekanizmasını geçersiz kıldığında hatalarla karşılaşır. Bu belirli bir Blazorsınırlama değildir. Aynı zorluk, fark tabanlı Kullanıcı Arayüzü Çerçevelerinde de ortaya çıkar.

Neyse ki, harici olarak oluşturulan kullanıcı arabirimini bir bileşen kullanıcı arabirimine güvenilir bir Razor şekilde eklemek kolaydır. Önerilen teknik, bileşenin kodunun (.razor dosyası) boş bir öğe üretmesini sağlamaktır. Blazor'nin fark sistemi söz konusu olduğunda, öğe her zaman boş olduğundan render işleyici öğeye yineleme yapmaz ve içeriği olduğu gibi bırakır. Bu, öğeyi rastgele dış tarafından yönetilen içerikle doldurmayı güvenli hale getirir.

Aşağıdaki örnekte kavramı gösterilmektedir. if deyimi içinde firstRendertrue olduğunda, unmanagedElement birlikte çalışabilirlik kullanarak Blazor ile JS dışında etkileşime geçin. Örneğin, bir harici JS kitaplığı çağırarak öğeyi doldurun. Blazor bu bileşen kaldırılana kadar öğenin içeriğine dokunmadan bırakır. Bileşen kaldırıldığında, bileşenin dom alt ağacının tamamı da kaldırılır.

<h1>Hello! This is a Razor component rendered at @DateTime.Now</h1>

<div @ref="unmanagedElement"></div>

@code {
    private ElementReference unmanagedElement;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            ...
        }
    }
}

Açık kaynak Mapbox API'lerini kullanarak etkileşimli bir haritayı işleyen aşağıdaki örneği göz önünde bulundurun.

Aşağıdaki JS modül uygulamaya yerleştirilir veya bir Razor sınıf kitaplığından kullanılabilir hale getirilir.

Not

Mapbox haritasını oluşturmak için, Mapbox Sign in'den bir erişim belirteci edinin ve ardından aşağıdaki kodda {ACCESS TOKEN} görünen yere yerleştirin.

wwwroot/mapComponent.js:

import 'https://api.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.js';

mapboxgl.accessToken = '{ACCESS TOKEN}';

export function addMapToElement(element) {
  return new mapboxgl.Map({
    container: element,
    style: 'mapbox://styles/mapbox/streets-v11',
    center: [-74.5, 40],
    zoom: 9
  });
}

export function setMapCenter(map, latitude, longitude) {
  map.setCenter([longitude, latitude]);
}

Doğru stil oluşturmak için konak HTML sayfasına aşağıdaki stil sayfası etiketini ekleyin.

Aşağıdaki <link> öğesini <head> öğe işaretlemesi içerisine ekleyin (<head> içeriği bulunduğu yer).

<link href="https://api.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.css" 
    rel="stylesheet" />

CallJs8.razor:

@page "/call-js-8"
@implements IAsyncDisposable
@inject IJSRuntime JS

<PageTitle>Call JS 8</PageTitle>

<HeadContent>
    <link href="https://api.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.css" 
        rel="stylesheet" />
</HeadContent>

<h1>Call JS Example 8</h1>

<div @ref="mapElement" style='width:400px;height:300px'></div>

<button @onclick="() => ShowAsync(51.454514, -2.587910)">Show Bristol, UK</button>
<button @onclick="() => ShowAsync(35.6762, 139.6503)">Show Tokyo, Japan</button>

@code
{
    private ElementReference mapElement;
    private IJSObjectReference? mapModule;
    private IJSObjectReference? mapInstance;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            mapModule = await JS.InvokeAsync<IJSObjectReference>(
                "import", "./mapComponent.js");
            mapInstance = await mapModule.InvokeAsync<IJSObjectReference>(
                "addMapToElement", mapElement);
        }
    }

    private async Task ShowAsync(double latitude, double longitude)
    {
        if (mapModule is not null && mapInstance is not null)
        {
            await mapModule.InvokeVoidAsync("setMapCenter", mapInstance, 
                latitude, longitude);
        }
    }

    async ValueTask IAsyncDisposable.DisposeAsync()
    {
        if (mapInstance is not null)
        {
            try
            {
                await mapInstance.DisposeAsync();
            }
            catch (JSDisconnectedException)
            {
            }
        }

        if (mapModule is not null)
        {
            try
            {
                await mapModule.DisposeAsync();
            }
            catch (JSDisconnectedException)
            {
            }
        }
    }
}

CallJs8.razor:

@page "/call-js-8"
@implements IAsyncDisposable
@inject IJSRuntime JS

<PageTitle>Call JS 8</PageTitle>

<HeadContent>
    <link href="https://api.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.css" 
        rel="stylesheet" />
</HeadContent>

<h1>Call JS Example 8</h1>

<div @ref="mapElement" style='width:400px;height:300px'></div>

<button @onclick="() => ShowAsync(51.454514, -2.587910)">Show Bristol, UK</button>
<button @onclick="() => ShowAsync(35.6762, 139.6503)">Show Tokyo, Japan</button>

@code
{
    private ElementReference mapElement;
    private IJSObjectReference? mapModule;
    private IJSObjectReference? mapInstance;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            mapModule = await JS.InvokeAsync<IJSObjectReference>(
                "import", "./mapComponent.js");
            mapInstance = await mapModule.InvokeAsync<IJSObjectReference>(
                "addMapToElement", mapElement);
        }
    }

    private async Task ShowAsync(double latitude, double longitude)
    {
        if (mapModule is not null && mapInstance is not null)
        {
            await mapModule.InvokeVoidAsync("setMapCenter", mapInstance, 
                latitude, longitude);
        }
    }

    async ValueTask IAsyncDisposable.DisposeAsync()
    {
        if (mapInstance is not null)
        {
            try
            {
                await mapInstance.DisposeAsync();
            }
            catch (JSDisconnectedException)
            {
            }
        }

        if (mapModule is not null)
        {
            try
            {
                await mapModule.DisposeAsync();
            }
            catch (JSDisconnectedException)
            {
            }
        }
    }
}

CallJsExample8.razor:

@page "/call-js-example-8"
@implements IAsyncDisposable
@inject IJSRuntime JS

<h1>Call JS Example 8</h1>

<div @ref="mapElement" style='width:400px;height:300px'></div>

<button @onclick="() => ShowAsync(51.454514, -2.587910)">Show Bristol, UK</button>
<button @onclick="() => ShowAsync(35.6762, 139.6503)">Show Tokyo, Japan</button>

@code
{
    private ElementReference mapElement;
    private IJSObjectReference? mapModule;
    private IJSObjectReference? mapInstance;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            mapModule = await JS.InvokeAsync<IJSObjectReference>(
                "import", "./mapComponent.js");
            mapInstance = await mapModule.InvokeAsync<IJSObjectReference>(
                "addMapToElement", mapElement);
        }
    }

    private async Task ShowAsync(double latitude, double longitude)
    {
        if (mapModule is not null && mapInstance is not null)
        {
            await mapModule.InvokeVoidAsync("setMapCenter", mapInstance, 
                latitude, longitude);
        }
    }

    async ValueTask IAsyncDisposable.DisposeAsync()
    {
        if (mapInstance is not null)
        {
            await mapInstance.DisposeAsync();
        }

        if (mapModule is not null)
        {
            await mapModule.DisposeAsync();
        }
    }
}

CallJsExample8.razor:

@page "/call-js-example-8"
@implements IAsyncDisposable
@inject IJSRuntime JS

<h1>Call JS Example 8</h1>

<div @ref="mapElement" style='width:400px;height:300px'></div>

<button @onclick="() => ShowAsync(51.454514, -2.587910)">Show Bristol, UK</button>
<button @onclick="() => ShowAsync(35.6762, 139.6503)">Show Tokyo, Japan</button>

@code
{
    private ElementReference mapElement;
    private IJSObjectReference? mapModule;
    private IJSObjectReference? mapInstance;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            mapModule = await JS.InvokeAsync<IJSObjectReference>(
                "import", "./mapComponent.js");
            mapInstance = await mapModule.InvokeAsync<IJSObjectReference>(
                "addMapToElement", mapElement);
        }
    }

    private async Task ShowAsync(double latitude, double longitude)
    {
        if (mapModule is not null && mapInstance is not null)
        {
            await mapModule.InvokeVoidAsync("setMapCenter", mapInstance, 
                latitude, longitude);
        }
    }

    async ValueTask IAsyncDisposable.DisposeAsync()
    {
        if (mapInstance is not null)
        {
            await mapInstance.DisposeAsync();
        }

        if (mapModule is not null)
        {
            await mapModule.DisposeAsync();
        }
    }
}

Yukarıdaki örnek etkileşimli bir harita kullanıcı arabirimi oluşturur. Kullanıcı:

  • Kaydırmak veya yakınlaştırmak için sürükleyebilir.
  • Önceden tanımlanmış konumlara atlamak için düğmeleri seçin.

Bristol, Birleşik Krallık ve Tokyo, Japonya'yı seçmek için düğmelerle Tokyo, Japonya'nın Mapbox sokak haritası

Yukarıdaki örnekte:

  • <div> ile @ref="mapElement"Blazor açısından boş bırakılır. Betik, mapbox-gl.js öğesini güvenli bir şekilde doldurabilir ve içeriğini değiştirebilir. Bu tekniği, kullanıcı arabirimini işleyen herhangi bir JS kitaplıkla kullanın. Üçüncü taraf JS SPA çerçevesindeki bileşenleri, sayfanın diğer kısımlarına ulaşmaya ve değiştirmeye çalışmadıkları sürece Razor bileşenlerin içine gömebilirsiniz. Dış kodun, JS tarafından boş kabul edilmeyen öğeleri değiştirmesi Blazor değildir.
  • Bu yaklaşımı kullanırken DOM öğelerinin nasıl Blazor korunduğundan veya yok edildiğinden bahseden kuralları aklınızda bulundurun. DOM öğeleri mümkün olduğunca korunduğu için bileşen düğme tıklama olaylarını güvenli bir şekilde işler ve mevcut harita örneğini güncelleştirir. Bir döngünün içinden @foreach harita öğelerini listeliyorsanız, bileşen örneklerinin korunmasını sağlamak için @key kullanın. Aksi takdirde, liste verilerindeki değişiklikler bileşen örneklerinin önceki örneklerin durumunu istenmeyen bir şekilde korumasına neden olabilir. Daha fazla bilgi için, öğeler, bileşenler ve model nesneleri arasındaki ilişkiyi korumak üzere @key yönerge özniteliğini nasıl kullanacağınızı görün.
  • Örnek, bir JavaScript modülü içindeki mantık ve bağımlılıkları kapsüller ve JS tanımlayıcıyı kullanarak modülü dinamik olarak yükler. Daha fazla bilgi için bkz . JavaScript modüllerinde JavaScript yalıtımı.

Bayt dizisi desteği

Blazor bayt dizilerinin Base64'e kodlanıp çözümlenmesi işlemlerini gerektirmeyen optimize edilmiş bayt dizisi JavaScript (JS) birlikte çalışmasını destekler. Aşağıdaki örnek, JS interop kullanarak bir bayt dizisini JavaScript'e geçirmek içindir.

Bir receiveByteArrayJS işlev sağlayın. İşlev InvokeVoidAsync ile çağrılır ve bir değer döndürmez.

<script>
  window.receiveByteArray = (bytes) => {
    let utf8decoder = new TextDecoder();
    let str = utf8decoder.decode(bytes);
    return str;
  };
</script>

Not

Genel JS konumu hakkında yönergeler ve üretim uygulamalarına yönelik önerilerimiz için ASP.NET Core Blazor uygulamalarında JavaScript konumu bölümüne bakın.

CallJs9.razor:

@page "/call-js-9"
@inject IJSRuntime JS

<h1>Call JS Example 9</h1>

<p>
    <button @onclick="SendByteArray">Send Bytes</button>
</p>

<p>
    @result
</p>

<p>
    Quote &copy;2005 <a href="https://www.uphe.com">Universal Pictures</a>:
    <a href="https://www.uphe.com/movies/serenity-2005">Serenity</a><br>
    <a href="https://www.imdb.com/name/nm0821612/">Jewel Staite on IMDB</a>
</p>

@code {
    private string? result;

    private async Task SendByteArray()
    {
        var bytes = new byte[] { 0x45, 0x76, 0x65, 0x72, 0x79, 0x74, 0x68, 0x69,
            0x6e, 0x67, 0x27, 0x73, 0x20, 0x73, 0x68, 0x69, 0x6e, 0x79, 0x2c,
            0x20, 0x43, 0x61, 0x70, 0x74, 0x69, 0x61, 0x6e, 0x2e, 0x20, 0x4e,
            0x6f, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x66, 0x72, 0x65, 0x74, 0x2e };

        result = await JS.InvokeAsync<string>("receiveByteArray", bytes);
    }
}

CallJsExample9.razor:

@page "/call-js-example-9"
@inject IJSRuntime JS

<h1>Call JS Example 9</h1>

<p>
    <button @onclick="SendByteArray">Send Bytes</button>
</p>

<p>
    @result
</p>

<p>
    Quote &copy;2005 <a href="https://www.uphe.com">Universal Pictures</a>:
    <a href="https://www.uphe.com/movies/serenity-2005">Serenity</a><br>
    <a href="https://www.imdb.com/name/nm0821612/">Jewel Staite on IMDB</a>
</p>

@code {
    private string? result;

    private async Task SendByteArray()
    {
        var bytes = new byte[] { 0x45, 0x76, 0x65, 0x72, 0x79, 0x74, 0x68, 0x69,
            0x6e, 0x67, 0x27, 0x73, 0x20, 0x73, 0x68, 0x69, 0x6e, 0x79, 0x2c,
            0x20, 0x43, 0x61, 0x70, 0x74, 0x69, 0x61, 0x6e, 0x2e, 0x20, 0x4e,
            0x6f, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x66, 0x72, 0x65, 0x74, 0x2e };

        result = await JS.InvokeAsync<string>("receiveByteArray", bytes);
    }
}

JavaScript'ten .NET çağırırken bayt dizisi kullanma hakkında bilgi için bkz . ASP.NET Core'da BlazorJavaScript işlevlerinden .NET yöntemlerini çağırma.

.NET'ten JavaScript'e akış

Blazor doğrudan .NET'ten JavaScript'e (JS ) akış verilerini destekler. Akışlar, DotNetStreamReference kullanılarak oluşturulur.

DotNetStreamReference bir .NET akışını temsil eder ve aşağıdaki parametreleri kullanır:

  • stream: JS için gönderilen akış.
  • leaveOpen: Akışın iletimden sonra açık bırakılıp bırakılmadığını belirler. Bir değer sağlanmazsa, leaveOpen varsayılan olarak olur false.

JS içinde, veriyi almak için bir dizi tamponu veya okunabilir bir akış kullanın:

  • ArrayBuffer Kullanımı:

    async function streamToJavaScript(streamRef) {
      const data = await streamRef.arrayBuffer();
    }
    
  • Bir ReadableStream kullanarak:

    async function streamToJavaScript(streamRef) {
      const stream = await streamRef.stream();
    }
    

C# kodunda:

var streamRef = new DotNetStreamReference(stream: {STREAM}, leaveOpen: false);
await JS.InvokeVoidAsync("streamToJavaScript", streamRef);

Yukarıdaki örnekte:

  • Yer tutucu {STREAM}, Stream'ye gönderilen JS öğesini temsil eder.
  • JS eklenen IJSRuntime bir örnektir.

Bir DotNetStreamReference örneğinin atılması genellikle gereksizdir. leaveOpen varsayılan değerine false ayarlandığında, temel alınan Stream öğesine iletildikten sonra JS otomatik olarak atılır.

Eğer leaveOpentrue ise, bir DotNetStreamReference'yi atmak, onun temel aldığı Stream'yi atmaz. Uygulamanın kodu, temel alınan Streamöğesinin ne zaman atılması gerekeceğini belirler. Temelindeki Stream'nin nasıl bertaraf edileceğine karar verirken aşağıdakileri göz önünde bulundurun:

  • Bir Stream öğesini JS'ye iletilirken atmak, bir uygulama hatası olarak değerlendirilir ve işlenmeyen bir istisnanın oluşmasına neden olabilir.
  • Stream iletimi, akışın DotNetStreamReference mantığında gerçekten kullanılıp kullanılmadığına bakılmaksızın, JS birlikte çalışabilirlik çağrısına bir bağımsız değişken olarak geçirildiği anda başlar.

Bu özellikler göz önünde bulundurulduğunda, Stream yalnızca, JS veya arrayBuffer tarafından döndürülen söz stream tarafından tamamen tüketildikten sonra çözümlendiğinde atmanızı öneririz. DotNetStreamReference yalnızca koşulsuz olarak JS mantığı tarafından tüketilecekse JS öğesine geçirilmelidir.

ASP.NET Core'daki Blazor JavaScript işlevlerinden .NET yöntemlerini çağırmak, JavaScript'ten .NET'e akışla ters işlemi kapsar.

ASP.NET Core Blazor dosya indirme işlemleri, Blazor'da bir dosyanın nasıl indirileceğini kapsar.

JavaScript özel durumlarını yakalama

tr-TR: Özel durumları yakalamak için, birlikte çalışma alanını bir JS sarmalayıp bir JS yakalayın.

Aşağıdaki örnekte nonFunctionJS işlev mevcut değildir. İşlev bulunamazsa, JSException aşağıdaki hatayı gösteren bir Message ile yakalanmış olur:

Could not find 'nonFunction' ('nonFunction' was undefined).

CallJs11.razor:

@page "/call-js-11"
@inject IJSRuntime JS

<PageTitle>Call JS 11</PageTitle>

<h1>Call JS Example 11</h1>

<p>
    <button @onclick="CatchUndefinedJSFunction">Catch Exception</button>
</p>

<p>
    @result
</p>

<p>
    @errorMessage
</p>

@code {
    private string? errorMessage;
    private string? result;

    private async Task CatchUndefinedJSFunction()
    {
        try
        {
            result = await JS.InvokeAsync<string>("nonFunction");
        }
        catch (JSException e)
        {
            errorMessage = $"Error Message: {e.Message}";
        }
    }
}

CallJs11.razor:

@page "/call-js-11"
@inject IJSRuntime JS

<PageTitle>Call JS 11</PageTitle>

<h1>Call JS Example 11</h1>

<p>
    <button @onclick="CatchUndefinedJSFunction">Catch Exception</button>
</p>

<p>
    @result
</p>

<p>
    @errorMessage
</p>

@code {
    private string? errorMessage;
    private string? result;

    private async Task CatchUndefinedJSFunction()
    {
        try
        {
            result = await JS.InvokeAsync<string>("nonFunction");
        }
        catch (JSException e)
        {
            errorMessage = $"Error Message: {e.Message}";
        }
    }
}

CallJsExample11.razor:

@page "/call-js-example-11"
@inject IJSRuntime JS

<h1>Call JS Example 11</h1>

<p>
    <button @onclick="CatchUndefinedJSFunction">Catch Exception</button>
</p>

<p>
    @result
</p>

<p>
    @errorMessage
</p>

@code {
    private string? errorMessage;
    private string? result;

    private async Task CatchUndefinedJSFunction()
    {
        try
        {
            result = await JS.InvokeAsync<string>("nonFunction");
        }
        catch (JSException e)
        {
            errorMessage = $"Error Message: {e.Message}";
        }
    }
}

CallJsExample11.razor:

@page "/call-js-example-11"
@inject IJSRuntime JS

<h1>Call JS Example 11</h1>

<p>
    <button @onclick="CatchUndefinedJSFunction">Catch Exception</button>
</p>

<p>
    @result
</p>

<p>
    @errorMessage
</p>

@code {
    private string? errorMessage;
    private string? result;

    private async Task CatchUndefinedJSFunction()
    {
        try
        {
            result = await JS.InvokeAsync<string>("nonFunction");
        }
        catch (JSException e)
        {
            errorMessage = $"Error Message: {e.Message}";
        }
    }
}

CallJsExample11.razor:

@page "/call-js-example-11"
@inject IJSRuntime JS

<h1>Call JS Example 11</h1>

<p>
    <button @onclick="CatchUndefinedJSFunction">Catch Exception</button>
</p>

<p>
    @result
</p>

<p>
    @errorMessage
</p>

@code {
    private string errorMessage;
    private string result;

    private async Task CatchUndefinedJSFunction()
    {
        try
        {
            result = await JS.InvokeAsync<string>("nonFunction");
        }
        catch (JSException e)
        {
            errorMessage = $"Error Message: {e.Message}";
        }
    }
}

CallJsExample11.razor:

@page "/call-js-example-11"
@inject IJSRuntime JS

<h1>Call JS Example 11</h1>

<p>
    <button @onclick="CatchUndefinedJSFunction">Catch Exception</button>
</p>

<p>
    @result
</p>

<p>
    @errorMessage
</p>

@code {
    private string errorMessage;
    private string result;

    private async Task CatchUndefinedJSFunction()
    {
        try
        {
            result = await JS.InvokeAsync<string>("nonFunction");
        }
        catch (JSException e)
        {
            errorMessage = $"Error Message: {e.Message}";
        }
    }
}

Uzun süre çalışan bir JavaScript işlevini durdurma

Bir bileşenin içinde uzun süre çalışan JavaScript fonksiyonunu C# kodundan durdurmak için JSAbortController ve bir CancellationTokenSource kullanın.

Aşağıdaki JSHelpers sınıfı, longRunningFn'ün çağrıldığını belirten AbortController.signal'e kadar sürekli sayması için tasarlanmış simüle edilmiş uzun süre çalışan bir işlev içerir. sleep İşlev, uzun süre çalışan işlevin yavaş yürütülmesini simüle etmek için gösterim amaçlıdır ve üretim kodunda mevcut olmaz. Bir bileşen stopFn çağırdığında, longRunningFnwhile üzerinde AbortSignal.aborted döngü koşul kontrolü ile durdurulması için sinyal gönderilir.

<script>
  class Helpers {
    static #controller = new AbortController();

    static async #sleep(ms) {
      return new Promise(resolve => setTimeout(resolve, ms));
    }

    static async longRunningFn() {
      var i = 0;
      while (!this.#controller.signal.aborted) {
        i++;
        console.log(`longRunningFn: ${i}`);
        await this.#sleep(1000);
      }
    }

    static stopFn() {
      this.#controller.abort();
      console.log('longRunningFn aborted!');
    }
  }

  window.Helpers = Helpers;
</script>

Not

Genel JS konumu hakkında yönergeler ve üretim uygulamalarına yönelik önerilerimiz için ASP.NET Core Blazor uygulamalarında JavaScript konumu bölümüne bakın.

Aşağıdaki bileşen:

CallJs12.razor:

@page "/call-js-12"
@inject IJSRuntime JS

<h1>Cancel long-running JS interop</h1>

<p>
    <button @onclick="StartTask">Start Task</button>
    <button @onclick="CancelTask">Cancel Task</button>
</p>

@code {
    private CancellationTokenSource? cts;

    private async Task StartTask()
    {
        cts = new CancellationTokenSource();
        cts.Token.Register(() => JS.InvokeVoidAsync("Helpers.stopFn"));

        await JS.InvokeVoidAsync("Helpers.longRunningFn");
    }

    private void CancelTask()
    {
        cts?.Cancel();
    }

    public void Dispose()
    {
        cts?.Cancel();
        cts?.Dispose();
    }
}

CallJsExample12.razor:

@page "/call-js-example-12"
@inject IJSRuntime JS

<h1>Cancel long-running JS interop</h1>

<p>
    <button @onclick="StartTask">Start Task</button>
    <button @onclick="CancelTask">Cancel Task</button>
</p>

@code {
    private CancellationTokenSource? cts;

    private async Task StartTask()
    {
        cts = new CancellationTokenSource();
        cts.Token.Register(() => JS.InvokeVoidAsync("Helpers.stopFn"));

        await JS.InvokeVoidAsync("Helpers.longRunningFn");
    }

    private void CancelTask()
    {
        cts?.Cancel();
    }

    public void Dispose()
    {
        cts?.Cancel();
        cts?.Dispose();
    }
}

Tarayıcının geliştirici araçları konsolu, JS düğmesi seçildiğinde uzun süre çalışan Start Task işlevin yürütüldüğünü ve Cancel Task düğmesi seçildiğinde işlevin durdurulduğunu gösterir.

longRunningFn: 1
longRunningFn: 2
longRunningFn: 3
longRunningFn aborted!

JavaScript [JSImport]/[JSExport] birlikte çalışma

Bu bölüm istemci tarafı bileşenleri için geçerlidir.

'nin JS arabirimine dayalı ortak çalışma mekanizmasını kullanan Blazoristemci tarafı bileşenlerinde JavaScript (JS) ile etkileşime alternatif olarak, .NET 7 veya sonraki sürümleri hedefleyen uygulamalar için bir IJSRuntimeJS[JSImport]/ birlikte çalışma API'si mevcuttur.

Daha fazla bilgi için bkz JavaScript JSImport/JSExport ve ASP.NET Core ile birlikte çalışabilirlik Blazor.

Özetlenmemiş JavaScript birlikte çalışma

Bu bölüm istemci tarafı bileşenleri için geçerlidir.

Arabirimi kullanan IJSUnmarshalledRuntime özetlenmemiş birlikte çalışma kullanım dışıdır ve JavaScript [JSImport]/[JSExport] birlikte çalışmasıyla değiştirilmelidir.

Daha fazla bilgi için bkz JavaScript JSImport/JSExport ve ASP.NET Core ile birlikte çalışabilirlik Blazor.

Özetlenmemiş JavaScript birlikte çalışma

Blazor WebAssembly .NET nesneleri JavaScript (JS) birlikte çalışma için seri hale getirildiğinde ve aşağıdakilerden biri doğru olduğunda bileşenler düşük performansla karşılaşabilir:

  • Yüksek hacimli .NET nesneleri hızla serileştirilir. Örneğin, fare tekerleğini döndürmek gibi bir giriş cihazının taşınması temelinde birlikte çalışma çağrıları yapıldığında düşük performans oluşabilir JS .
  • Büyük .NET nesneleri veya birçok .NET nesnesi birlikte çalışma için JS seri hale getirilmelidir. Örneğin, birlikte çalışma çağrıları onlarca dosyayı seri hale getirme gerektirdiğinde JS düşük performansa neden olabilir.

IJSUnmarshalledObjectReference , .NET verilerini seri hale getirme yükü olmadan işlevleri çağrılabilen bir JS nesneye başvuruyu temsil eder.

Aşağıdaki örnekte:

  • Bir dize ve tamsayı içeren yapı serileştirilmeden JS'ye geçirilir.
  • JS işlevleri verileri işler ve çağırana bir boolean veya string döndürür.
  • Dize JS doğrudan .NET string nesnesine dönüştürülemez. unmarshalledFunctionReturnString işlevi, bir BINDING.js_string_to_mono_string dizesinin dönüştürülme işlemini yönetmek için JS'yi çağırır.

Not

Aşağıdaki örnekler bu senaryo için tipik kullanım örnekleri değildir çünkü 'ya geçirilen JS düşük bileşen performansına neden olmaz. Örnek, yalnızca serileştirilmemiş .NET verilerinin aktarım kavramlarını göstermek için küçük bir nesne kullanır.

<script>
  window.returnObjectReference = () => {
    return {
      unmarshalledFunctionReturnBoolean: function (fields) {
        const name = Blazor.platform.readStringField(fields, 0);
        const year = Blazor.platform.readInt32Field(fields, 8);

        return name === "Brigadier Alistair Gordon Lethbridge-Stewart" &&
            year === 1968;
      },
      unmarshalledFunctionReturnString: function (fields) {
        const name = Blazor.platform.readStringField(fields, 0);
        const year = Blazor.platform.readInt32Field(fields, 8);

        return BINDING.js_string_to_mono_string(`Hello, ${name} (${year})!`);
      }
    };
  }
</script>

Not

Genel JS konumu hakkında yönergeler ve üretim uygulamalarına yönelik önerilerimiz için ASP.NET Core Blazor uygulamalarında JavaScript konumu bölümüne bakın.

Uyarı

js_string_to_mono_string İşlev adı, davranışı ve varlığı,.NET'in gelecek bir sürümünde değiştirilebilir. Örneğin:

  • İşlev büyük olasılıkla yeniden adlandırılacaktır.
  • İşlevin kendisi, dizelerin çerçeve tarafından otomatik olarak dönüştürülmesi yerine kaldırılabilir.

CallJsExample10.razor:

@page "/call-js-example-10"
@using System.Runtime.InteropServices
@using Microsoft.JSInterop
@inject IJSRuntime JS

<h1>Call JS Example 10</h1>

@if (callResultForBoolean)
{
    <p>JS interop was successful!</p>
}

@if (!string.IsNullOrEmpty(callResultForString))
{
    <p>@callResultForString</p>
}

<p>
    <button @onclick="CallJSUnmarshalledForBoolean">
        Call Unmarshalled JS & Return Boolean
    </button>
    <button @onclick="CallJSUnmarshalledForString">
        Call Unmarshalled JS & Return String
    </button>
</p>

<p>
    <a href="https://www.doctorwho.tv">Doctor Who</a>
    is a registered trademark of the <a href="https://www.bbc.com/">BBC</a>.
</p>

@code {
    private bool callResultForBoolean;
    private string? callResultForString;

    private void CallJSUnmarshalledForBoolean()
    {
        var unmarshalledRuntime = (IJSUnmarshalledRuntime)JS;

        var jsUnmarshalledReference = unmarshalledRuntime
            .InvokeUnmarshalled<IJSUnmarshalledObjectReference>(
                "returnObjectReference");

        callResultForBoolean = 
            jsUnmarshalledReference.InvokeUnmarshalled<InteropStruct, bool>(
                "unmarshalledFunctionReturnBoolean", GetStruct());
    }

    private void CallJSUnmarshalledForString()
    {
        var unmarshalledRuntime = (IJSUnmarshalledRuntime)JS;

        var jsUnmarshalledReference = unmarshalledRuntime
            .InvokeUnmarshalled<IJSUnmarshalledObjectReference>(
                "returnObjectReference");

        callResultForString = 
            jsUnmarshalledReference.InvokeUnmarshalled<InteropStruct, string>(
                "unmarshalledFunctionReturnString", GetStruct());
    }

    private InteropStruct GetStruct()
    {
        return new InteropStruct
        {
            Name = "Brigadier Alistair Gordon Lethbridge-Stewart",
            Year = 1968,
        };
    }

    [StructLayout(LayoutKind.Explicit)]
    public struct InteropStruct
    {
        [FieldOffset(0)]
        public string Name;

        [FieldOffset(8)]
        public int Year;
    }
}
@page "/call-js-example-10"
@using System.Runtime.InteropServices
@using Microsoft.JSInterop
@inject IJSRuntime JS

<h1>Call JS Example 10</h1>

@if (callResultForBoolean)
{
    <p>JS interop was successful!</p>
}

@if (!string.IsNullOrEmpty(callResultForString))
{
    <p>@callResultForString</p>
}

<p>
    <button @onclick="CallJSUnmarshalledForBoolean">
        Call Unmarshalled JS & Return Boolean
    </button>
    <button @onclick="CallJSUnmarshalledForString">
        Call Unmarshalled JS & Return String
    </button>
</p>

<p>
    <a href="https://www.doctorwho.tv">Doctor Who</a>
    is a registered trademark of the <a href="https://www.bbc.com/">BBC</a>.
</p>

@code {
    private bool callResultForBoolean;
    private string callResultForString;

    private void CallJSUnmarshalledForBoolean()
    {
        var unmarshalledRuntime = (IJSUnmarshalledRuntime)JS;

        var jsUnmarshalledReference = unmarshalledRuntime
            .InvokeUnmarshalled<IJSUnmarshalledObjectReference>(
                "returnObjectReference");

        callResultForBoolean = 
            jsUnmarshalledReference.InvokeUnmarshalled<InteropStruct, bool>(
                "unmarshalledFunctionReturnBoolean", GetStruct());
    }

    private void CallJSUnmarshalledForString()
    {
        var unmarshalledRuntime = (IJSUnmarshalledRuntime)JS;

        var jsUnmarshalledReference = unmarshalledRuntime
            .InvokeUnmarshalled<IJSUnmarshalledObjectReference>(
                "returnObjectReference");

        callResultForString = 
            jsUnmarshalledReference.InvokeUnmarshalled<InteropStruct, string>(
                "unmarshalledFunctionReturnString", GetStruct());
    }

    private InteropStruct GetStruct()
    {
        return new InteropStruct
        {
            Name = "Brigadier Alistair Gordon Lethbridge-Stewart",
            Year = 1968,
        };
    }

    [StructLayout(LayoutKind.Explicit)]
    public struct InteropStruct
    {
        [FieldOffset(0)]
        public string Name;

        [FieldOffset(8)]
        public int Year;
    }
}

Bir IJSUnmarshalledObjectReference örneği C# kodunda bertaraf edilmiyorsa, JS içinde bertaraf edilebilir. Aşağıdaki dispose işlev, JS çağrıldığında nesne referansını elden çıkarır:

window.exampleJSObjectReferenceNotDisposedInCSharp = () => {
  return {
    dispose: function () {
      DotNet.disposeJSObjectReference(this);
    },

    ...
  };
}

Dizi türleri kullanılarak JSnesnelerden js_typed_array_to_array .NET nesnelerine dönüştürülebilir, ancak JS dizinin türü alınmış bir dizi olması gerekir. 'den JS diziler C# kodunda .NET nesne dizisi (object[]) olarak okunabilir.

Dize dizileri gibi diğer veri türleri dönüştürülebilir, ancak yeni bir Mono dizi nesnesi () oluşturulmasını ve değerinin (mono_obj_array_newmono_obj_array_set) ayarlanmasını gerektirir.

Uyarı

JS çerçevesi tarafından sağlanan işlevler örneğin Blazor, js_typed_array_to_array ve mono_obj_array_new, .NET'in gelecek sürümlerinde ad değişikliklerine, davranış değişikliklerine veya kaldırılmalara tabi olabilir.

JavaScript birlikte çalışma nesnesi referanslarının bertaraf edilmesi

JavaScript (JS) birlikte çalışma makaleleri boyunca yer alan örnekler, tipik nesne yok etme kalıplarını gösterir.

  • .NET'ten JS çağırma işlemi gerçekleştirilirken, bu makalede detaylandırıldığı gibi, .NET'te veya IJSObjectReference üzerinde oluşturulan /IJSInProcessObjectReference/JSObjectReferenceJS bertaraf ederek JS bellek sızıntısını önleyin.

  • .NET JS çağrısı yaparken, ASP.NET Core'daki Blazor JavaScript işlevlerinden .NET yöntemlerini çağırma bölümünde açıklandığı gibi, .NET belleğinin sızmasını önlemek için, oluşturulan bir DotNetObjectReference'yi ya .NET'ten ya da JS'den atılmasını sağlayın.

JS birlikte çalışma nesne başvuruları, birlikte çalışma çağrısının JS yanında başvuruyu oluşturan bir tanımlayıcı tarafından anahtarlanan bir eşleme olarak uygulanır. Nesne imhası .NET'ten veya JS taraftan başlatıldığında, Blazor girdiyi haritadan kaldırır ve nesneye başka güçlü bir başvuru olmadığı sürece çöp toplanmasına izin verilir.

.NET yönetilen belleğinin sızmasını önlemek için en azından .NET tarafında oluşturulan nesneleri her zaman atın.

Bileşen bertarafı sırasında DOM temizleme görevleri

Daha fazla bilgi için bkz. ASP.NET Core Blazor JavaScript birlikte çalışabilirliği (JSbirlikte çalışma).

Bağlantı hattı olmayan JavaScript birlikte çalışma çağrıları

Daha fazla bilgi için bkz. ASP.NET Core Blazor JavaScript birlikte çalışabilirliği (JSbirlikte çalışma).

Ek kaynaklar