如何使用React / Om在输入onChange中传播文本

时间:2015-09-12 17:59:37

标签: reactjs clojurescript om

作为React / Om新手,我不确定这个问题是否特定于Om。

我想基于自由文本输入构建日期条目组件。它包含一个<input>字段,可以键入,<p>显示解析日期(如果有效)。

我将其实现为:

(defn parse-date [e owner]
  (let [text (.. e -target -value)]
    (om/set-state! owner :parsed-date text)))

(defn date-entry [app owner]
  (reify
    om/IInitState
    (init-state [_] {:parsed-date ""})
    om/IRenderState
    (render-state [this state]
      (dom/div nil
               (dom/input #js {:type "text" 
                               :ref "date"
                               :id "new-date"
                               :onChange #(parse-date % owner)})
               (dom/p     nil (:parsed-date state))))))

不幸的是,只要我插入此更改处理程序,它就不会按预期运行。当我在输入字段中输入一个数字时,我可以看到它出现在输入中并且旁边有<p>,但它会立即从输入中消失。

我可以通过将文本放在状态:

来解决这个问题
(defn parse-date [e owner]
  (let [text (.. e -target -value)]
    (om/set-state! owner :parsed-date text)
    (om/set-state! owner :text text)))

(defn date-entry [app owner]
  (reify
    om/IInitState
    (init-state [_] {:parsed-date "" :text ""})
    om/IRenderState
    (render-state [this state]
      (dom/div nil
               (dom/input #js {:type "text" 
                               :ref "date" 
                               :id "new-date" 
                               :onChange #(parse-date % owner) 
                               :value (:text state)})
               (dom/p     nil (:parsed-date state))))))

然而,我很惊讶我必须这样做。真的有必要吗?有人可以解释这里发生了什么或指向相关文档?为什么插入调用set-state!的更改处理程序会吞下事件?

1 个答案:

答案 0 :(得分:1)

是的,这是必要的。每次状态改变时,DOM都会重新呈现并清除您输入的值。因此,如果您的:value属性中没有:input,则会将其清除。

这样做的原因是当React.js开始使用虚拟DOM扩展真实DOM时,它会发现真实属性中有一些value,而虚拟中没有public class ProcessService extends Service { private Set<String> mLockedApps = new HashSet<String>(); private long lastModified = 0; private BroadcastReceiver mScreenStateReceiver; private File mLockedAppsFile; ArrayList<String> packagezList; SharedPreferences sharedPrefs; Map<String, ?> allEntries; SharedPreferences sharedPrefsapp; Object obj; private String prefix; private Handler handler; private DbAccess dbAccess; @Override public IBinder onBind(Intent arg0) { return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { startService(new Intent(this, ProcessService.class)); dbAccess=new DbAccess(this); if (TIMER == null) { TIMER = new Timer(true); TIMER.scheduleAtFixedRate(new LockAppsTimerTask(), 3000, 750); mScreenStateReceiver = new BroadcastReceiver() { private boolean screenOff; @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { screenOff = true; } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) { screenOff = false; } if (screenOff) { //Log.i(TAG, "Cancel Timer"); TIMER.cancel(); } else { // Log.i(TAG, "Restart Timer"); TIMER = new Timer(true); TIMER.scheduleAtFixedRate(new LockAppsTimerTask(), 1000, 250); } } }; IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON); filter.addAction(Intent.ACTION_SCREEN_OFF); registerReceiver(mScreenStateReceiver, filter); } // this.stopSelf(); //startforeground goes here return START_STICKY; } @Override public void onDestroy() { super.onDestroy(); startService(new Intent(this, ProcessService.class)); } private class LockAppsTimerTask extends TimerTask { @Override public void run() { sharedPrefs = getApplicationContext().getSharedPreferences(getApplicationContext().getPackageName(), Context.MODE_PRIVATE); sharedPrefsapp = getApplicationContext().getSharedPreferences("appdb", Context.MODE_PRIVATE); allEntries= null; allEntries = sharedPrefsapp.getAll(); //prefix = "m"; packagezList= null; packagezList = new ArrayList<String>(); for (Map.Entry<String, ?> entry : allEntries.entrySet()) { Log.e("right key: ", entry.getKey().toString() + "right value: " + entry.getValue().toString()); packagezList.add(entry.getKey()); } for(Object object: packagezList){ Log.e("Object!", (String) object); // Log.e("Package",""+packagezList.get(0)); } ActivityManager activityManager = (ActivityManager) getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE); try { //List<RecentTaskInfo> recentTasks = activityManager.getRecentTasks(1, ActivityManager.RECENT_IGNORE_UNAVAILABLE); ActivityManager mActivityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); List<ActivityManager.RunningTaskInfo> RunningTask = mActivityManager .getRunningTasks(1); ActivityManager.RunningTaskInfo ar = RunningTask.get(0); String activityOnTop = ar.topActivity.getPackageName(); Log.e("activity on Top", "" + activityOnTop); Log.e(" My package name", "" + getApplicationContext().getPackageName()); //for (Object data : newArrayList) { for(Object object: packagezList){ Log.e("My Object!", (String)object); if(activityOnTop.equals("com.android.settings")) { // you have to make this check even better Intent i = new Intent(getApplicationContext(), MainActivity.class); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_USER_ACTION); i.putExtra("callFromService",true); i.putExtra("ApppakageName", "com.android.settings" ); startActivity(i); } } } catch (Exception e) { Log.e("Foreground App", e.getMessage(), e); } } } } DOM,因此它会清除它,假设它是你想要的。您应该始终明确DOM应该是什么样的(例如,您的第二个片段)。