我使用 Node.js 作为后端和HTML / CSS / JS作为前端开发Web应用程序。我正在尝试使用 Express 框架构建单页应用。
我想使用Node.js或JavaScript构建单个页面应用程序,我知道对于响应,我们可以调用类似res.render('contact')
的内容,但这不适用于我的情况,因为我不想动态更改我的页面,我不想要任何其他框架,如React,Angular,...
在我的 index.html 页面上,有一个菜单,其每个元素都包含一个hyperLink。例如,当点击索引页面中的联系人hyperLink时,我希望动态地在同一页面上显示联系页面的内容和表格...而不加载页面:
<li> <a href="/contact">Contact</a></li>
我的 server.js 文件定义了路由,默认情况下我被定向到索引页面:
//to define the routes
var express = require('express'), app = express();
//to call multiple template engines easly, like html page...ect
var engines = require('consolidate');
app.engine('html', engines.nunjucks);
app.set('view engine', 'html');
app.set('views', __dirname + '/public');
app.use(express.static(__dirname + '/public'));
app.get('/', function(req, res){
res.render('index');
});
app.get('/contact', function(req, res){
res.render('views/contact');
});
var server = app.listen(8080, function(){
console.log('Listening on port ' + server.address().port);
});
我知道SPA存在于单个HTML文档中,但是如何在不加载页面的情况下使用Express Framework执行此操作?我有点失落。
答案 0 :(得分:4)
您的问题非常广泛,但我会尝试解释一些可能有用的内容。
Express的工作是处理HTTP请求并返回响应。其中一些响应将是HTML文件,可能使用JavaScript和CSS。
要创建SPA,您至少需要向客户端的浏览器提供一堆HTML和JavaScript作为起点,通常是import UIKit
import MapKit
import CoreLocation
class MapVC: UIViewController, UIGestureRecognizerDelegate {
@IBOutlet weak var pullUpViewHighConstraint: NSLayoutConstraint!
@IBOutlet weak var pullUpView: UIView!
@IBOutlet weak var mapView: MKMapView!
var locationManager = CLLocationManager()
var authStatus = CLLocationManager.authorizationStatus()
let regiounRadius: Double = 1000
var spinner: UIActivityIndicatorView?
var progrssLabel: UILabel?
var screen = UIScreen.main.bounds
override func viewDidLoad() {
super.viewDidLoad()
mapView.delegate = self
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.mapView.showsUserLocation = true
configureLocationServices()
addDoubleTap()
}
func addDoubleTap() {
let doubleTap = UITapGestureRecognizer(target: self, action: #selector(droupPin(sender:)))
doubleTap.numberOfTapsRequired = 2
doubleTap.delegate = self
mapView.addGestureRecognizer(doubleTap)
}
func addSwipe() {
let swipe = UISwipeGestureRecognizer(target: self, action: #selector(animateViewDown))
swipe.direction = .down
pullUpView.addGestureRecognizer(swipe)
}
func animateViewUp() {
pullUpViewHighConstraint.constant = 300
UIView.animate(withDuration: 0.4) {
self.view.layoutIfNeeded()
}
}
@objc func animateViewDown() {
pullUpViewHighConstraint.constant = 0
UIView.animate(withDuration: 0.4) {
self.view.layoutIfNeeded()
}
}
func addSpinner() {
spinner = UIActivityIndicatorView()
spinner?.center = CGPoint(x: screen.width / 2 - (spinner?.frame.width)! / 2, y: 150)
spinner?.activityIndicatorViewStyle = .whiteLarge
spinner?.color = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)
spinner?.stopAnimating()
pullUpView.addSubview(spinner!)
}
@IBAction func centerMapBtnPressed(_ sender: Any) {
if authStatus == .authorizedAlways || authStatus == .authorizedWhenInUse{
centerMapOnUserLocation()
// removePin()
}else {return}
}
}
extension MapVC: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
let pinAnnotation = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "droppablePin")
pinAnnotation.pinTintColor = #colorLiteral(red: 0.9771530032, green: 0.7062081099, blue: 0.1748393774, alpha: 1)
pinAnnotation.animatesDrop = true
return pinAnnotation
}
func centerMapOnUserLocation() {
guard let coordinets = locationManager.location?.coordinate else { return }
let coordinateRegion = MKCoordinateRegionMakeWithDistance(coordinets, regiounRadius*2.0, regiounRadius*2.0)
mapView.setRegion(coordinateRegion, animated: true)
}
@objc func droupPin(sender: UITapGestureRecognizer) {
removePin()
animateViewUp()
addSwipe()
addSpinner()
let touchPoint = sender.location(in: mapView)
let touchCoordinate = mapView.convert(touchPoint, toCoordinateFrom: mapView)
let annotation = DroppablePin(coordinatee: touchCoordinate, identifierr: "droppablePin")
mapView.addAnnotation(annotation)
let coordinateRegion = MKCoordinateRegionMakeWithDistance(touchCoordinate, regiounRadius*2.0, regiounRadius*2.0)
mapView.setRegion(coordinateRegion, animated: true)
}
func removePin() {
for annotation in mapView.annotations {
mapView.removeAnnotation(annotation)
}
}
}
extension MapVC: CLLocationManagerDelegate {
func configureLocationServices() {
if authStatus == .notDetermined {
locationManager.requestAlwaysAuthorization()
}
else {
return
}
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
centerMapOnUserLocation()
}
}
页面。
此页面通过JavaScript和HTML,可以侦听事件,包括用户操作和输入,并回拨到Express服务器上的其他端点,而不是返回数据,HTML代码段或任何您需要的内容更改您为用户提供的单页。但是,更改必须由初始页面上存在的JavaScript执行,或者由初始JavaScript添加并执行的脚本执行。
例如,您可以使用jQuery或index.html
来回调您的服务器,甚至是浏览器中的basic web APIs。还有其他工具可用。