Angularjs-Hello

1 关于Angularjs

最近因为项目需要又要做这个,所以简单复习下。其实这个大概7,8年前就用过,当时做了几个简单页面觉得太简单就还是回去做嵌入式了。按照互联网技术的进化速度,本来以为早死在 沙滩上了,没想到现在还在坚持。据说是google在后面支持,有这么强的亲爹,难怪能撑这么久。

之前用Angular是因为说的可以跨平台,也不知道现在还有没有。先还是对比一下现在流行的几个前端框架。

核心特性对比

框架 React (Meta) Vue (尤雨溪) Angular (Google) Svelte (Rich Harris)
类型 库(需搭配生态) 渐进式框架 全功能企业级框架 编译时框架
语言 JavaScript/JSX JavaScript/TypeScript TypeScript JavaScript/Svelte语法
数据流 单向(Props + State) 双向绑定(v-model) 双向绑定 + RxJS 响应式变量
DOM 更新 虚拟DOM Diff 虚拟DOM + 精确更新 变更检测(Zone.js) 编译为原生JS
学习曲线 中等 极低

对了,这里有两个版本。AngularJS(1.x)是旧版,Angular(2+)是全新框架,两者不兼容。

学习资料

AngularJS官方文档:AngularJS

AngularJS官方指南:AngularJS

AngularJS源码:GitHub - angular/angular.js: AngularJS - HTML enhanced for web apps!

=================================================

Angular官方文档: Angular

Angular快速手册:Angular

2 搭配Springboot的一个简单实现

SpringBoot简单体验(TODO)-CSDN博客

之前的SpringBoot是直接print,没法直接对接前端,所以现在要改成前后端的实现。

前后端的实现目前有两种,一种是完全集成到一起,还有一种是分开,只留API接口。貌似第二种更流行,所以也只看第二种。

+-------------------+ HTTP Requests +-------------------+

| | ------------------------------> | |

| AngularJS Front | (API Calls) | Spring Boot API |

| (Port: 3000) | <------------------------------ | (Port: 8081) |

| | JSON Responses | |

+-------------------+ +-------------------+

2.1 SpringBoot的改造

其实东西也不多。第一个是输出改成json。否则前端无法解析会报错。

bash 复制代码
angular.min.js:129 Error: [$http:baddata] http://errors.angularjs.org/1.8.3/$http/baddata?p0=Hello%20from%20Spring%20Boot!&p1=%7B%7D
    at angular.min.js:7:168
    at wc (angular.min.js:101:482)
    at angular.min.js:102:399
    at r (angular.min.js:8:76)
    at Bd (angular.min.js:102:381)
    at f (angular.min.js:104:472)
    at angular.min.js:141:454
    at m.$digest (angular.min.js:153:67)
    at m.$apply (angular.min.js:156:484)
    at k (angular.min.js:107:445) 'Possibly unhandled rejection: {}'

还有一个就是跨域。之前听说了好几次,今天看了一下原来就是浏览器本身的一个安全限制。

协议(protocol) 例如 http vs https

域名(host) 例如 localhost vs example.com

端口(port) 例如 3000 vs 8080

以上三个有一个不同,就算是跨域,要在代码中指定。

比如:

前端页面地址 请求的接口地址 是否跨域
http://localhost:3000 http://localhost:8080/api/data ✅ 跨域
http://example.com https://example.com/api/data ✅ 跨域
http://localhost:8080 http://localhost:8080/api/data ❌ 同源

综合上面两点,将之前的hello函数改成这个即可。

java 复制代码
    @CrossOrigin(origins = "*")
    @GetMapping("/hello")
    public Map<String, String> hello() {
        Map<String, String> response = new HashMap<>();
        response.put("message", "Hello from Spring Boot!");
        return response;
    }

2.2 AngularJS

前几天和前端的哥们配合,看了一下他们的操作,全是npm。好吧,我也这样玩。npm就是node.js的工具。要先安装一下。

至于代码,看了一下,核心就是index.html,app/main.js,package.json

package.json是用在npm环境中的,npm(Node Package Manager)是javascript的包管理工具。配置了package.json,npm就可以自动下载需要依赖的库。我这边的如下:

python 复制代码
ubuntu@VM-8-10-ubuntu:~/web3$ cat package.json
{
  "name": "angularjs-frontend",
  "version": "1.0.0",
  "description": "AngularJS frontend example",
  "main": "index.html",
  "scripts": {
    "start": "lite-server"
  },
  "dependencies": {
    "angular": "^1.8.2"
  },
  "devDependencies": {
    "lite-server": "^2.6.1"
  }
}

index.html如下

html 复制代码
<!DOCTYPE html>
<html ng-app="helloApp">
<head>
  <meta charset="UTF-8">
  <title>AngularJS Frontend</title>
  <script src="node_modules/angular/angular.min.js"></script>
  <script src="app/main.js"></script>
</head>
<body ng-controller="HelloController">
  <h1>{{ message }}</h1>
</body>
</html>

app/main.js如下

html 复制代码
var app = angular.module('helloApp', []);
app.controller('HelloController', function($scope, $http) {
  $http.get("http://XXXXX:8081/hello")
    .then(function(resp) {
      $scope.message = resp.data;
    });
});

之后就是两个命令

bash 复制代码
npm install 
npm start

npm install会下载依赖,同时会塞很多东西到node_modules。

之后就是npm start。

bash 复制代码
ubuntu@VM-8-10-ubuntu:~/web3$ npm start

> angularjs-frontend@1.0.0 start
> lite-server

Did not detect a `bs-config.json` or `bs-config.js` override file. Using lite-server defaults...
** browser-sync config **
{
  injectChanges: false,
  files: [ './**/*.{html,htm,css,js}' ],
  watchOptions: { ignored: 'node_modules' },
  server: { baseDir: './', middleware: [ [Function], [Function] ] }
}
[Browsersync] Access URLs:
 ----------------------------------
       Local: http://localhost:3000
    External: http://10.0.8.10:3000
 ----------------------------------
          UI: http://localhost:3001
 UI External: http://localhost:3001
 ----------------------------------
[Browsersync] Serving files from: ./
[Browsersync] Watching files...
25.05.31 13:07:02 304 GET /index.html
25.05.31 13:07:02 304 GET /node_modules/angular/angular.min.js
25.05.31 13:07:02 304 GET /app/main.js
[Browsersync] Couldn't open browser (if you are using BrowserSync in a headless environment, you might want to set the open option to false)

最后就很简单了。直接访问3000端口:http://XXX.XXX.99.181:3000/

3 高级特性

后面再玩点高级特性,先TODO。。。

3.1 前端路由

说实话,听到这个词有点诧异,因为我是做过路由器,路由这个词一般用在网络中。前端为什么会用到路由,查了一下,原来是单页应用(Single page web application)。其实本质就是将一些页面直接缓存到浏览器,需要的时候有前端控制调用,往后台只获取API接口数据。。。这样大大加快了速度。。。好吧,现在的浏览器确实玩的花。

场景 传统多页应用 单页应用(SPA)
页面切换 每次请求服务器获取完整 HTML 从缓存读取模板,仅 API 请求数据
模板存储 每次从服务器加载 首次加载时打包进 JS
用户体验 刷新页面,速度较慢 无刷新,快速切换

关键实现。

1 浏览器地址换成http://example.com/#!/home

html 复制代码
<a href="#!/home">主页</a> <!-- 使用了 hashbang 模式 -->

这个表示跳转不由浏览器控制,由Angular控制。

2 路由函数?

就是处理发过来的#!/home,转成页面加载。第一次还是会发送异步请求去加载,后续就直接使用浏览器中的缓存。

html 复制代码
app.config(function($routeProvider) {
  $routeProvider
    .when('/home', {
      templateUrl: 'views/home.html',
      controller: 'HomeCtrl'
    })
    ...
});

3.2 指令(Directives)

自定义组件

javascript 复制代码
app.directive('fileUploader', function() {
  return {
    restrict: 'E',
    scope: {
      onUpload: '&'
    },
    template: `
      <input type="file" />
      <button ng-click="upload()">Upload</button>
    `,
    link: function(scope, element) {
      var fileInput = element.find('input')[0];

      scope.upload = function() {
        var file = fileInput.files[0];
        if (file) {
          scope.onUpload({ file: file });
        }
      };
    }
  };
});

后面可以直接在html中使用。

html 复制代码
<file-uploader on-upload="uploadFile(file)"></file-uploader>

支持以下扩展指令:

类型 示例 说明
元素指令 <my-widget></my-widget> 创建自定义 HTML 元素
属性指令 <div my-attr></div> 扩展元素行为
类名指令 <div class="my-dir"></div> 通过 CSS 类触发
注释指令 <!-- directive: my-dir --> 较少使用

常见内置指令:

指令 用途
ng-model 双向数据绑定
ng-repeat 循环渲染
ng-show/ng-hide 显示/隐藏元素
ng-class 动态 CSS 类
ng-click 点击事件处理
ng-if 条件渲染
ng-switch 多条件切换
ng-include 动态加载模板

3.3 双向数据绑定

index.html

html 复制代码
<!DOCTYPE html>
<html ng-app="demoApp">
<head>
    <meta charset="UTF-8">
    <title>AngularJS双向绑定示例</title>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script>
    <style>
        body { font-family: Arial; padding: 20px; }
        .demo-box { 
            border: 1px solid #ddd; 
            padding: 20px; 
            margin: 10px 0;
            border-radius: 5px;
        }
        input, select { 
            padding: 8px; 
            margin: 5px 0; 
            width: 100%;
            box-sizing: border-box;
        }
        .output { 
            background: #f0f8ff; 
            padding: 10px; 
            margin-top: 10px;
        }
    </style>
</head>
<body>
    <h1>AngularJS 双向数据绑定演示</h1>
    
    <div ng-controller="DemoController">
        <!-- 示例1: 文本输入绑定 -->
        <div class="demo-box">
            <h3>1. 文本同步</h3>
            <input type="text" ng-model="userInput" placeholder="输入任意内容">
            <div class="output">
                <p>实时显示: <strong>{{ userInput || "(暂无输入)" }}</strong></p>
                <p>字符数: {{ userInput.length }}</p>
            </div>
        </div>
        
        <!-- 示例2: 复选框绑定 -->
        <div class="demo-box">
            <h3>2. 复选框状态</h3>
            <label>
                <input type="checkbox" ng-model="isAgreed"> 我同意条款
            </label>
            <div class="output">
                当前状态: <span style="color: {{ isAgreed ? 'green' : 'red' }};">
                    {{ isAgreed ? "已同意" : "未同意" }}
                </span>
            </div>
        </div>
        
        <!-- 示例3: 下拉选择绑定 -->
        <div class="demo-box">
            <h3>3. 下拉选择</h3>
            <select ng-model="selectedFruit" 
                    ng-options="fruit for fruit in fruits">
                <option value="">-- 选择水果 --</option>
            </select>
            <div class="output" ng-if="selectedFruit">
                您选择的是: <strong>{{ selectedFruit }}</strong>
                <img ng-src="images/{{ selectedFruit }}.png" 
                     alt="{{ selectedFruit }}" 
                     style="height: 50px; display: block; margin-top: 10px;">
            </div>
        </div>
    </div>

    <script>
        angular.module('demoApp', [])
        .controller('DemoController', function($scope) {
            // 初始化模型数据
            $scope.userInput = "";
            $scope.isAgreed = false;
            $scope.fruits = ['苹果', '香蕉', '橙子', '葡萄'];
            $scope.selectedFruit = "";
        });
    </script>
</body>
</html>

用的话还是很简单,就是一个ng-model。

作用就是用户在界面上改了,对应的程序变量也自动改了,不用手动去写赋值函数。而程序中的变量改了,自动在界面显示上改变。

3.4 依赖注入(DI)

javascript 复制代码
// 自定义服务
app.service('MyLogger', function() {
  this.log = function(msg) {
    console.log("MyLogger:", msg);
  };
});

// 控制器中使用
app.controller('MyCtrl', function($scope, MyLogger, $http) {
  MyLogger.log("控制器启动");

  $http.get('/api/data').then(function(response) {
    $scope.data = response.data;
  });
});

好像就是预制很多类或者说服务?直接逮来用就完事?

AngularJS 内部有一个 依赖容器(Injector),它做了两件事:

  1. 提前注册好了很多服务 (比如 $http$scope$timeout 等);

  2. 当你写控制器、服务、指令等组件时,只要声明需要什么,AngularJS 就自动传入这些依赖。

相关推荐
Mintopia2 分钟前
3D Quickhull 算法:用可见性与冲突图搭建空间凸壳
前端·javascript·计算机图形学
Mintopia2 分钟前
Three.js 三维数据交互与高并发优化:从点云到地图的底层修炼
前端·javascript·three.js
陌小路8 分钟前
5天 Vibe Coding 出一个在线音乐分享空间应用是什么体验
前端·aigc·vibecoding
成长ing1213815 分钟前
cocos creator 3.x shader 流光
前端·cocos creator
Alo36524 分钟前
antd 组件部分API使用方法
前端
BillKu27 分钟前
Vue3数组去重方法总结
前端·javascript·vue.js
GDAL29 分钟前
Object.freeze() 深度解析:不可变性的实现与实战指南
javascript·freeze
江城开朗的豌豆1 小时前
Vue+JSX真香现场:告别模板语法,解锁新姿势!
前端·javascript·vue.js
这里有鱼汤1 小时前
首个支持A股的AI多智能体金融系统,来了
前端·python
袁煦丞1 小时前
5分钟搭建高颜值后台!SoybeanAdmin:cpolar内网穿透实验室第648个成功挑战
前端·程序员·远程工作