Create your Gitee Account
Explore and code with more than 6 million developers,Free private repositories !:)
Sign up
This repository doesn't specify license. Without author's permission, this code is only for learning and cannot be used for other purposes.
Clone or download
Cancel
Notice: Creating folder will generate an empty file .keep, because not support in Git
Loading...
README.md

Super MEAN 全栈教程

薛鹏翔 2016-4-9

本教程[^ 参考Youtube教程(说是抄袭也不为过) https://goo.gl/O3FqyT]介绍采用MEAN开发,以Todolist应用为例,涉及MongoDB Express AngularJS Node Webpack SASS Babel/ES6 Bootstrap AngularUI-Router

Step1 基本环境nodeJS


网址:https://nodejs.org/en/  
链接:https://nodejs.org/en/download/

安装完成,在命令行运行 node -v v5.5.1
显示具体版本号,即表示安装正确。
node安装时应将包管理工具npm也一并安装,若执行命令 npm -v 3.3.12
显示具体版本号, 即包管理工具npm也安装正确。

Step2 建立工程目录


新建工程目录todo-app mkdir todo-app cd todo-app

Step3 建立package.json文件


运行如下命令 npm init -y
自动生成package.json在工程目录中 Wrote to /Users/xuepx/MEAN/todo-app/package.json:

{
  "name": "todo-app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

Step4 安装Express


npm install --save express

install 安装(可用i代替)
--save 保存安装信息到package.json中(可用-S代替)

安装结束后package.json内容会发生变化,出现了依赖库

{
  "name": "todo-app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.13.4"
  }
}

Step5 建立Server


工程目录里新建server.js

var express = require('express');
var app = express();

var PORT = process.env.PORT || 3000;

app.all('/*', function(request, response){
    response.send('hello Express!');
})

app.listen(PORT, function(){
    console.log("Server running at " + PORT);
})

运行 node server.js
启动服务,浏览器打开localhost:3000即可访问.
可以将response内容换成HTML。

var express = require('express');
var app = express();

var PORT = process.env.PORT || 3000;

app.all('/*', function(request, response){
    response.send('\
        <html>\
            <head>\
                <title>测试Express</title>\
            </head>\
            <body>\
                <h1>这是个例子</h1>\
            </body>\
        </html>\
    ');
})

app.listen(PORT, function(){
    console.log("Server running at " + PORT);
})

重启服务,Ctrl+C关闭,重新运行node server, 打开浏览器即访问到新的页面.

Step6 webpack MODULE BUNDLER


npm install -g webpack webpack-dev-server

-g 全局安装, 即安装到node环境下, 不是在当前工程中.

npm install --save-dev webpack webpack-dev-server

--save-dev 安装到开发依赖环境, 即当前工程部署环境不需要, 但开发环境需要(可用-D代替).

此时package.json内容会增加devDependencies段落

{
  "name": "todo-app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.13.4"
  },
  "devDependencies": {
    "webpack": "^1.12.14",
    "webpack-dev-server": "^1.14.1"
  }
}

Step7 babel-loader babel-preset-es2015


npm install --save-dev babel-loader babel-preset-es2015 安装完后package.json文件中开发依赖包会增加该内容

{
  "name": "todo-app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.13.4"
  },
  "devDependencies": {
    "babel-loader": "^6.2.4",
    "babel-preset-es2015": "^6.6.0",
    "webpack": "^1.12.14",
    "webpack-dev-server": "^1.14.1"
  }
}

Step8 配置webpack

新建webpack.config.js文件

var webpack = require('webpack');
var path = require('path');

module.exports = {
   devtool: 'inline-source-map',
   entry: [
       'webpack-dev-server/client?http://127.0.0.1:8080/',
       'webpack/hot/only-dev-server',
       './src'
   ],
   output: {
       path: path.join(__dirname, 'public'),
       filename: 'bundle.js'
   },
   resolve: {
       modulesDirectories: ['node_modules', 'src'],
       extension: ['', '.js']
   },
   module:[
       {
           test: /\.js$/,
           exclude: /node_modules/,
           loader: 'babel',
           query: {
               presets: ['es2015']
           }
       },
       {
           test: /\.html$/,
           loader: 'raw'
       }
   ],
   plugins: [
       new webpack.HotModuleReplacementPlugin(),
       new webpack.NoErrorsPlugin(),
   ],
   devServer: {
       hot: true,
       proxy: {
           '*': 'http://localhost:3000'
       }
   }
}

