ASP.NET Core Blazor JavaScript birlikte çalışabilirliğiASP.NET Core Blazor JavaScript interop

Sağlayan Javier Calvarro Nelson, Daniel Rothve Luke LathamBy Javier Calvarro Nelson, Daniel Roth, and Luke Latham

Önemli

Önizlemede Blazor WeelsemblyBlazor WebAssembly in preview

Blazor sunucusu ASP.NET Core 3,0 ' de desteklenir.Blazor Server is supported in ASP.NET Core 3.0. Blazor WebAssembly ASP.NET Core 3,1 için önizlemededir.Blazor WebAssembly is in preview for ASP.NET Core 3.1.

Blazor bir uygulama, JavaScript kodundan .NET ve .NET yöntemlerinden JavaScript işlevlerini çağırabilir.A Blazor app can invoke JavaScript functions from .NET and .NET methods from JavaScript code.

Görüntüleme veya indirme örnek kodu (nasıl indirileceğini)View or download sample code (how to download)

.NET metotlarından JavaScript işlevlerini çağırmaInvoke JavaScript functions from .NET methods

Bir JavaScript işlevini çağırmak için .NET kodunun gerekli olduğu durumlar vardır.There are times when .NET code is required to call a JavaScript function. Örneğin, JavaScript çağrısı, tarayıcı özelliklerini veya bir JavaScript kitaplığından uygulamaya yönelik işlevselliği sunabilir.For example, a JavaScript call can expose browser capabilities or functionality from a JavaScript library to the app. Bu senaryoya JavaScript birlikte çalışabilirliği (js birlikte çalışma) denir.This scenario is called JavaScript interoperability (JS interop).

.NET 'ten JavaScript 'i çağırmak için IJSRuntime soyutlamasını kullanın.To call into JavaScript from .NET, use the IJSRuntime abstraction. JS birlikte çalışma çağrıları vermek için IJSRuntime soyutlamasını bileşeninizin içine ekler.To issue JS interop calls, inject the IJSRuntime abstraction in your component. InvokeAsync<T> yöntemi, herhangi bir sayıda JSON seri hale getirilebilir bağımsız değişkenle birlikte çağırmak istediğiniz JavaScript işlevi için bir tanımlayıcı alır.The InvokeAsync<T> method takes an identifier for the JavaScript function that you wish to invoke along with any number of JSON-serializable arguments. İşlev tanımlayıcısı, genel kapsama (window) göredir.The function identifier is relative to the global scope (window). window.someScope.someFunctionçağırmak isterseniz, tanımlayıcı someScope.someFunction.If you wish to call window.someScope.someFunction, the identifier is someScope.someFunction. Çağrılmadan önce işlevi kaydetmeniz gerekmez.There's no need to register the function before it's called. Dönüş türü T ayrıca seri hale getirilebilir JSON olmalıdır.The return type T must also be JSON serializable. T, döndürülen JSON türüyle en iyi eşleşen .NET türüyle eşleşmelidir.T should match the .NET type that best maps to the JSON type returned.

Prerendering özellikli Blazor Server uygulamaları için, ilk prerendering sırasında JavaScript 'e çağırma mümkün değildir.For Blazor Server apps with prerendering enabled, calling into JavaScript isn't possible during the initial prerendering. JavaScript birlikte çalışma çağrılarının, tarayıcıyla bağlantı kurulana kadar ertelenmesi gerekir.JavaScript interop calls must be deferred until after the connection with the browser is established. Daha fazla bilgi için, Blazor bir uygulamanın ne zaman prerendering olduğunu Algıla bölümüne bakın.For more information, see the Detect when a Blazor app is prerendering section.

Aşağıdaki örnek, deneysel bir JavaScript tabanlı kod çözücüsü olan Textdecodertabanlıdır.The following example is based on TextDecoder, an experimental JavaScript-based decoder. Örnek, bir C# yöntemden JavaScript işlevinin nasıl çağrılacağını gösterir.The example demonstrates how to invoke a JavaScript function from a C# method. JavaScript işlevi bir C# yöntemden bir bayt dizisi kabul eder, dizinin kodunu çözer ve görüntülenecek metni bileşene döndürür.The JavaScript function accepts a byte array from a C# method, decodes the array, and returns the text to the component for display.

Wwwroot/index.html (Blazor WebAssembly) veya Pages/_Host. cshtml (Blazor Server) <head> öğesi içinde, geçirilen bir dizinin kodunu çözmek Için TextDecoder kullanan bir JavaScript işlevi sağlayın ve kodu çözülen değeri döndürün:Inside the <head> element of wwwroot/index.html (Blazor WebAssembly) or Pages/_Host.cshtml (Blazor Server), provide a JavaScript function that uses TextDecoder to decode a passed array and return the decoded value:

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

Önceki örnekte gösterilen kod gibi JavaScript kodu, betik dosyasına yönelik bir başvuruya sahip bir JavaScript dosyasından ( . js) de yüklenebilir:JavaScript code, such as the code shown in the preceding example, can also be loaded from a JavaScript file (.js) with a reference to the script file:

<script src="exampleJsInterop.js"></script>

