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

> [email protected] 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 就自动传入这些依赖。

相关推荐
Hello-Mr.Wang5 分钟前
Vue3使用vue-web-screen-shot实现截图功能
前端·javascript·vue.js
机巧咸鱼不会受伤36 分钟前
在 React Umi 项目中实现基于 SSE 的流式聊天功能
前端·react.js
白筱汐41 分钟前
element plus 根据嵌套数据合并表格
前端·javascript
Mr.Liu61 小时前
小程序32-简易双向数据绑定
前端·微信小程序·小程序
BillKu1 小时前
CSS强制div单行显示不换行
前端·css
大明881 小时前
Vue 中导致 detached 元素产生的常见行为
前端·vue.js
哎呦你好1 小时前
CSS 渐变完全指南:从基础概念到实战案例(线性渐变/径向渐变/重复渐变)
前端·css
hachi03131 小时前
el-table-column如何获取行数据的值
javascript·vue.js·elementui
工呈士1 小时前
React进阶:状态管理选择题
前端·react.js·面试