新建目录src, public, 并在目录src下新建index.js

var message = 'Hello from the entry file';

console.log(message);

修改server.js增加bundle.js

var express = require('express');
var app = express();

var PORT = process.env.PORT || 3000;

app.all('/*', function(request, response){
    response.send('\
        <html>\
            <head>\
                <title>测试Express</title>\
                <script src="bundle.js"></script>\
            </head>\
            <body>\
                <h1>这是个例子</h1>\
            </body>\
        </html>\
    ');
})

app.listen(PORT, function(){
    console.log("Server running at " + PORT);
})

运行命令 node server & webpack-dev-server
即可打开浏览器访问locahost:8080

当然打开localhost:3000也可访问, 与8080端口的区别时如果代码发生变化, 不需要手动重启服务, webpack-dev-server会帮我们重启该服务, 如我们现在访问8080, 打开浏览器开发者工具, 控制台可以看到我们在index.js中写的log(Hello from the entry file), 如果我们修改这个log, 那么只需要刷新浏览器即可,不必重启node

Step9 webpack快速启动dev-server


修改package.json的scripts段如下

{
  "name": "todo-app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "NODE_PATH=$NODE_PATH:./src node server & ",
    "dev": "npm start webpack-dev-server --progress --colors"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.13.4"
  },
  "devDependencies": {
    "babel-loader": "^6.2.4",
    "babel-preset-es2015": "^6.6.0",
    "webpack": "^1.12.14",
    "webpack-dev-server": "^1.14.1"
  }
}

运行命令 killall -9 node

如果之前没有启动服务则无需此步
windows下需要打开任务管理器关闭node进程. npm run dev
之后运行dev-server只需执行上述命令即可.

Step10 Angular Angular-ui-router


执行命令 npm install --save angular angular-ui-router 安装结束, package.json会增加相应的依赖项. 执行命令 npm install -D raw-loader 安装raw loader作为开发环境, 安装结束package.json会增加dependencies内容

{
  "name": "todo-app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "NODE_PATH=$NODE_PATH:./src node server & ",
    "dev": "npm start webpack-dev-server --progress --colors"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "angular": "^1.5.3",
    "angular-ui-router": "^0.2.18",
    "express": "^4.13.4"
  },
  "devDependencies": {
    "babel-loader": "^6.2.4",
    "babel-preset-es2015": "^6.6.0",
    "raw-loader": "^0.5.1",
    "webpack": "^1.12.14",
    "webpack-dev-server": "^1.14.1"
  }
}

新建src/config.js

import angular from 'angular';
import uiRouter from 'angular-ui-router';

const app = angular.module('app', [uiRouter]);

app.config(($stateProvider, $urlRouterProvider, $locationProvider) => {
    $urlRouterProvider.other('/');

    $stateProvider
        .state('todos', {
            url: '/',
            template: require('todos/todos.html')
        })
        .state('about', {
            url: 'about',
            template: require('about/about.html')
        })

    $locationProvider.html5Mode(true);
});

export default app;

修改src/index.js

var express = require('express');
var app = express();

var PORT = process.env.PORT || 3000;

app.all('/*', function(request, response){
    response.send('\
        <html>\
            <head>\
                <title>测试Angular</title>\
                <base href="/">\
            </head>\
            <body>\
                <div ui-view></div> \
                <script src="bundle.js"></script>\
            </body>\
        </html>\
    ');
})

app.listen(PORT, function(){
    console.log("Server running at " + PORT);
})

新建目录src/todos和src/about, 并建立文件src/todos/todos.html如下

<div>
    <a ui-sref="about">About</a>
    <h2> ToDo 应用</h2>
</div>

建立src/about/about.html如下

<div>
    <a ui-sref="todos">ToDo</a>
    <h2> 关于 Todo 应用</h2>

    <p>这是个学习应用</p>
</div>

修改webpack.config.js如下

var webpack = require('webpack');
var path = require('path');

