Heim  >  Artikel  >  Web-Frontend  >  Beispiel für eine praktische Projektzusammenfassung von Vue Family Bucket

Beispiel für eine praktische Projektzusammenfassung von Vue Family Bucket

小云云
小云云Original
2017-12-28 09:44:502595Durchsuche

Aus Front-End-Sicht kann man sagen, dass Vue derzeit das idealste Front-End-MVVM-Framework ist, und der Einstieg ist einfach Bucket (Vue+Vue-Router+Vuex). Der Prozess des jQuery+Template-Projekts und was ich während des Prozesses gelernt habe. In diesem Artikel wird hauptsächlich die praktische Projektzusammenfassung von Vue Family Bucket vorgestellt (empfohlen). Der Herausgeber findet sie recht gut, daher werde ich sie jetzt mit Ihnen teilen und als Referenz verwenden. Folgen wir dem Herausgeber und schauen wir uns das an. Ich hoffe, es kann allen helfen.

Erste Schritte

Die offizielle Dokumentation von Vue ist das beste Tutorial zum Erlernen von Vue. Es kann sein, dass der Autor des Frameworks kein Designer ist -Endhintergrund, damit alle Arten abstrakter Konzepte in Vue auf die verständlichste Weise erklärt werden können. Hier wird nur eine kurze Einführung in die Konzepte von Vue, Vue-Router und Vuex empfohlen die offizielle Dokumentation.

Vue

Die Kernfunktion von Vue ist die bidirektionale Bindung, mit der schnittstellengesteuerte Datenänderungen und datengesteuerte Schnittstellenänderungen automatisch realisiert werden können, was zu einer erheblichen Reduzierung führen kann die Kosten für die Entwicklung interaktiver Front-End-Anwendungen. Es gibt mehr als ein ähnliches Framework wie Vue, aber die Implementierung von Vue bietet gewisse Leistungsvorteile durch die Nutzung der nativen Funktionen von ES5.

Vue-Router

Vue-Router ist die offizielle Route, mit der die Zuordnungsbeziehung zwischen URLs und Komponenten organisiert und automatisch auf URL-Änderungen an den Komponenten reagiert wird. So müssen sich Entwickler nur auf die Komponentenentwicklung konzentrieren, und das Routing hilft Ihnen bei der Lösung verwandter trivialer Probleme.

Vuex

Vuex bietet ein zentralisiertes Datenverwaltungsmodell für den Umgang mit komplexen Datenflusssituationen, z. B. wenn mehrere Komponenten Daten gemeinsam nutzen, aber unabhängig voneinander arbeiten. Dies kann dazu führen, dass die Daten synchronisiert werden Daten sind nicht synchronisiert, oder weil der Hook des Objektobjekts in js auf dieselbe Instanz im Speicher zeigt, werden andere Komponenten kontaminiert, sobald die Originaldaten manipuliert werden. In diesem Fall ist ein besser organisierter Datenbetriebsmodus erforderlich. Das ist Vuex.

Technische Auswahl

Vergleich mit jQuery

Nachdem Sie die Grundkonzepte von Vue verstanden haben, werden Sie definitiv unbewusst sein, sie zu vergleichen mit dem jQuery-Technologie-Stack und frage mich, ob diese Dinge für mein Unternehmen wirklich notwendig sind.

Können die von MVVM gelösten Probleme zunächst mit jQuery gelöst werden? Die Antwort lautet: Ja. Erinnern Sie sich, dass Sie beim Absenden des Formulars jQuery verwendet haben, um Werte nacheinander aus den Eingaben abzurufen? Dies sind schnittstellengesteuerte Daten. Wenn Sie asynchrone interaktive Funktionen ausgeführt haben, sollten Sie Erfahrung mit der Verwendung von jQuery haben, um Ajax-Daten in verschiedene Elemente in der Schnittstelle einzugeben. Obwohl dies möglich ist, ist es etwas umständlich. Selbst wenn Sie ein Formularüberprüfungs-Plug-in und eine Front-End-Vorlagen-Engine verwenden, müssen Sie die Überprüfungsmethode und die Rendering-Methode auf jedem laufenden Knoten manuell aufrufen eine Website-Seite zu erstellen, aber wenn die Anforderungen bis zu einem gewissen Grad komplex sind, wird dies eine große Belastung sein.