Aşağıdaki bileşen:The following component:

  • Bir bileşen düğmesi (diziyi Dönüştür) seçildiğinde JSRuntime kullanarak convertArray JavaScript işlevini çağırır.Invokes the convertArray JavaScript function using JSRuntime when a component button (Convert Array) is selected.
  • JavaScript işlevi çağrıldıktan sonra, geçirilen dizi bir dizeye dönüştürülür.After the JavaScript function is called, the passed array is converted into a string. Dize, görüntüleme için bileşene döndürülür.The string is returned to the component for display.
@page "/call-js-example"
@inject IJSRuntime JSRuntime;

<h1>Call JavaScript Function Example</h1>

<button type="button" class="btn btn-primary" @onclick="ConvertArray">
    Convert Array
</button>

<p class="mt-2" style="font-size:1.6em">
    <span class="badge badge-success">
        @ConvertedText
    </span>
</p>

@code {
    // Quote (c)2005 Universal Pictures: Serenity
    // https://www.uphe.com/movies/serenity
    // David Krumholtz on IMDB: https://www.imdb.com/name/nm0472710/

    private MarkupString ConvertedText =
        new MarkupString("Select the <b>Convert Array</b> button.");

    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()
    {
        var text =
            await JSRuntime.InvokeAsync<string>("convertArray", QuoteArray);

        ConvertedText = new MarkupString(text);

        StateHasChanged();
    }
}

IJSRuntime kullanımıUse of IJSRuntime

IJSRuntime soyutlamasını kullanmak için aşağıdaki yaklaşımlardan birini benimseyin:To use the IJSRuntime abstraction, adopt any of the following approaches:

  • IJSRuntime soyutlama Razor bileşenine ( . Razor) ekleme:Inject the IJSRuntime abstraction into the Razor component (.razor):

    @inject IJSRuntime JSRuntime
    
    @code {
        protected override void OnInitialized()
        {
            StocksService.OnStockTickerUpdated += stockUpdate =>
            {
                JSRuntime.InvokeVoidAsync("handleTickerChanged",
                    stockUpdate.symbol, stockUpdate.price);
            };
        }
    }
    

    Wwwroot/index.html (Blazor WebAssembly) veya Pages/_Host. cshtml (Blazor Server) <head> öğesinin Içinde, bir handleTickerChanged JavaScript işlevi sağlayın.Inside the <head> element of wwwroot/index.html (Blazor WebAssembly) or Pages/_Host.cshtml (Blazor Server), provide a handleTickerChanged JavaScript function. İşlevi IJSRuntime.InvokeVoidAsync ile çağrılır ve bir değer döndürmez:The function is called with IJSRuntime.InvokeVoidAsync and doesn't return a value:

    <script>
      window.handleTickerChanged = (symbol, price) => {
        // ... client-side processing/display code ...
      };
    </script>
    
  • IJSRuntime soyutlamasını bir sınıfa ( . cs) Ekle:Inject the IJSRuntime abstraction into a class (.cs):

    public class JsInteropClasses
    {
        private readonly IJSRuntime _jsRuntime;
    
        public JsInteropClasses(IJSRuntime jsRuntime)
        {
            _jsRuntime = jsRuntime;
        }
    
        public ValueTask<string> TickerChanged(string data)
        {
            return _jsRuntime.InvokeAsync<string>(
                "handleTickerChanged",
                stockUpdate.symbol,
                stockUpdate.price);
        }
    }
    

    Wwwroot/index.html (Blazor WebAssembly) veya Pages/_Host. cshtml (Blazor Server) <head> öğesinin Içinde, bir handleTickerChanged JavaScript işlevi sağlayın.Inside the <head> element of wwwroot/index.html (Blazor WebAssembly) or Pages/_Host.cshtml (Blazor Server), provide a handleTickerChanged JavaScript function. İşlevi JSRuntime.InvokeAsync ile çağrılır ve bir değer döndürür:The function is called with JSRuntime.InvokeAsync and returns a value:

    <script>
      window.handleTickerChanged = (symbol, price) => {
        // ... client-side processing/display code ...
        return 'Done!';
      };
    </script>
    
  • Buildrendertreeile dinamik içerik oluşturma için [Inject] özniteliğini kullanın:For dynamic content generation with BuildRenderTree, use the [Inject] attribute:

    [Inject]
    IJSRuntime JSRuntime { get; set; }
    

Bu konuya eşlik eden istemci tarafı örnek uygulamada, Kullanıcı girişi almak ve bir hoş geldiniz iletisi göstermek üzere DOM ile etkileşime geçen uygulama için iki JavaScript işlevi mevcuttur:In the client-side sample app that accompanies this topic, two JavaScript functions are available to the app that interact with the DOM to receive user input and display a welcome message:

  • showPrompt – Kullanıcı girişini kabul etmek için bir istem üretir (kullanıcının adı) ve çağıranın adını döndürür.showPrompt – Produces a prompt to accept user input (the user's name) and returns the name to the caller.
  • displayWelcome –, çağıran bir id welcomebir DOM nesnesine bir hoş geldiniz iletisi atar.displayWelcome – Assigns a welcome message from the caller to a DOM object with an id of welcome.

Wwwroot/Examplejsınterop. js:wwwroot/exampleJsInterop.js:

window.exampleJsFunctions = {
  showPrompt: function (text) {
    return prompt(text, 'Type your name here');
  },
  displayWelcome: function (welcomeMessage) {
    document.getElementById('welcome').innerText = welcomeMessage;
  },
  returnArrayAsyncJs: function () {
    DotNet.invokeMethodAsync('BlazorSample', 'ReturnArrayAsync')
      .then(data => {
        data.push(4);
          console.log(data);
    });
  },
  sayHello: function (dotnetHelper) {
    return dotnetHelper.invokeMethodAsync('SayHello')
      .then(r => console.log(r));
  }
};

JavaScript dosyasına başvuran <script> etiketini Wwwroot/index.html dosyasında (Blazor WebAssembly) veya Pages/_Host. cshtml dosyasında (Blazor Server) yerleştirin.Place the <script> tag that references the JavaScript file in the wwwroot/index.html file (Blazor WebAssembly) or Pages/_Host.cshtml file (Blazor Server).

Wwwroot/index.html (Blazor WebAssembly):wwwroot/index.html (Blazor WebAssembly):

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>Blazor WebAssembly Sample</title>
    <base href="/" />
    <link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
    <link href="css/site.css" rel="stylesheet" />
</head>

<body>
    <app>Loading...</app>

    <div id="blazor-error-ui">
        An unhandled error has occurred.
        <a href="" class="reload">Reload</a>
        <a class="dismiss">🗙</a>
    </div>
    <script src="_framework/blazor.webassembly.js"></script>
    <script src="exampleJsInterop.js"></script>
</body>

</html>

Pages/_Host. cshtml (Blazor sunucusu):Pages/_Host.cshtml (Blazor Server):

@page "/"
@namespace BlazorSample.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
    Layout = null;
}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Blazor Server Sample</title>
    <base href="~/" />
    <link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
    <link href="css/site.css" rel="stylesheet" />
</head>
<body>
    <app>
        <component type="typeof(App)" render-mode="ServerPrerendered" />
    </app>

    <div id="blazor-error-ui">
        <environment include="Staging,Production">
            An error has occurred. This application may no longer respond until reloaded.
        </environment>
        <environment include="Development">
            An unhandled exception has occurred. See browser dev tools for details.
        </environment>
        <a href="" class="reload">Reload</a>
        <a class="dismiss">🗙</a>
    </div>

    <script src="_framework/blazor.server.js"></script>
    <script src="exampleJsInterop.js"></script>
</body>
</html>

<script> etiketi dinamik olarak güncelleştirilemediğinden bir <script> etiketini bileşen dosyasına yerleştirmeyin.Don't place a <script> tag in a component file because the <script> tag can't be updated dynamically.

.NET yöntemleri, IJSRuntime.InvokeAsync<T>çağırarak Examplejsınterop. js dosyasında JavaScript işlevleriyle birlikte çalışır..NET methods interop with the JavaScript functions in the exampleJsInterop.js file by calling IJSRuntime.InvokeAsync<T>.

IJSRuntime soyutlama, Blazor sunucu senaryolarına izin vermek için zaman uyumsuzdur.The IJSRuntime abstraction is asynchronous to allow for Blazor Server scenarios. Uygulama bir Blazor Weelsembly uygulaması ise ve bir JavaScript işlevini zaman uyumlu olarak çağırmak istiyorsanız, IJSInProcessRuntime ve bunun yerine Invoke<T> çağırın.If the app is a Blazor WebAssembly app and you want to invoke a JavaScript function synchronously, downcast to IJSInProcessRuntime and call Invoke<T> instead. Çoğu JS birlikte çalışma kitaplıklarının, kitaplıkların tüm senaryolarda kullanılabilir olmasını sağlamak için zaman uyumsuz API 'Leri kullanmasını öneririz.We recommend that most JS interop libraries use the async APIs to ensure that the libraries are available in all scenarios.

Örnek uygulama, JS birlikte çalışabilirliği göstermek için bir bileşeni içerir.The sample app includes a component to demonstrate JS interop. Bileşen:The component:

  • Bir JavaScript istemi aracılığıyla Kullanıcı girişini alır.Receives user input via a JavaScript prompt.
  • İşlemek için bileşene metni döndürür.Returns the text to the component for processing.
  • Bir hoş geldiniz iletisini göstermek için DOM ile etkileşime sahip ikinci bir JavaScript işlevini çağırır.Calls a second JavaScript function that interacts with the DOM to display a welcome message.

Pages/Jsınterop. Razor:Pages/JSInterop.razor:

@page "/JSInterop"
@using BlazorSample.JsInteropClasses
@inject IJSRuntime JSRuntime

<h1>JavaScript Interop</h1>

<h2>Invoke JavaScript functions from .NET methods</h2>

<button type="button" class="btn btn-primary" @onclick="TriggerJsPrompt">
    Trigger JavaScript Prompt
</button>

<h3 id="welcome" style="color:green;font-style:italic"></h3>

@code {
    public async Task TriggerJsPrompt()
    {
        // showPrompt is implemented in wwwroot/exampleJsInterop.js
        var name = await JSRuntime.InvokeAsync<string>(
                "exampleJsFunctions.showPrompt",
                "What's your name?");
        // displayWelcome is implemented in wwwroot/exampleJsInterop.js
        await JSRuntime.InvokeVoidAsync(
                "exampleJsFunctions.displayWelcome",
                $"Hello {name}! Welcome to Blazor!");
    }
}
  1. TriggerJsPrompt, bileşenin tetikleyicisi JavaScript istem düğmesi seçilerek yürütüldüğünde, Wwwroot/Examplejsınterop. js dosyasında verilen JavaScript showPrompt işlevi çağırılır.When TriggerJsPrompt is executed by selecting the component's Trigger JavaScript Prompt button, the JavaScript showPrompt function provided in the wwwroot/exampleJsInterop.js file is called.
  2. showPrompt işlevi, HTML kodlu ve bileşene döndürülen kullanıcı girişini (kullanıcının adı) kabul eder.The showPrompt function accepts user input (the user's name), which is HTML-encoded and returned to the component. Bileşen, kullanıcının adını nameyerel bir değişkende depolar.The component stores the user's name in a local variable, name.
  3. name depolanan dize, hoş geldiniz iletisini bir başlık etiketine işleyen displayWelcomebir JavaScript işlevine iletilen bir hoş geldiniz iletisine dahil edilir.The string stored in name is incorporated into a welcome message, which is passed to a JavaScript function, displayWelcome, which renders the welcome message into a heading tag.

Void JavaScript işlevini çağırınCall a void JavaScript function

Void (0)/void 0 veya undefined döndüren JavaScript işlevleri IJSRuntime.InvokeVoidAsyncile çağırılır.JavaScript functions that return void(0)/void 0 or undefined are called with IJSRuntime.InvokeVoidAsync.

Blazor bir uygulamanın ne zaman prerendering olduğunu AlgılaDetect when a Blazor app is prerendering

Blazor sunucu uygulaması prerendering olduğunda, tarayıcıyla bir bağlantı kurulmadığından, JavaScript 'e çağırma gibi bazı eylemler mümkün değildir.While a Blazor Server app is prerendering, certain actions, such as calling into JavaScript, aren't possible because a connection with the browser hasn't been established. Bileşenler, ön işlenmiş olduğunda farklı şekilde işlenmesi gerekebilir.Components may need to render differently when prerendered.

Tarayıcı bağlantısı kurulana kadar JavaScript birlikte çalışma çağrılarını geciktirmek için Onafterrenderasync bileşen yaşam döngüsü olayınıkullanabilirsiniz.To delay JavaScript interop calls until after the connection with the browser is established, you can use the OnAfterRenderAsync component lifecycle event. Bu olay yalnızca uygulama tam olarak işlendikten ve istemci bağlantısı kurulduktan sonra çağırılır.This event is only called after the app is fully rendered and the client connection is established.

@using Microsoft.JSInterop
@inject IJSRuntime JSRuntime

<div @ref="divElement">Text during render</div>

@code {
    private ElementReference divElement;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            await JSRuntime.InvokeVoidAsync(
                "setElementText", divElement, "Text after render");
        }
    }
}

Yukarıdaki örnek kod için, Wwwroot/index.html (Blazor WebAssembly) veya Pages/_Host. cshtml (Blazor Server) <head> öğesi içinde bir setElementText JavaScript işlevi sağlayın.For the preceding example code, provide a setElementText JavaScript function inside the <head> element of wwwroot/index.html (Blazor WebAssembly) or Pages/_Host.cshtml (Blazor Server). İşlevi IJSRuntime.InvokeVoidAsync ile çağrılır ve bir değer döndürmez:The function is called with IJSRuntime.InvokeVoidAsync and doesn't return a value:

<script>
  window.setElementText = (element, text) => element.innerText = text;
</script>

Uyarı

Yukarıdaki örnek yalnızca tanıtım amacıyla Belge Nesne Modeli (DOM) değiştirir.The preceding example modifies the Document Object Model (DOM) directly for demonstration purposes only. JavaScript, Blazor 'in değişiklik izlemesini kesintiye uğradığı için çoğu senaryoda, JavaScript ile DOM 'ı doğrudan değiştirme önerilmez.Directly modifying the DOM with JavaScript isn't recommended in most scenarios because JavaScript can interfere with Blazor's change tracking.

Aşağıdaki bileşen, prerendering ile uyumlu bir şekilde bileşenin başlatma mantığının bir parçası olarak JavaScript birlikte çalışabilirinin nasıl kullanılacağını göstermektedir.The following component demonstrates how to use JavaScript interop as part of a component's initialization logic in a way that's compatible with prerendering. Bileşeni, OnAfterRenderAsynciçinden bir işleme güncelleştirmesi tetiklemenin mümkün olduğunu gösterir.The component shows that it's possible to trigger a rendering update from inside OnAfterRenderAsync. Geliştirici Bu senaryoda sonsuz bir döngü oluşturmaktan kaçınmalıdır.The developer must avoid creating an infinite loop in this scenario.

JSRuntime.InvokeAsync çağrıldığında, bileşen işlenene kadar hiçbir JavaScript öğesi olmadığından, ElementRef yalnızca OnAfterRenderAsync için kullanılır ve daha önceki bir yaşam döngüsü yönteminde değil.Where JSRuntime.InvokeAsync is called, ElementRef is only used in OnAfterRenderAsync and not in any earlier lifecycle method because there's no JavaScript element until after the component is rendered.