module.exports = {
   devtool: 'inline-source-map',
   entry: [
       'webpack-dev-server/client?http://127.0.0.1:8080/',
       'webpack/hot/only-dev-server',
       './src'
   ],
   output: {
       path: path.join(__dirname, 'public'),
       filename: 'bundle.js'
   },
   resolve: {
       modulesDirectories: ['node_modules', 'src'],
       extension: ['', '.js']
   },
   module:{
       loaders:[
           {
               test: /\.js$/,
               exclude: /node_modules/,
               loader: 'babel',
               query: {
                   presets: ['es2015']
               }
           },
           {
               test: /\.html$/,
               loader: 'raw'
           }
       ]
   },
   plugins: [
       new webpack.HotModuleReplacementPlugin(),
       new webpack.NoErrorsPlugin(),
   ],
   devServer: {
       hot: true,
       proxy: {
           '*': 'http://localhost:3000'
       }
   }
}

执行命令 npm run dev
打开浏览器访问localhost:8080可以看到页面,并点击about切换到Todo页面, 点击Todo切换到about.

Step11 css-loader style-loader sass-loader node-sass autoprefixer-loader


执行命令 npm install --save-dev css-loader style-loader sass-loader node-sass autoprefixer-loader
安装开发环境. 安装完后package.json会增加开发依赖

{
  "name": "todo-app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "NODE_PATH=$NODE_PATH:./src/ node server & ",
    "dev": "npm start webpack-dev-server --progress --colors"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "angular": "^1.5.3",
    "angular-ui-router": "^0.2.18",
    "express": "^4.13.4"
  },
  "devDependencies": {
    "autoprefixer-loader": "^3.2.0",
    "babel-loader": "^6.2.4",
    "babel-preset-es2015": "^6.6.0",
    "css-loader": "^0.23.1",
    "node-sass": "^3.4.2",
    "raw-loader": "^0.5.1",
    "sass-loader": "^3.2.0",
    "style-loader": "^0.13.1",
    "webpack": "^1.12.14",
    "webpack-dev-server": "^1.14.1"
  }
}

在工程中配置让css, sass等文件导入工程, 修改webpack.config.js的resolve(增加扩展名为scss)和module的loaders如下

var webpack = require('webpack');
var path = require('path');

module.exports = {
   devtool: 'inline-source-map',
   entry: [
       'webpack-dev-server/client?http://127.0.0.1:8080/',
       'webpack/hot/only-dev-server',
       './src'
   ],
   output: {
       path: path.join(__dirname, 'public'),
       filename: 'bundle.js'
   },
   resolve: {
       modulesDirectories: ['node_modules', 'src'],
       extension: ['', '.js', '.scss']
   },
   module:{
       loaders:[
           {
               test: /\.js$/,
               exclude: /node_modules/,
               loader: 'babel',
               query: {
                   presets: ['es2015']
               }
           },
           {
               test: /\.html$/,
               loader: 'raw'
           },
           {
               test: /\.scss$/,
               loaders: [
                   'style',
                   'css',
                   'autoprefixer?browsers=last 3 versions',
                   'sass?outputStyle=expanded'
               ]
           }
       ]
   },
   plugins: [
       new webpack.HotModuleReplacementPlugin(),
       new webpack.NoErrorsPlugin(),
   ],
   devServer: {
       hot: true,
       proxy: {
           '*': 'http://localhost:3000'
       }
   }
}

Step12 为HTML增加style


修改src/about/about.html

<div>
    <a ui-sref="about" class="nav-link">About</a>
    <h2> ToDo 应用</h2>
</div>

和src/todos/todos.html

<div>
    <a ui-sref="todos" class="nav-link">Todo</a>
    <h2> 关于 Todo 应用</h2>

    <p>这是个学习应用</p>
</div>

新建文件夹src/css, 并新建文件src/css/master.scss内容如下

.nav-link {
    float: right;
    margin-top: 20px;
}

将sass引入工程, 修改src/index.js

import angular from 'angular';
import appModule from 'config';
import 'css/master.scss';

angular.bootstrap(document, [appModule.name]);

刷新页面, 添加的样式即起作用, About和todos连接显示在右侧。

Step13 bootstrap-sass juqery bootstrap-loader url-loader file-loader resolve-url-loader imports-loader


执行命令 npm install --save bootstrap-sass jquery 为工程引入bootstrap和query. 执行命令 npm install --save-dev bootstrap-loader url-loader file-loader resolve-url-loader imports-loader 为开发环境进入必要包, 两个命令执行完后package.json中依赖和开发依赖会添加相应内容

{
  "name": "todo-app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "NODE_PATH=$NODE_PATH:./src/ node server & ",
    "dev": "npm start webpack-dev-server --progress --colors"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "angular": "^1.5.3",
    "angular-ui-router": "^0.2.18",
    "bootstrap-sass": "^3.3.6",
    "express": "^4.13.4",
    "jquery": "^2.2.3"
  },
  "devDependencies": {
    "autoprefixer-loader": "^3.2.0",
    "babel-loader": "^6.2.4",
    "babel-preset-es2015": "^6.6.0",
    "bootstrap-loader": "^1.0.10",
    "css-loader": "^0.23.1",
    "file-loader": "^0.8.5",
    "imports-loader": "^0.6.5",
    "node-sass": "^3.4.2",
    "raw-loader": "^0.5.1",
    "resolve-url-loader": "^1.4.3",
    "sass-loader": "^3.2.0",
    "style-loader": "^0.13.1",
    "url-loader": "^0.5.7",
    "webpack": "^1.12.14",
    "webpack-dev-server": "^1.14.1"
  }
}

配置bootstrap和jquery引入工程, 修改webpack.config.js增加bootstrap的entry和各类文件的module loader

var webpack = require('webpack');
var path = require('path');

module.exports = {
   devtool: 'inline-source-map',
   entry: [
       'webpack-dev-server/client?http://127.0.0.1:8080/',
       'webpack/hot/only-dev-server',
       'bootstrap-loader',
       './src'
   ],
   output: {
       path: path.join(__dirname, 'public'),
       filename: 'bundle.js'
   },
   resolve: {
       modulesDirectories: ['node_modules', 'src'],
       extension: ['', '.js', '.scss']
   },
   module:{
       loaders:[
           {
               test: /\.js$/,
               exclude: /node_modules/,
               loader: 'babel',
               query: {
                   presets: ['es2015']
               }
           },
           {
               test: /\.html$/,
               loader: 'raw'
           },
           {
               test: /\.scss$/,
               loaders: [
                   'style',
                   'css',
                   'autoprefixer?browsers=last 3 versions',
                   'sass?outputStyle=expanded'
               ]
           },
           {
               test: /\.(woff2?|ttf|eot|svg)$/,
               loader: 'url?limit=10000'
           },
           {
               test: /bootstrap-sass\/assets\/javascripts\//,
               loader: 'imports'
           }
       ]
   },
   plugins: [
       new webpack.HotModuleReplacementPlugin(),
       new webpack.NoErrorsPlugin(),
       new webpack.ProvidePlugin({
           $: "jquery",
           jQuery: "jquery",
           "window.jQuery": "jquery"
       })
   ],
   devServer: {
       hot: true,
       proxy: {
           '*': 'http://localhost:3000'
       }
   }
}

Step14 Form


修改src/config.js增加todos的controller如下

import angular from 'angular';
import uiRouter from 'angular-ui-router';
import todosController from 'todos/todos';

const app = angular.module('app', [uiRouter]);

app.config(($stateProvider, $urlRouterProvider, $locationProvider) => {
    $urlRouterProvider.otherwise('/');

    $stateProvider
        .state('todos', {
            url: '/',
            template: require('todos/todos.html'),
            controller: todosController
        })
        .state('about', {
            url: '/about',
            template: require('about/about.html')
        })

    $locationProvider.html5Mode(true);
});

export default app;

实现controller, 新建文件src/todos/todos.js

export default function() {

}

在src/todos/todos.html增加form

<div class="container">
    <a ui-sref="about" class="nav-link">About</a>
    <h2> ToDo 应用</h2>

    <form class="" action="index.html" method="post">
        <input class="form-control todos__create-input" placeholder="你要做什么?">
        <button type="button" class="btn btn-success todos__create-button">创建任务</button>
    </form>
</div>

为todos增加css, 新建文件src/css/todos.scss内容如下:

.todos{
    &__create-input {
        margin: 0 auto 5px;
        width: 300px;
    }
    &__create-button {
        display: block;
        margin: 0 auto 20px;
    }
}
/*
.todos{
    &__create-input {

    }
}
等价于
.todos__create-input{

}
*/

在src/css/master.scss引入新添加的样式文件

@import 'todos.scss';
.nav-link {
    float: right;
    margin-top: 20px;
}

刷新页面即可看到bootstrap样式的页面.

Step15 Table


修改src/todos/todos.html增加table