Dann gibt es Routing, das die Schnittstellenumschaltung und Schnittstellenwartung durch den Betrieb von URLs ermöglicht. Dies hat eigentlich nichts mit dem Technologie-Stack zu tun Es werden Routing-Anforderungen generiert, und selbst auf jQuery basierende Projekte können dies tun. Es handelt sich lediglich um eine neu erstellte Route, aber Single-Page-Anwendungen werden im jQuery-Zeitalter selten erstellt.

Vuex basiert vollständig auf der bidirektionalen Bindung, was dem Hinzufügen eines Brokers zwischen den Daten und der Komponente entspricht. Die Komponente kann die Daten nicht direkt bedienen und kann nur Betriebsanforderungen an den Broker übermitteln Der Broker Um den Vorgang zu implementieren, können wir verschiedene unvorhersehbare Probleme lösen, die durch zu viele Personen verursacht werden, und die Daten werden aus der Anwendung verschoben. Außerdem wird ein Speicher speziell eingerichtet, um das Problem der Datenkontamination zwischen Komponenten zu beseitigen. Es sollte gesagt werden, dass jQuery diesen Bedarf nicht hat, da jQuery die Daten vollständig manuell verarbeitet und es überhaupt keine unerwarteten Situationen gibt.

Anwendbare Szenarien

Nach dem Vergleich mit jQuery sind die anwendbaren Szenarien von Vue offensichtlich. Aus Entwicklungssicht sind Projekte mit komplexeren Interaktionen am besten geeignet Geeignete, inhaltsbasierte Websites sind am wenigsten geeignet. Wenn Bedarf für einzelne Seiten der Website besteht, können diese auch lokal verwendet werden, beispielsweise für Warenkorbseiten.

Natürlich muss dies alles auf der Annahme basieren, dass es nicht mit IE8 kompatibel ist. Ich bin darüber etwas verwirrt, weil ich gesehen habe, dass einige 2C-Sites Vue verwenden ihre Chefs täuschen?

Projektanalyse

Projekthintergrund

Das Refactoring-Projekt ist dieses Mal das Front-End-Komponentenmanagement, das für das vorherige entwickelt wurde Ich habe mich für die Rekonstruktion dieses Projekts entschieden, da ich mit den Anforderungen vertraut bin. Es handelt sich um eine typische einseitige Anwendung mit mäßiger Komplexität, daher eignet sie sich eher für eine praktische Übung.

Der Hintergrund des Projekts ist, dass beim Outsourcing von Website-Erstellungsunternehmen im Designprozess eine große Anzahl wiederverwendbarer Komponenten anfällt. Designer müssen die Komponenten oft nur verfeinern, um die Seite zusammenzusetzen und zu liefern Theoretisch können diese Komponenten auch im Frontend wiederverwendet werden, tatsächlich muss das Frontend jedoch jedes Mal die gesamte Seite neu implementieren, was viel Arbeitskraft verschwendet.

Funktionale Anforderungen

Die Idee dieses Projekts besteht darin, alle Komponenten zu entwickeln und in eine einheitliche Plattform für die Verwaltung einzugeben. Designer können auf der Plattform Komponenten auswählen und in Echtzeit eine Vorschau der Komponenten anzeigen und anpassen Sie erhalten während des gesamten Prozesses und die Plattform nimmt Anpassungen vor. Als Ergebnis wird eine Codezeichenfolge generiert. Solange der Code an das Frontend übergeben wird, können Sie diese Codezeichenfolge verwenden, um die geänderte Komponente zu reproduzieren vom Designer auf der Plattform können Sie den HTML/CSS/JS-Code der Komponente auch mit einem Klick kopieren und schnell auf das Projekt Go anwenden, wodurch die Front-End-Entwicklungskosten des Komponententeils nahezu Null sind. Die Plattform muss die folgenden Funktionen implementieren:

  1. Komponenten verwalten, Klassifizierung, Suche, Sortierung unterstützen

  2. Komponenten anzeigen, Online-Vorschau/Bearbeitung unterstützen von Komponenten

  3. Komponentenübergabe, unterstützt das Generieren von Komponentencode und das Reproduzieren von Komponenten basierend auf Code

  4. Nutzungsstatistiken, unterstützt Statistiken über die Komponentennutzung zur weiteren Erleichterung Optimierungskomponente