JavaScript birlikte çalışma çağrısından alınan yeni durumla birlikte bileşeni yeniden sağlamak için Statehaschanged çağrılır.StateHasChanged is called to rerender the component with the new state obtained from the JavaScript interop call. StateHasChanged yalnızca infoFromJs nullolduğunda çağrıldığı için, kod sonsuz bir döngü oluşturmaz.The code doesn't create an infinite loop because StateHasChanged is only called when infoFromJs is null.

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

<p>
    Get value via JS interop call:
    <strong id="val-get-by-interop">@(infoFromJs ?? "No value yet")</strong>
</p>

Set value via JS interop call:
<div id="val-set-by-interop" @ref="divElement"></div>

@code {
    private string infoFromJs;
    private ElementReference divElement;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender && infoFromJs == null)
        {
            infoFromJs = await JSRuntime.InvokeAsync<string>(
                "setElementText", divElement, "Hello from interop call!");

            StateHasChanged();
        }
    }
}

Yukarıdaki örnek kod için, Wwwroot/index.html (Blazor WebAssembly) veya Pages/_Host. cshtml (Blazor Server) <head> öğesi içinde bir setElementText JavaScript işlevi sağlayın.For the preceding example code, provide a setElementText JavaScript function inside the <head> element of wwwroot/index.html (Blazor WebAssembly) or Pages/_Host.cshtml (Blazor Server). İşlevi IJSRuntime.InvokeAsync ile çağrılır ve bir değer döndürür:The function is called with IJSRuntime.InvokeAsync and returns a value:

<script>
  window.setElementText = (element, text) => {
    element.innerText = text;
    return text;
  };
</script>

Uyarı

Yukarıdaki örnek yalnızca tanıtım amacıyla Belge Nesne Modeli (DOM) değiştirir.The preceding example modifies the Document Object Model (DOM) directly for demonstration purposes only. JavaScript, Blazor 'in değişiklik izlemesini kesintiye uğradığı için çoğu senaryoda, JavaScript ile DOM 'ı doğrudan değiştirme önerilmez.Directly modifying the DOM with JavaScript isn't recommended in most scenarios because JavaScript can interfere with Blazor's change tracking.

Öğelere başvuruları yakalaCapture references to elements

Bazı JS birlikte çalışma senaryoları HTML öğelerine başvurular gerektirir.Some JS interop scenarios require references to HTML elements. Örneğin, bir kullanıcı arabirimi kitaplığı başlatma için bir öğe başvurusu gerektirebilir veya focus veya playgibi bir öğe üzerinde komut benzeri API 'Ler çağırmanız gerekebilir.For example, a UI library may require an element reference for initialization, or you might need to call command-like APIs on an element, such as focus or play.

Aşağıdaki yaklaşımı kullanarak bir bileşen içindeki HTML öğelerine başvuruları yakalayın:Capture references to HTML elements in a component using the following approach:

  • HTML öğesine bir @ref özniteliği ekleyin.Add an @ref attribute to the HTML element.
  • Adı @ref özniteliği değeri ile eşleşen ElementReference türünde bir alan tanımlayın.Define a field of type ElementReference whose name matches the value of the @ref attribute.

Aşağıdaki örnek, username <input> öğesine bir başvuru yakalama göstermektedir:The following example shows capturing a reference to the username <input> element:

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

@code {
    ElementReference username;
}

Uyarı

Yalnızca Blazoretkileşimde bulunmayan boş bir öğenin içeriğini bulunmamalıdır için bir öğe başvurusu kullanın.Only use an element reference to mutate the contents of an empty element that doesn't interact with Blazor. Bu senaryo, bir 3. taraf API 'SI öğeye içerik sağladığı zaman yararlıdır.This scenario is useful when a 3rd party API supplies content to the element. Blazor öğesiyle etkileşmediği için, Blazoröğesi ve DOM gösterimi arasında bir çakışma olabilir.Because Blazor doesn't interact with the element, there's no possibility of a conflict between Blazor's representation of the element and the DOM.

Aşağıdaki örnekte, Blazor, bu öğenin liste öğelerini (<li>) doldurmak üzere DOM ile etkileşimde bulunduğundan, sıralanmamış listenin (ul) içeriğini () zaman zaman aşmaktır .In the following example, it's dangerous to mutate the contents of the unordered list (ul) because Blazor interacts with the DOM to populate this element's list items (<li>):

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

JS birlikte çalışma öğesi, öğe MyList içeriğini değiştiriyorsa ve Blazor SLA 'ya uygulamaya çalışırsa, diffler DOM ile eşleşmez.If JS interop mutates the contents of element MyList and Blazor attempts to apply diffs to the element, the diffs won't match the DOM.

.NET kodu açısından düşünüldüğünde, ElementReference donuk bir tanıtıcıdır.As far as .NET code is concerned, an ElementReference is an opaque handle. ElementReference ile yapabileceğiniz tek şey, JS birlikte çalışma yoluyla JavaScript koduna geçiş yapar.The only thing you can do with ElementReference is pass it through to JavaScript code via JS interop. Bunu yaptığınızda, JavaScript tarafı kodu normal DOM API 'Leri ile kullanılabilecek bir HTMLElement örneğini alır.When you do so, the JavaScript-side code receives an HTMLElement instance, which it can use with normal DOM APIs.