<div class="container">
    <a ui-sref="about" class="nav-link">About</a>
    <h2> ToDo 应用</h2>

    <form class="" action="index.html" method="post">
        <input class="form-control todos__create-input" placeholder="你要做什么?">
        <button type="button" class="btn btn-success todos__create-button">创建任务</button>
    </form>

    <table class='table table-striped'>
        <tr>
            <th>
                状态
            </th>
            <th>
                任务
            </th>
            <th>
                操作
            </th>
        </tr>
        <tr>
            <td>
                未完成
            </td>
            <td>
                学习Mongodb
            </td>
            <td>
                编辑, 删除
            </td>
        </tr>
        <tr>
            <td>
                未完成
            </td>
            <td>
                学习Express
            </td>
            <td>
                编辑, 删除
            </td>
        </tr>
        <tr>
            <td>
                未完成
            </td>
            <td>
                学习Angular
            </td>
            <td>
                编辑, 删除
            </td>
        </tr>
        <tr>
            <td>
                未完成
            </td>
            <td>
                学习Node
            </td>
            <td>
                编辑, 删除
            </td>
        </tr>
    </table>
</div>

刷新页面可以看到表格. 下面通过Controller实现刚才的表格, 修改src/todos/todos.js内容如下:

export default function($scope) {
    $scope.todos = [
        {
            task: "学习Mongodb",
            isCompleted: false
        },
        {
            task: "学习Express",
            isCompleted: false
        },
        {
            task: "学习Angular",
            isCompleted: false
        },
        {
            task: "学习Node",
            isCompleted: true
        },
    ];
}

这里是建立一个json对象todos, 并传递到todos.html中(之前配置了controller), 下面修改src/todos/todos.html

<div class="container">
    <a ui-sref="about" class="nav-link">About</a>
    <h2> ToDo 应用</h2>

    <form>
        <input class="form-control todos__create-input" placeholder="你要做什么?">
        <button type="button" class="btn btn-success todos__create-button">创建任务</button>
    </form>

    <table class='table table-striped'>
        <tr>
            <th>
                状态
            </th>
            <th>
                任务
            </th>
            <th>
                操作
            </th>
        </tr>
        <tr ng-repeat="todo in todos">
            <td>
                <input type="checkbox" class="todo__checkbox" ng-checked="todo.isCompleted" />
            </td>
            <td>
                <span class="todos__task">{{todo.task}}</span>
            </td>
            <td>
                <button class="btn btn-info">编辑</button>
                <button class="btn btn-danger">删除</button>
            </td>
        </tr>
    </table>
</div>

Step16 check事件绑定


为checkbox增加事件绑定, 修改src/todos/todos.html部分内容绑定click事件如下

<tr ng-repeat="todo in todos">
    <td>
        <input type="checkbox" class="todo__checkbox"
            ng-checked="todo.isCompleted"
            ng-click="onCompletedClick(todo)"/>
    </td>
    <td>
        <span class="todos__task">{{todo.task}}</span>
    </td>
    <td>
        <button class="btn btn-info">编辑</button>
        <button class="btn btn-danger">删除</button>
    </td>
</tr>

在src/todos/todos.js中实现函数onCompletedClick

export default function($scope) {
    $scope.todos = [{
        task: "学习Mongodb",
        isCompleted: false
    }, {
        task: "学习Express",
        isCompleted: false
    }, {
        task: "学习Angular",
        isCompleted: false
    }, {
        task: "学习Node",
        isCompleted: true
    }, ];

    $scope.onCompletedClick = todo => {
        todo.isCompleted = !todo.isCompleted;
    }
}

下面为已完成和未完成的任务添加不同的样式, 修改src/todos/todos.html的任务列

<td>
    <span class="todos__task" ng-class="{'todos__task--completed':todo.isCompleted}">
        {{todo.task}}
    </span>
</td>

在src/css/todos.scss中增加完成时的样式

.todos{
    &__create-input {
        margin: 0 auto 5px;
        width: 300px;
    }
    &__create-button {
        display: block;
        margin: 0 auto 20px;
    }
    &__task{
        &--completed {
            text-decoration: line-through;
        }
    }
}

刷新页面, 即可看到已完成项目出现删除线, 并且点击状态的checkbox删除线也随着消失或出现.

Step17 Change事件绑定


我们希望用户在任务框输入时任务列表同步出现添加, 点击创建任务按钮(或回车)后添加该任务, 首先修改src/todos/todos.html为输入框增加model

<form>
    <input class="form-control todos__create-input" placeholder="你要做什么?" ng-model="createTaskInput">
    <button type="button" class="btn btn-success todos__create-button">创建任务</button>
</form>

修改Controller监视input的change

