作为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!
的更改处理程序会吞下事件?
答案 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应该是什么样的(例如,您的第二个片段)。