Örneğin, aşağıdaki kod bir öğe üzerinde odağı ayarlamaya izin veren bir .NET genişletme yöntemi tanımlar:For example, the following code defines a .NET extension method that enables setting the focus on an element:

Examplejsınterop. js:exampleJsInterop.js:

window.exampleJsFunctions = {
  focusElement : function (element) {
    element.focus();
  }
}

Değer döndürmeyen bir JavaScript işlevini çağırmak için IJSRuntime.InvokeVoidAsynckullanın.To call a JavaScript function that doesn't return a value, use IJSRuntime.InvokeVoidAsync. Aşağıdaki kod, yakalanan ElementReferenceönceki JavaScript işlevini çağırarak Kullanıcı adı girişi üzerinde odağı ayarlar:The following code sets the focus on the username input by calling the preceding JavaScript function with the captured ElementReference:

@inject IJSRuntime JSRuntime

<input @ref="username" />
<button @onclick="SetFocus">Set focus on username</button>

@code {
    private ElementReference username;

    public async Task SetFocus()
    {
        await JSRuntime.InvokeVoidAsync(
            "exampleJsFunctions.focusElement", username);
    }
}

Bir genişletme yöntemi kullanmak için IJSRuntime örneğini alan bir statik genişletme yöntemi oluşturun:To use an extension method, create a static extension method that receives the IJSRuntime instance:

public static async Task Focus(this ElementReference elementRef, IJSRuntime jsRuntime)
{
    await jsRuntime.InvokeVoidAsync(
        "exampleJsFunctions.focusElement", elementRef);
}

Focus yöntemi doğrudan nesne üzerinde çağrılır.The Focus method is called directly on the object. Aşağıdaki örnek, Focus yönteminin JsInteropClasses ad alanından kullanılabildiğini varsayar:The following example assumes that the Focus method is available from the JsInteropClasses namespace:

@inject IJSRuntime JSRuntime
@using JsInteropClasses

<input @ref="username" />
<button @onclick="SetFocus">Set focus on username</button>

@code {
    private ElementReference username;

    public async Task SetFocus()
    {
        await username.Focus(JSRuntime);
    }
}

Önemli

username değişkeni yalnızca bileşen işlendikten sonra doldurulur.The username variable is only populated after the component is rendered. Doldurulmamış bir ElementReference JavaScript koduna geçirilirse, JavaScript kodu bir nulldeğeri alır.If an unpopulated ElementReference is passed to JavaScript code, the JavaScript code receives a value of null. Bileşen işlemeyi tamamladıktan sonra öğe başvurularını değiştirmek için (bir öğe üzerinde ilk odağı ayarlamak için) Onafterrenderasync veya OnAfterRender bileşen yaşam döngüsü yöntemlerinikullanın.To manipulate element references after the component has finished rendering (to set the initial focus on an element) use the OnAfterRenderAsync or OnAfterRender component lifecycle methods.

Genel türlerle çalışırken ve bir değer döndürürken, Valuetask<t >kullanın:When working with generic types and returning a value, use ValueTask<T>:

public static ValueTask<T> GenericMethod<T>(this ElementReference elementRef, 
    IJSRuntime jsRuntime)
{
    return jsRuntime.InvokeAsync<T>(
        "exampleJsFunctions.doSomethingGeneric", elementRef);
}

GenericMethod doğrudan nesne üzerinde bir tür ile çağırılır.GenericMethod is called directly on the object with a type. Aşağıdaki örnek, GenericMethod JsInteropClasses ad alanından kullanılabilir olduğunu varsayar:The following example assumes that the GenericMethod is available from the JsInteropClasses namespace:

@inject IJSRuntime JSRuntime
@using JsInteropClasses

<input @ref="username" />
<button @onclick="OnClick">Do something generic</button>

<p>
    returnValue: @returnValue
</p>