export default function($scope) {
    let params = {
        createHasInput: false,  // 输入内容是否已经创建任务
    }
    $scope.todos = [{
        task: "学习Mongodb",
        isCompleted: false
    }, {
        task: "学习Express",
        isCompleted: false
    }, {
        task: "学习Angular",
        isCompleted: false
    }, {
        task: "学习Node",
        isCompleted: true
    }, ];

    $scope.onCompletedClick = todo => {
        todo.isCompleted = !todo.isCompleted;
    }

    $scope.$watch('createTaskInput', val => {
        //输入框内容不为空, 且未创建任务
        if (val && !params.createHasInput){
            $scope.todos.push({task: val, isCompleted:false});
            params.createHasInput = true;  // 已创建
        }
        // 输入框内容不为空, 且已创建任务
        else if (val && params.createHasInput){
            $scope.todos[$scope.todos.length - 1].task = val;
        }
        // 输入内容为空, 且未创建(即删除输入框内容)
        else if (!val && params.createHasInput){
            $scope.todos.pop();
            params.createHasInput = false;
        }
    });
}

Step18 Submit


为form添加submit, 修改src/todos/todos.html

<form ng-submit="createTask()">
    <input class="form-control todos__create-input" placeholder="你要做什么?" ng-model="createTaskInput">
    <button type="submit" class="btn btn-success todos__create-button">创建任务</button>
</form>

在controller中实现createTask, 修改src/todos/todos.js

export default function($scope) {
    let params = {
        createHasInput: false,  // 输入内容是否已经创建任务
    }
    $scope.todos = [{
        task: "学习Mongodb",
        isCompleted: false
    }, {
        task: "学习Express",
        isCompleted: false
    }, {
        task: "学习Angular",
        isCompleted: false
    }, {
        task: "学习Node",
        isCompleted: true
    }, ];

    $scope.onCompletedClick = todo => {
        todo.isCompleted = !todo.isCompleted;
    }

    $scope.createTask = () => {
        params.createHasInput = false;  // 置状态为未创建(避免被判断为用户删除输入内容)
        $scope.createTaskInput = "";
    }

    $scope.$watch('createTaskInput', val => {
        //输入框内容不为空, 且未创建任务
        if (val && !params.createHasInput){
            $scope.todos.push({task: val, isCompleted:false});
            params.createHasInput = true;  // 已创建
        }
        // 输入框内容不为空, 且已创建任务
        else if (val && params.createHasInput){
            $scope.todos[$scope.todos.length - 1].task = val;
        }
        // 输入内容为空, 且未创建(即删除输入框内容)
        else if (!val && params.createHasInput){
            $scope.todos.pop();
            params.createHasInput = false;
        }
    });
}

Step19 任务编辑


修改src/todos/todos.html为修改按钮增加响应绑定。

<td>
    <button class="btn btn-info" ng-click="onEditBtnClick(todo);">编辑</button>
    <button class="btn btn-danger">删除</button>
</td>

修改src/todos/todos.js增加具体实现, 为每个任务添加isEditing属性, 点击编辑时修改该属性, HTML端依据该属性判断显示输入框或span.

$scope.todos = [{
    task: "学习Mongodb",
    isCompleted: false,
    isEditing: false,
}, {
    task: "学习Express",
    isCompleted: false,
    isEditing: false,
}, {
    task: "学习Angular",
    isCompleted: false,
    isEditing: false,
}, {
    task: "学习Node",
    isCompleted: true,
    isEditing: false,
}, ];

$scope.onEditBtnClick = todo => {
    todo.isEditing = true;
}

修改src/todos/todos.html

<tr ng-repeat="todo in todos">
    <td>
        <input type="checkbox" class="todo__checkbox" ng-checked="todo.isCompleted" ng-click="onCompletedClick(todo)" />
    </td>   
    <td>
        <span ng-if="!todo.isEditing" class="todos__task" ng-class="{'todos__task--completed':todo.isCompleted}">
            {{todo.task}}
        </span>
        <form>
            <input ng-if="todo.isEditing" class="form-control todos__update-input" ng-value="todo.task" />
        </form>
    </td>
    <td>
        <button class="btn btn-info" ng-click="onEditBtnClick(todo)">编辑</button>
        <button class="btn btn-danger">删除</button>
    </td>
</tr>

Comments ( 0 )

Sign in for post a comment

About

Cancel

Releases

No release

Contributors

All

Activities

load more
can not load any more