Funktionsanalyse

Dieser Technologie-Stack ist zu flexibel Es kann jeden Bedarf erfüllen, aber der Nachteil ist, dass es unabhängig von der Art und Weise umgesetzt werden kann. Es trägt nicht dazu bei, Ihre Ideen zu klären, und es geht dabei oft mit Änderungen einher.

Die Komponenten werden in einem widgets/-Ordner abgelegt, der als Komponentenbibliothek bezeichnet wird. Da es sich um ein reines Front-End-Projekt ohne Dateioperationsfunktionen handelt, ist das Lesen von Komponenten auf eine statische JSON-Datei angewiesen, die fungiert als Komponentenbibliothek. Verzeichnis, das alle Informationen wie Komponentenklassifizierung, Bezeichnung, Name, Datum usw. enthält. Die Datenstruktur ist ungefähr wie folgt:


[{
 "title": "导航类",
 "list": [{
 "widget": "bread-1",
 "title": "图标面包屑",
 "tag": "面包屑/图标",
 "author": "UI",
 "date": "2015-06-04"
 }, 
 ...]
},
...]

Komponenten werden in der Komponentenbibliothek nach Spalte/Nummer aufgelistet. Sie werden in Form eines sekundären Ordners gespeichert und es wird vereinbart, das Speicherverzeichnis als Komponentencode zu verwenden. Beispielsweise bedeutet Komponente bread-1, dass die Speicheradresse der Komponente lautet den Ordner widgets/bread/1/.

Natürlich muss auch die interne Dateistruktur der Komponente vereinbart werden, und zwar wie folgt:


widgets
  |-bread
    |-1
      |-album.jpg   //缩略图
      |-config.json  //配置文件
      |-script.js   //脚本模板
      |-style.css   //样式模板
      `-temp.htm   //界面模板

Mit diesen Vereinbarungen kann das Programm erhalten werden Alle Dateien über die Verzeichnisdatei Komponenteninformationen, Komponentenerfassung, -anzeige und -abruf können ebenfalls realisiert werden.

Der kritischste Teil der Komponente ist die Datei config.json, die die konfigurierbaren Elemente der Komponente und ihre Standardwerte enthält. Die Plattform liest diese Konfigurationsdatei, wenn sie die Komponente anzeigt, und generiert ein Konfigurationsfenster basierend darauf Konfigurationsinformationen. Hier können Sie alle Variablen in Komponentenschnittstellen, Stilen und Skripten definieren. Die Konfigurationsdatei sieht wahrscheinlich so aus:


{
 "cssConfig": {
 "fontSize": {
  "name": "字号",
  "value": "12px",
  "type": "text"
 },
 ...
 },
 "jsConfig": {
    ...
 },
 "showConfig": {
 "viewWidth": {
  "name": "栅格宽度",
  "value": 12,
  "type": "number"
 },
 ...
 }
}

Es gibt drei cssConfig, showConfig , und jsConfig in der Konfigurationsdatei ist eine Sammlung aller Variablen, die in einer Komponente geändert werden können. Wenn Sie diese Variablen auf die Komponente anwenden möchten, müssen Sie die drei wichtigsten verwenden Komponenten der Komponente werden während der Entwicklung in der Vorlagensyntax geschrieben. Nach der Analyse durch die Vorlagen-Engine können Sie den tatsächlichen HTML-/CSS-/JS-Inhalt nach der Konfiguration erhalten. Die Stilvorlage sieht beispielsweise so aus:


.widget-bread-1 {
  font-size: ${fontSize.value}; 
  color: ${textColor.value}; 
}
.widget-bread-1 a { 
  color: ${textColor.value};
}
.widget-bread-1 a:hover{
  color:${hoverColor.value};
}
.widget-bread-1 .ion { 
  font-size: ${iconSize.value}; 
  margin: 0 ${iconMargin.value};
}

Nachdem Sie den eigentlichen Code der Komponente erhalten haben, fügen Sie einfach das Ergebnis hinzu. Fügen Sie es einfach in die Seite ein und aktualisieren Sie es rechtzeitig. HTML und CSS können den Textinhalt direkt ersetzen. Da js modular eingeführt wird, wird nur der Modulinhalt ersetzt und das Modul wird nicht überlastet. Das gesamte Modul muss umbenannt und als Ganzes ersetzt werden, sodass js die Namen der Module zufällig sind.

Hier liegt ein Problem vor, das mehrere Male auf der Seite verwendet werden muss, sodass der js-Selektor dieser Komponente in Konflikt gerät. Dieses Problem kann mithilfe des zufälligen Namens des js gelöst werden Modul Wir sind uns einig, dass bei der Komponentenentwicklung die ID als reservierte Variable verwendet wird und die Plattform automatisch eine zufällige Zeichenfolge zuweist. Diese Zeichenfolge ist innerhalb der Komponenteninstanz identisch, unterscheidet sich jedoch, wenn sie mehrmals aufgerufen wird Solange ${id} als ID oder Klasse des übergeordneten Knotens der Komponente verwendet wird, wird das Problem von Selektorkonflikten gelöst und es kann auch als CSS-Namespace der Komponente verwendet werden, sodass mögliche CSS-Namenskonflikte vermieden werden können unsichtbar gelöst werden.

Die oben genannten sind die Kernfunktionen des Projekts.

Darüber hinaus wird localStorage als Speichermethode zum Implementieren eigenständiger Datenstatistiken verwendet, mit denen Komponentennutzungsdatensätze des aktuellen Browsers und die Konfiguration jeder Verwendung erfasst werden können. Dies ist hauptsächlich der Betrieb des lokalen Speichers. Die Entwicklung des Projekts selbst verwendet jedoch auch Front-End-Vorlagen sowie Komponentenvorlagen, die nach dem ersten Laden mit localStorage zwischengespeichert werden. Die Caching-Strategien für diese Inhalte sollten unterschiedlich sein, und die Projektvorlagen sollten unterschiedlich sein Manuell aktualisiert. Die Vorlage muss je nach Situation bestimmt werden. Wenn zu viele Inhalte gespeichert werden, ist es unrealistisch, sie alle während der Bereinigung zu löschen Der Ansatz hier besteht darin, den LocalStorage-Vorgang zu kapseln und die Speichermethode vor dem Schlüssel hinzuzufügen. Beim Löschen müssen Sie nur den lokal gespeicherten Schlüssel durchlaufen und feststellen, ob er mit dem Präfix übereinstimmt Die entsprechende Wertmethode muss das Präfix auch in umgekehrter Reihenfolge zum Schlüssel hinzufügen.

Darüber hinaus unterstützt localStorage nur den Zugriff auf Zeichenfolgen. Um unseren Zugriff auf Objekttypen zu erleichtern, unterstützt die Kapselungsmethode auch die automatische Konvertierung. Diese Konvertierung kann jedoch nicht blind in Zeichen konvertiert werden, wenn ein Objekt gefunden wird, und stimmt überein, wenn der Wert vorhanden ist Wenn das Objekt übertragen werden kann, wird das Objekt automatisch übertragen, da der Benutzer manchmal tatsächlich eine Objektzeichenfolge speichern möchte und sie beim Herausnehmen wieder so erhalten möchte, wie sie ist kleiner Hack. Wenn die Speichermethode den Wert erkennt, wird er in eine Zeichenfolge umgewandelt und dann wird eine Identifikationszeichenfolge vorangestellt. Die Wertmethode stellt die folgende Zeichenfolge erst wieder für ein Objekt her, nachdem diese Identifikation erkannt wurde Obwohl diese Methode die Anforderungen erfüllen kann, ist sie nicht sehr sicher, da dieses Präfix festgelegt ist und es theoretisch immer möglich ist, auf einen Lottogewinner zu stoßen Problem.

Die Hauptfunktionspunkte des Projekts sind diese.

Rekonstruktion

Eine Rekonstruktion

Bei der ersten Rekonstruktion wurde nur Vue verwendet, der erste Schritt Was ich Erfahrung ist, dass ich ursprünglich die Template-Engine aufrufen musste, um Ereignisse in js zu binden, aber jetzt kann ich sie direkt in die Vorlage binden, und es gibt verschiedene andere Syntaxen Zucker.

Das Wichtigste ist natürlich die bidirektionale Bindung. Basierend auf der bidirektionalen Bindung können Schnittstelle und Daten automatisch verknüpft werden, sodass die Benutzer das Gefühl haben, dass das Programm über ein gewisses Maß an Autonomie verfügt Damit diese Autonomie normal funktioniert, müssen Entwickler jeden Schritt im Voraus planen, was weniger kostenlos ist als jQuery. Nehmen Sie als Beispiel das Bewegen von Steinen. jQuery ist wie ein besonders flexibler Kran, der Steine ​​auf einfache Weise heben und bewegen kann. Vue ist wie eine universelle Fernbedienung Was während des Vorgangs passiert, hängt davon ab, wie damit umgegangen wird. Die Steine ​​können durch Drücken der Taste automatisch verschoben werden.

Beide Methoden haben ihre eigenen Vor- und Nachteile. Wenn der Kran gut gefahren wird, ist es einfach, Gruben auf der Straße zu vermeiden Auch hier kann der Knopf so programmiert werden, dass er automatisch auf einmal läuft. Der Nachteil besteht darin, dass Sie die Schlaglöcher auf der Straße im Voraus inspizieren, alle anderen Autos einplanen und alle Situationen klar erklären müssen, sonst wird das Auto umkippen oder abstürzen Wenn Sie von jQuery zu Vue wechseln, werden Sie auf jeden Fall dazu gezwungen werden: „Sie können nicht zuerst ins Auto steigen und dann darüber reden.“

Ein großer Teil der Arbeit während der Rekonstruktionsphase besteht darin, Vue-Instanzen einzurichten, die in allen Ecken von js verstreuten Daten in Daten zu sammeln und den Prozess der Verarbeitung von Daten Stück für Stück in Methoden zu konzentrieren und diese zu übertragen Daten Der Screening-Prozess konzentriert sich auf die Berechnung aller Implementierungsdetails und überlegt, ob jede Implementierungsmethode sinnvoll ist. Tatsächlich geht es darum, den ursprünglichen Prozess des Fahrens eines Krans einzeln in Fernbedienungstasten zusammenzufassen. Wenn alles Nachdem die Zusammenfassung abgeschlossen ist, wird das Vue-Beispiel zu unserem endgültigen Projekt und kann automatisch ausgeführt werden.

Nach der Rekonstruktion hat sich die Codemenge im Logikteil reduziert, da es kein Routing gibt, das Problem des Verlusts Der Status der Aktualisierungsseite besteht weiterhin. Da Vuex nicht verwendet wird, ist eine Datenverschmutzungsgrube vorhanden, die nur durch tiefes Kopieren gelöst werden kann. Diese Probleme erfordern eine sekundäre Rekonstruktion .

Zweite Rekonstruktion

Das Ziel der zweiten Rekonstruktion ist die Verbesserung von Routing, Vuex, Code-Organisation und Wild Dog Cloud-Backend.

Obwohl ich die Erfahrung des ersten Refactorings habe, bin ich zu Beginn des zweiten Refactorings immer noch etwas verwirrt. Welches sollte zuerst implementiert werden, Routing oder Vuex? Nachdem ich darüber nachgedacht habe, ist das, was das Routing macht, „abreißen“ und was Vuex macht, ist „modifizieren“. Ich habe das Gefühl, dass der Arbeitsaufwand für die Demontage nach der Änderung geringer sein wird, also verwende ich zuerst Vuex.

Das Konzept von Vuex ist etwas abstrakt, aber wenn man es einmal verwendet, fühlt man sich sehr wohl. Darüber hinaus kann es im Gegensatz zum Routing fast ohne Unterscheidungsszenarien verwendet werden Vuex wird das Problem der Datenverschmutzung natürlich lösen. Der von Vuex eingeführte Aktions- => Mutations- => Speicherprozess wird die Dinge nach der Akzeptanz wirklich vereinfachen. Der Prozess der Einführung von Vuex besteht im Wesentlichen darin, Daten in den Speicher zu übertragen und zu verteilen Datenoperationen in Aktionen, Getter und Mutationen umwandeln, und gleichzeitig werden viele synchronisierte Datenoperationen nicht mehr benötigt, wodurch die Codemenge reduziert wird.

Danach begann ich mit der Einführung des Routings. Die großen Ansichten müssen Anmeldung, Registrierung und Hauptschnittstelle sein Theoretisch kann es in viele Teile unterteilt werden, aber in Kombination mit den tatsächlichen Nutzungsszenarien der Anwendung wird festgestellt, dass der Schnittstellenwechsel relativ häufig ist und das häufige Laden und Entladen von Komponenten sehr teuer ist. Darüber hinaus erfordert die Aufteilung eng gekoppelter Komponenten in verschiedene Ansichten die Aufzeichnung vieler Statusinformationen, was die Vorteile etwas überwiegt. Am Ende habe ich aufgegeben und die Hauptansicht nicht weiter unterteilt. Da die Zugriffsüberlappung der drei Ansichten nicht hoch ist, ist es selbstverständlich, die Komponente asynchron zu laden und die Komponente nur zu laden, wenn auf sie zugegriffen wird. Vue selbst unterstützt asynchrone Komponenten, sodass dies sehr einfach wird, sofern dies möglich ist Geben Sie ein Versprechen zurück, Sie können Komponenten auf beliebige Weise erhalten.

Der nächste Schritt besteht darin, eine Verbindung zur Wild Dog Cloud herzustellen, um eine echte Benutzerverwaltung und Datenstatistik zu erreichen. Mit der Wild Dog Cloud können Sie eine Reihe von Funktionen wie Benutzerauthentifizierung und Datenspeicherung bereitstellen Verwenden Sie nur eine js-Anwendung. Auf diese Weise müssen alle vorherigen Vorgänge auf localStorage in Vorgänge in der Wild Dog Cloud geändert werden, und die Daten werden zuverlässiger, wenn sie die Cloud erreichen.

Zu diesem Zeitpunkt ist die zweite Rekonstruktion abgeschlossen. Der gesamte Geschäftscode wird jedoch voraussichtlich nicht viel geringer sein. Immerhin wurden jedoch drei Framework-Dateien hinzugefügt. Nach wiederholter Aufteilung ist die Anzahl der Dateien von ursprünglich drei oder zwei Js auf etwa zehn Js gesunken. Für die Modularisierung wird SeaJs anstelle von Webpack verwendet, da ich immer noch eine abwartende Haltung gegenüber Webpack habe Ich habe nicht das Bedürfnis, es zu verwenden. Der Code wird mit vielen privaten Dingen vermischt, sodass Ihr Code nicht ganz ohne ihn ausgeführt werden kann Akzeptieren Sie dies. Darüber hinaus bietet Seajs in Kombination mit lokalem Caching mehr Vorteile als der Unterschied zwischen jQuery und Vue Im Nutzungsszenario ist das Passende das Beste.

Postscript

Nach zwei Refactoring-Praktiken und Fallstricken habe ich ein tieferes Verständnis des Vue-Frameworks, ich möchte Vue flexibel und frei nutzen und habe ein gutes Verständnis Es gibt eine Mindestanforderung an die Projektarchitekturfähigkeiten des Projekt-Builders. Wenn Vue in die unterste Ebene eingeführt werden soll, gibt es auch eine Mindestanforderung an die Planungsfähigkeiten des Infrastruktur-Builders Der jQuery-Technologie-Stack und der Prozess der Verwendung von Vue akzeptieren auch diese Einschränkungen. Dabei können sie Entwickler dabei unterstützen, ihr eigenes Regelsystem zu etablieren, was eine gute Sache und ein allgemeiner Trend ist.

Der vollständige Code dieses Artikels ist auf Github zu finden.

Verwandte Empfehlungen:

Detaillierte Erläuterung der Verwendung von React Family Bucket zum Erstellen einer Hintergrundverwaltungssysteminstanz

Von FamilyMart entwickelte Vue2.0-Webanwendung (siehe Wuji-APP)

Beispiel für eine detaillierte Erklärung der Vue-Verbundkomponente zur Implementierung der Registrierungsformularfunktion

Das obige ist der detaillierte Inhalt vonBeispiel für eine praktische Projektzusammenfassung von Vue Family Bucket. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn