为什么 phoenix liveview update/assign 消息使客户端 contenteditable 值恢复?
why phoenix liveview update/assign message make client contenteditable value revert?
使用 Phoenix 实时视图文档,我添加了一个用于编写实时表单应用程序的实时页面。有很简单的demo:
<h2>Hello</h2>
Counter is222: <%= @counter %>
<hr>
<button phx-click="dec">-</button>
<button phx-click="inc">+</button>
<table border="1">
<tr>
<th contenteditable="true">Month</th>
<th>S1</th>
<th>S2</th>
</tr>
<tr>
<td contenteditable="true">January</td>
<td contenteditable="true">0</td>
<td contenteditable="true">220</td>
</tr>
</table>
服务器端代码(就像文档一样):
defmodule TicTacWeb.MemberSchedulerLive do
use Phoenix.LiveView
def render(assigns) do
TicTacWeb.PageView.render("member_scheduler.html", assigns)
end
def mount(_, socket) do
{:ok, assign(socket, %{counter: 100})}
end
def handle_event("inc", _, socket) do
{:noreply, update(socket, :counter, fn(x) -> x + 1 end)}
end
def handle_event("dec", _, socket) do
IO.puts("item")
{:noreply, update(socket, :counter, fn(x) -> x - 1 end)}
end
end
问题是 <td contenteditable
值将在我单击 -
或 +
向服务器发送消息后恢复。
- 为什么
-
或 +
会影响 <td>
的值?是不是最小化更改修改了dom数据?
- 这种场景有没有最佳实践?
谢谢!
更新
添加contenteditable作为数据模型后,还是不行,如:
1. html 片段
....
<td contenteditable="true">0</td>
<td contenteditable="true" phx-blur="somedata"><%=@somedata%></td>
</tr>
</table>
- 后端
...
def mount(_, socket) do
{:ok, assign(socket, %{counter: 100, somedata: "[=14=]1"})}
end
如果单击 -
或 +
,@somedata
也会恢复为 $001。
why -
or +
affect <td>
’s value?
反之亦然。它们不影响 <td>
的值,相反,它发送 diff 之前的状态和更新的状态和前端 applies这个差异.
LiveView
不知道您使用 contenteditable="true"
进行的本地更改,因此它将所有内容重置为原始状态,除了更新的 :counter
。要支持 contenteditable="true"
,您需要使这些 <td>
成为数据模型的一部分,以便 LiveView
了解其中的变化。
我终于分两步解决了这个问题:
添加phx-update='ignore'
contenteditable 将不会更新!
在这个阶段,是<td contenteditable="true" phx-update='ignore'>220</td>
将phoenix_live_view更新为github: phoenixframework/phoenix_live_view
的0.4.1(锁定提交为:73e9a695eff1d7d21e4cb34ea9894835b3a2fa32),旧版本似乎不支持phx-update
希望对你也有帮助。
感谢@Aleksei Matiushkin,我将深入研究实时取景差异算法。
使用 Phoenix 实时视图文档,我添加了一个用于编写实时表单应用程序的实时页面。有很简单的demo:
<h2>Hello</h2>
Counter is222: <%= @counter %>
<hr>
<button phx-click="dec">-</button>
<button phx-click="inc">+</button>
<table border="1">
<tr>
<th contenteditable="true">Month</th>
<th>S1</th>
<th>S2</th>
</tr>
<tr>
<td contenteditable="true">January</td>
<td contenteditable="true">0</td>
<td contenteditable="true">220</td>
</tr>
</table>
服务器端代码(就像文档一样):
defmodule TicTacWeb.MemberSchedulerLive do
use Phoenix.LiveView
def render(assigns) do
TicTacWeb.PageView.render("member_scheduler.html", assigns)
end
def mount(_, socket) do
{:ok, assign(socket, %{counter: 100})}
end
def handle_event("inc", _, socket) do
{:noreply, update(socket, :counter, fn(x) -> x + 1 end)}
end
def handle_event("dec", _, socket) do
IO.puts("item")
{:noreply, update(socket, :counter, fn(x) -> x - 1 end)}
end
end
问题是 <td contenteditable
值将在我单击 -
或 +
向服务器发送消息后恢复。
- 为什么
-
或+
会影响<td>
的值?是不是最小化更改修改了dom数据? - 这种场景有没有最佳实践?
谢谢!
更新
添加contenteditable作为数据模型后,还是不行,如:
1. html 片段
....
<td contenteditable="true">0</td>
<td contenteditable="true" phx-blur="somedata"><%=@somedata%></td>
</tr>
</table>
- 后端
...
def mount(_, socket) do
{:ok, assign(socket, %{counter: 100, somedata: "[=14=]1"})}
end
如果单击 -
或 +
,@somedata
也会恢复为 $001。
why
-
or+
affect<td>
’s value?
反之亦然。它们不影响 <td>
的值,相反,它发送 diff 之前的状态和更新的状态和前端 applies这个差异.
LiveView
不知道您使用 contenteditable="true"
进行的本地更改,因此它将所有内容重置为原始状态,除了更新的 :counter
。要支持 contenteditable="true"
,您需要使这些 <td>
成为数据模型的一部分,以便 LiveView
了解其中的变化。
我终于分两步解决了这个问题:
添加
phx-update='ignore'
contenteditable 将不会更新!
在这个阶段,是<td contenteditable="true" phx-update='ignore'>220</td>
将phoenix_live_view更新为
github: phoenixframework/phoenix_live_view
的0.4.1(锁定提交为:73e9a695eff1d7d21e4cb34ea9894835b3a2fa32),旧版本似乎不支持phx-update
希望对你也有帮助。
感谢@Aleksei Matiushkin,我将深入研究实时取景差异算法。