From 5dee570cb22af49b853d733e69bc6105cd40d5eb Mon Sep 17 00:00:00 2001 From: Roan Kattouw Date: Fri, 5 Nov 2021 15:53:34 -0700 Subject: [PATCH] search: Prepare for Vue 3 migration Port the initialization code for the Vue search to use Vue.createMwApp() instead of new Vue( ... ). The former mimicks Vue 3's API for mounting components. Without this change, this code breaks in Vue 3 (even in compatibility mode) because the compat support for new Vue(...) is imperfect. By the time renderFn is called, the searchForm container has already been emptied by Vue's internal mounting code. Instead, inspect searchForm and generate the prop list before mounting, then pass the props to createMwApp() and mount the component. Bug: T294476 Depends-On: I1fcdcf7bf87f5af2deb9763a231f2c360ea45b23 Change-Id: I5b6e66051d97e75f8f03b8258894daba22525797 --- .../skins.vector.search.js | 40 ++++++------------- 1 file changed, 12 insertions(+), 28 deletions(-) diff --git a/resources/skins.vector.search/skins.vector.search.js b/resources/skins.vector.search/skins.vector.search.js index dc7fcd24..e614d11a 100644 --- a/resources/skins.vector.search/skins.vector.search.js +++ b/resources/skins.vector.search/skins.vector.search.js @@ -1,17 +1,15 @@ /** @module search */ + var Vue = require( 'vue' ).default || require( 'vue' ), App = require( './App.vue' ), config = require( './config.json' ); /** - * @param {Function} createElement * @param {Element} searchForm - * @return {Vue.VNode} - * @throws {Error} if the searchForm does not - * contain input[name=title] and input[name="search"] elements. + * @return {void} */ -function renderFn( createElement, searchForm ) { +function initApp( searchForm ) { var titleInput = /** @type {HTMLInputElement|null} */ ( searchForm.querySelector( 'input[name=title]' ) @@ -23,8 +21,9 @@ function renderFn( createElement, searchForm ) { throw new Error( 'Attempted to create Vue search element from an incompatible element.' ); } - return createElement( App, { - props: $.extend( { + // @ts-ignore + Vue.createMwApp( + App, $.extend( { id: searchForm.id, autofocusInput: search === document.activeElement, action: searchForm.getAttribute( 'action' ), @@ -33,27 +32,10 @@ function renderFn( createElement, searchForm ) { searchTitle: search.getAttribute( 'title' ), searchPlaceholder: search.getAttribute( 'placeholder' ), searchQuery: search.value - }, // Pass additional config from server. - config - ) - } ); -} - -/** - * @param {NodeList} searchForms - * @return {void} - */ -function initApp( searchForms ) { - searchForms.forEach( function ( searchForm ) { - // eslint-disable-next-line no-new - new Vue( { - el: /** @type {Element} */ ( searchForm ), - render: function ( createElement ) { - return renderFn( createElement, /** @type {Element} */ ( searchForm ) ); - } - } ); - } ); + }, config ) + ) + .mount( searchForm ); } /** * @param {Document} document @@ -63,6 +45,8 @@ function main( document ) { var searchForms = document.querySelectorAll( '.vector-search-box-form' ); - initApp( searchForms ); + searchForms.forEach( function ( searchForm ) { + initApp( searchForm ); + } ); } main( document );