@code {
    private ElementReference username;
    private string returnValue;

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

JavaScript işlevlerinden .NET yöntemlerini çağırInvoke .NET methods from JavaScript functions

Statik .NET yöntemi çağrısıStatic .NET method call

JavaScript 'ten statik bir .NET yöntemi çağırmak için DotNet.invokeMethod veya DotNet.invokeMethodAsync işlevlerini kullanın.To invoke a static .NET method from JavaScript, use the DotNet.invokeMethod or DotNet.invokeMethodAsync functions. Çağırmak istediğiniz statik metodun tanımlayıcısını, işlevi içeren derlemenin adını ve tüm bağımsız değişkenleri geçirin.Pass in the identifier of the static method you wish to call, the name of the assembly containing the function, and any arguments. Blazor sunucu senaryolarını desteklemek için zaman uyumsuz sürüm tercih edilir.The asynchronous version is preferred to support Blazor Server scenarios. JavaScript 'ten bir .NET yöntemi çağırmak için, .NET yönteminin public, static ve [JSInvokable] özniteliğine sahip olması gerekir.To invoke a .NET method from JavaScript, the .NET method must be public, static, and have the [JSInvokable] attribute. Varsayılan olarak, yöntem tanımlayıcısı yöntem adıdır, ancak JSInvokableAttribute oluşturucusunu kullanarak farklı bir tanımlayıcı belirtebilirsiniz.By default, the method identifier is the method name, but you can specify a different identifier using the JSInvokableAttribute constructor. Açık genel yöntemlerin çağrılması Şu anda desteklenmiyor.Calling open generic methods isn't currently supported.

Örnek uygulama, ints C# dizisini döndürmek için bir yöntem içerir.The sample app includes a C# method to return an array of ints. JSInvokable özniteliği yöntemine uygulanır.The JSInvokable attribute is applied to the method.

Pages/Jsınterop. Razor:Pages/JsInterop.razor:

<button type="button" class="btn btn-primary"
        onclick="exampleJsFunctions.returnArrayAsyncJs()">
    Trigger .NET static method ReturnArrayAsync
</button>

@code {
    [JSInvokable]
    public static Task<int[]> ReturnArrayAsync()
    {
        return Task.FromResult(new int[] { 1, 2, 3 });
    }
}

İstemciye sunulan JavaScript, C# .net yöntemini çağırır.JavaScript served to the client invokes the C# .NET method.

Wwwroot/Examplejsınterop. js:wwwroot/exampleJsInterop.js:

window.exampleJsFunctions = {
  showPrompt: function (text) {
    return prompt(text, 'Type your name here');
  },
  displayWelcome: function (welcomeMessage) {
    document.getElementById('welcome').innerText = welcomeMessage;
  },
  returnArrayAsyncJs: function () {
    DotNet.invokeMethodAsync('BlazorSample', 'ReturnArrayAsync')
      .then(data => {
        data.push(4);
          console.log(data);
    });
  },
  sayHello: function (dotnetHelper) {
    return dotnetHelper.invokeMethodAsync('SayHello')
      .then(r => console.log(r));
  }
};

Tetikleyici .net static yöntemi ReturnArrayAsync düğmesi seçildiğinde, tarayıcının Web geliştirici araçlarında konsol çıkışını inceleyin.When the Trigger .NET static method ReturnArrayAsync button is selected, examine the console output in the browser's web developer tools.

Konsol çıktısı:The console output is:

Array(4) [ 1, 2, 3, 4 ]

Dördüncü dizi değeri, ReturnArrayAsynctarafından döndürülen diziye (data.push(4);) gönderilir.The fourth array value is pushed to the array (data.push(4);) returned by ReturnArrayAsync.

Örnek yöntem çağrısıInstance method call

JavaScript 'ten de .NET örnek yöntemlerini çağırabilirsiniz.You can also call .NET instance methods from JavaScript. JavaScript 'ten bir .NET örnek yöntemi çağırmak için:To invoke a .NET instance method from JavaScript:

  • .NET örneğini bir DotNetObjectReference örneğine sarmalayarak JavaScript 'e geçirin.Pass the .NET instance to JavaScript by wrapping it in a DotNetObjectReference instance. .NET örneği, JavaScript 'e başvuruya göre geçirilir.The .NET instance is passed by reference to JavaScript.
  • invokeMethod veya invokeMethodAsync işlevlerini kullanarak örnekte .NET örnek yöntemlerini çağırın.Invoke .NET instance methods on the instance using the invokeMethod or invokeMethodAsync functions. .NET örneği, JavaScript 'ten başka .NET yöntemleri çağrılırken bir bağımsız değişken olarak da geçirilebilir.The .NET instance can also be passed as an argument when invoking other .NET methods from JavaScript.

Not

Örnek uygulama, iletileri istemci tarafı konsoluna kaydeder.The sample app logs messages to the client-side console. Örnek uygulama tarafından gösterilen aşağıdaki örnekler için tarayıcının geliştirici araçlarında tarayıcının konsol çıkışını inceleyin.For the following examples demonstrated by the sample app, examine the browser's console output in the browser's developer tools.

Tetikleyici .NET örnek yöntemi HelloHelper. SayHello düğmesi seçildiğinde, ExampleJsInterop.CallHelloHelperSayHello çağrılır ve Blazorbir adı yöntemine geçirir.When the Trigger .NET instance method HelloHelper.SayHello button is selected, ExampleJsInterop.CallHelloHelperSayHello is called and passes a name, Blazor, to the method.

Pages/Jsınterop. Razor:Pages/JsInterop.razor:

<button type="button" class="btn btn-primary" @onclick="TriggerNetInstanceMethod">
    Trigger .NET instance method HelloHelper.SayHello
</button>

@code {
    public async Task TriggerNetInstanceMethod()
    {
        var exampleJsInterop = new ExampleJsInterop(JSRuntime);
        await exampleJsInterop.CallHelloHelperSayHello("Blazor");
    }
}

CallHelloHelperSayHello, JavaScript işlevini sayHello yeni bir HelloHelperörneğiyle çağırır.CallHelloHelperSayHello invokes the JavaScript function sayHello with a new instance of HelloHelper.

JsInteropClasses/Examplejsınterop. cs:JsInteropClasses/ExampleJsInterop.cs:

public class ExampleJsInterop
{
    private readonly IJSRuntime _jsRuntime;

    public ExampleJsInterop(IJSRuntime jsRuntime)
    {
        _jsRuntime = jsRuntime;
    }

    public ValueTask<string> CallHelloHelperSayHello(string name)
    {
        // sayHello is implemented in wwwroot/exampleJsInterop.js
        return _jsRuntime.InvokeAsync<string>(
            "exampleJsFunctions.sayHello",
            DotNetObjectReference.Create(new HelloHelper(name)));
    }
}

Wwwroot/Examplejsınterop. js:wwwroot/exampleJsInterop.js:

window.exampleJsFunctions = {
  showPrompt: function (text) {
    return prompt(text, 'Type your name here');
  },
  displayWelcome: function (welcomeMessage) {
    document.getElementById('welcome').innerText = welcomeMessage;
  },
  returnArrayAsyncJs: function () {
    DotNet.invokeMethodAsync('BlazorSample', 'ReturnArrayAsync')
      .then(data => {
        data.push(4);
          console.log(data);
    });
  },
  sayHello: function (dotnetHelper) {
    return dotnetHelper.invokeMethodAsync('SayHello')
      .then(r => console.log(r));
  }
};

Ad, HelloHelper.Name özelliğini ayarlayan HelloHelperoluşturucusuna geçirilir.The name is passed to HelloHelper's constructor, which sets the HelloHelper.Name property. JavaScript işlevi sayHello yürütüldüğünde, HelloHelper.SayHello JavaScript işlevi tarafından konsola yazılan Hello, {Name}! iletisi döndürür.When the JavaScript function sayHello is executed, HelloHelper.SayHello returns the Hello, {Name}! message, which is written to the console by the JavaScript function.

JsInteropClasses/HelloHelper. cs:JsInteropClasses/HelloHelper.cs:

public class HelloHelper
{
    public HelloHelper(string name)
    {
        Name = name;
    }

    public string Name { get; set; }

    [JSInvokable]
    public string SayHello() => $"Hello, {Name}!";
}

Tarayıcının Web geliştirici araçlarında konsol çıkışı:Console output in the browser's web developer tools:

Hello, Blazor!

Birlikte çalışma kodunu bir sınıf kitaplığında paylaşmaShare interop code in a class library

JS birlikte çalışma kodu bir NuGet paketindeki kodu paylaşmanıza olanak sağlayan bir sınıf kitaplığına dahil edilebilir.JS interop code can be included in a class library, which allows you to share the code in a NuGet package.

Sınıf kitaplığı, yerleşik derlemede JavaScript kaynaklarını katıştırmayı işler.The class library handles embedding JavaScript resources in the built assembly. JavaScript dosyaları Wwwroot klasörüne yerleştirilir.The JavaScript files are placed in the wwwroot folder. Araç, kitaplık oluşturulduğunda kaynakları katıştırmaya önem kazanır.The tooling takes care of embedding the resources when the library is built.

Oluşturulan NuGet paketine, uygulamanın proje dosyasında herhangi bir NuGet paketiyle aynı şekilde başvurulur.The built NuGet package is referenced in the app's project file the same way that any NuGet package is referenced. Paket geri yüklendikten sonra, uygulama kodu JavaScript 'e, gibi çağrı yapabilir C#.After the package is restored, app code can call into JavaScript as if it were C#.

Daha fazla bilgi için bkz. ASP.NET Core Razor bileşenleri sınıf kitaplıkları.For more information, see ASP.NET Core Razor bileşenleri sınıf kitaplıkları.

Harden JS birlikte çalışma çağrılarıHarden JS interop calls

JS birlikte çalışması, ağ hataları nedeniyle başarısız olabilir ve güvenilmez olarak değerlendirilmelidir.JS interop may fail due to networking errors and should be treated as unreliable. Varsayılan olarak, bir Blazor sunucusu uygulaması, bir dakika sonra sunucu üzerinde JS birlikte çalışabilirlik çağrılarını zaman aşımına uğrar.By default, a Blazor Server app times out JS interop calls on the server after one minute. Bir uygulama, 10 saniye gibi daha agresif zaman aşımına uğrayedebilmesine, aşağıdaki yaklaşımlardan birini kullanarak zaman aşımını ayarlayın:If an app can tolerate a more aggressive timeout, such as 10 seconds, set the timeout using one of the following approaches:

  • Startup.ConfigureServicesgenel olarak, zaman aşımını belirtin:Globally in Startup.ConfigureServices, specify the timeout:

    services.AddServerSideBlazor(
        options => options.JSInteropDefaultCallTimeout = TimeSpan.FromSeconds({SECONDS}));
    
  • Bileşen kodunda çağrı başına, tek bir çağrı zaman aşımını belirtebilir:Per-invocation in component code, a single call can specify the timeout:

    var result = await JSRuntime.InvokeAsync<string>("MyJSOperation", 
        TimeSpan.FromSeconds({SECONDS}), new[] { "Arg1" });
    

Kaynak tükenmesi hakkında daha fazla bilgi için bkz. Güvenli ASP.NET Core Blazor Server uygulamaları.For more information on resource exhaustion, see Güvenli ASP.NET Core Blazor Server uygulamaları.

Ek kaynaklarAdditional resources