iT邦幫忙

2021 iThome 鐵人賽

0
Modern Web

Laravel Livewire:不用 Vue 跟 jQuery 居然也能讓 Laravel 的畫面動起來 ?!系列 第 32

Day 31 | 常見 Livewire 問題: jQuery 在渲染時會打回原形

  • 分享至 

  • xImage
  •  

jQuery 在大多數的專案中都不可或缺,在沒有 Livewire 之前要修改畫面都要靠它來手動更改。但使用了 Livewire 後,Livewire 的渲染機制居然會導致 jQuery 失效!??

ㄧ、先簡單建立一個有使用 jQuery 的功能

先簡單用在畫面上印出一個 Hello World,並透過 jQuery 去將它改成 你好世界

<div>
    <p id="title">Hello World!!</p>
</div>

<script>
    $('#title').text('你好世界 !!')
</script>

https://ithelp.ithome.com.tw/upload/images/20211005/20111805KAb8ChF0V8.png

這時候畫面都很正常,原本的「HelloWorld」也有被正確的替換成 「你好世界」


二、給他一個 Input

這時我們就來做一些會產生頁面變動的事吧!只要輸入了值就會帶動下方的 $input_text 顯示跟著修改,到時候再來看會不會有問題!

public $input_text;
<div class="mt-5">
        <label>隨意輸入些什麼</label>
        <input type="text" wire:model="input_text">

        剛剛輸入的:{{ $input_text }}
    </div>

https://ithelp.ithome.com.tw/upload/images/20211005/20111805yNoZNEjt8N.png


三、輸入!然後爆炸!!!

咦咦咦咦咦! 隨著輸入的同時,上方的「你好世界」居然變回最原本的 Hello World 了 !!!

https://ithelp.ithome.com.tw/upload/images/20211005/2011180573OYkiAIyH.png


四、解決方法

壞掉的原因是因為畫面有變動時,會使頁面重新渲染都並致後來透過手動修改 DOM 的內容被打回原形。所以不光只有 jQuery 會有問題,就算是用原生的 document 去改動頁面都會有這個問題!

知道原因後,只要知道畫面哪時候改動再去執行一次改動的程式碼就好啦!!

因為要重新執行一次一模一樣的 code,因此可以考慮把載入頁面時執行的 JavaScript 都包進一個 Function ,這樣之後更新時直接呼叫一個就能跑全部。也要記得呼叫一次,這樣才會執行

<script>
    function init () {
        $('#title').text('你好世界 !!')
    }

    init()
</script>

之後加入 Livewire 的事件監聽,每當觸發 ReloadJS 事件就會執行一次:

Livewire.on('ReloadJS', () => {
    init()
})

由於 Livewire.on 必須跟最外層引入的 @livewireScripts 放一起才有作用,這個在講解該篇時也有提到。所以我們會用 @section('scripts') 將每個 Livewire 元件的 <scrpitt> 區塊包起來,好讓他被渲染至最外層。

完整的 JS 部分長這樣

@section('scripts')
<script>
    function init () {
        $('#title').text('你好世界 !!')
    }

    init()

    Livewire.on('ReloadJS', () => {
        init()
    })

</script>
@endsection

之後就可以在變動時透過 $this->emit('ReloadJS') 來觸發上面寫的監聽,這樣就算畫面重新渲染了也能重新執行修改 DOM 的程式碼!!所以我們可以很好地利用生命週期勾(Lifecycle Hooks)去呼叫它:

這裡不使用 updated 的原因很簡單,因為 updated 只會在 wire:model 修改時觸發。所以如果我在按鈕呼叫後端改值的函式,即便值被改了也不會觸發到 updated。

    public function hydrate()
    {
        $this->emit('ReloadJS');
    }

結論 & 心得

還是盡量不要手動去修改 DOM 的內容。不管是 VueJS 還是 Livewire 其實都可以透過資料去控制畫面的呈現,官方文件也都會呼籲儘量避免手動修改的操作。其實在 Vue 使用 jQuery 其實也很容易發生跟現在類似的問題 XD

不過 Vue 到現在已經有很大量的元件庫可以使用,不管是在表格、HTML頁面產生器等等功能都有 Vue 的版本可以用。而 Livewire 等還比較少類似的元件,因此還是很難避免使用到含有 jQuery 的前端套件。萬一遇到了也只能乖乖的一個一個照上方的方法做啦。


上一篇
Day 30 | 很像 Vue 的 AlpineJS(五): 與 Livewire 共享資料
下一篇
Day 32 | 常見 Livewire 問題:與 Controller 兼容的幾種方式
系列文
Laravel Livewire:不用 Vue 跟 jQuery 居然也能讓 Laravel 的畫面動起來 ?!34
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言