体验angularjs(入门基础篇)

来源:互联网 发布:js控制元素隐藏 编辑:程序博客网 时间:2024/05/29 05:04
体验angular:


  <body >


    <div id="app" ng-app>
      <input type="text" ng-model="msg"/>
      <p>{{msg}}</p>
    </div>
    <script type="text/javascript" src="./bower_components/angular/angular.js"></script>
  </body>




在angular我们通过定义一个ng-app来启动一个应用程序
流程
  1 页面加载完毕,angular开始对页面进行处理,寻找ng-app指令,找到这个指令以后,就确认app容器元素了,
    此时开始对该容器元素内部的元素进行处理(在angular中,我们通常将ng-app定义在最外层)
  2 此时遍历到input元素,这个元素上有个ng-model指令,此时angular将该元素的内容绑定在作用域中的msg变量中
  3 遍历到p元素,此时p元素进行了一个插值操作,angular会将作用域中的改变量的值插入到p元素内
  4 遍历完成,将angular应用程序启动,我们就可以体验双向绑定的功能


ng-init
  初始化数据的指令
  在angular中,我们可以通过ng-init来初始化我们应用程序中的数据,ng-init指令对应的属性值就是我们要初始化的数据,
    定义方式跟js中定义变量方式一样,多个变量定义时候用;隔开,不能用,
ng-bind
  用来做插值操作的,他的优势,我们看不到页面加载时候的插值符号了
  为元素绑定一个内容值,他的属性值就是要被渲染的内容


  我们页面中的变量往往不止一两个,可能会有很多,所以定义在ng-init不方便管理,可读性差
  ,因此我们就要在js中定义这些变量
  要为应用程序定义这些变量,我们要做的第一件事就是获取这个应用程序
  Angular.module可以获取我们的应用程序
      通常有两个参数
        第一个参数表示应用程序的名称(ng-app指令的值)
        第二个参数表示应用程序的依赖集合(服务),是一个数组,如果没有依赖传递一个空数组


  我们要在js中定义这些变量
    第一步是获取这个应用程序
    第二个是创建一个作用域,在作用域中定义这些变量
  创建作用域用ng-controller指令,创建一个作用域的
  APP对象中有个方法controller,通过这个方法我们可以将页面中的控制器拿到js中
    接收两个参数
      第一个参数表示控制器名称
      第二个参数表示控制器处理函数,通常,我们在这个函数中定义作用域中的变量
        作用域是一个空对象,通过他,我们什么也做不了
        参数是一个空对象,什么都没有,我们在函数中什么也做不了
      那么我们想定义变量就要获取作用域,但是我们目前通过this,arguments都获取不到,
      angular提供了一个技术叫参数注入,我们想用什么功能,直接在参数里传递
      我们想使用作用域,我们可以直接在参数中传递进来,angular作用域相当于一个内置的服务,
      angular内置服务有个特点,都是以$开头的
      作用域服务名称叫$scope
      在作用与中定义变量,我们通$scope.定义


事件
    在vue中使用事件分成两步
      在html中定义这个事件v-on:click="fn"
      在vue中的methods属性中定义这些回调函数
    在angular中每一个事件相当于一个指令,都是以ng开头的


    不同点:
      1 事件定义方式 (区别是回调函数的()) 例如:ng-click="fn()"定义了一个click事件
        在angular默认要加上(),在vue中默认不要加()
      2 回调函数的定义,在angular中事件回调函数定义在作用域中
          vue定义在methods属性中
      3 作用域 在angular中事件回调函数中的作用域就是控制器的作用域
          vue作用域是vue实例化对象
      4 设置作用域中的数据在angular中在事件回调函数内部设置作用域中的数据有两种方式
          第一种是通过this设置
          第二种是通过$scope设置
          vue只有一种方式,只能通过this


    相同点:
      在angular中传入事件对象跟vue一样都是$event


ng-show 是否显隐元素
  True 显示元素
  False 隐藏元素
ng-hide 是否显隐元素
    True 表示隐藏元素
    False 表示显示元素


插值表达式
  angular同vue一样可以对插入的数据执行js的表达式,例如:运算,方法


插值时候使用的表示式不能复用,因此我们可以通过插值过滤器来帮我们实现
  Json 将对象转换成json字符串
  angular中过滤器语法跟vue中过滤器语法是一样的(只是传递参数时候是不同的)


数组过滤器filter
  vue中有个数组过滤器叫filterBy,
  在angular叫filter接收参数有三种方式
    第一种 传递一个字符串,表示过滤的字段
    第二种 传递一个变量,这个变量是在作用域中定义的字段
    第三种 可以传递一个函数,当每一次执行过滤的时候,会执行该函数,函数的返回值就是过滤条件
      三个参数
        第一个参数是遍历数组成员值
        第二个参数是成员索引值
        第三个参数是原数组
      作用域是全局作用域
  在过滤器中传递参数时,参数前面一定要加上:


date 过滤器
  是格式化时间的一个过滤器,这个过滤器很强大,我们看到所有页面的时间,日期格式都可以通过
  这个过滤器表达出来(中文的星期是格式化不出来的)
        参数是格式化的模板,模板中的y表示年,M表示月,d表示日,E表示星期,h表示小时 H表示24进制的,
        m表示分钟,s表示秒


字符串过滤器
  uppercase 将字符串转换成大写
  lowercase 将字符串转换成大写
  limitTo 截取字符串的长度(字符串和数组都可以)
    参数表示截取的长度(slice(0,参数))


数字过滤器
  将一个数组转换成一种可读性的格式,对于整数部分,每三位加一个,对小数做截取
    参数就是小数位数的截取长度(默认保留三位小数)
    截取的最后一位会做四舍五入


数组过滤器
  orderBy排序过滤器
    接收两个参数
      第一个参数表示排序的字段
      第二个参数表示正序还是倒序
        true 倒序
        false 正序
    如果排序是数字,直接比较数字的大小
    如果排序是字符串,根据字符所在编码进行排序


自定义过滤器
  应用程序对象app中有个方法叫filter,这个方法就是用来定义过滤器的
    第一个参数 过滤器名称
    第二个参数是过滤器的处理函数,它与vue的过滤处理函数的区别
      vue 的返回值会直接渲染到页面中
      angular过滤函数的返回值是一个函数,这个函数才是真正处理插值数据的函数
        这个处理插值的函数它的返回值才是渲染到页面中的数据
      第一级函数,在一生中只执行一次
        没有参数,作用域是一个空对象
      第二级函数,在每一次绑定的时候,数据如果变化都会执行一次
        参数
          第一个参数是插值数据
          从第二个参数开始表示过滤器使用时候传递的参数,并一一对应
        返回值就是处理后要渲染到页面中的数据
        作用域是全局作用域(指向window)
        这个函数跟vue的过滤器很像,但有一点不同,vue的这个函数的作用域执行vue实例化对象
  在使用过滤器的时候,我们可以使用多个过滤器,前一个的输出最为后一个的输入


指令:
脏值检测
  是对表单验证
  以前用jquery对页面中表单元素做验证?
    绑定事件(表单元素)focus,blur,keydown,keyup,change,click等等
    在时间回调函数中获取需要验证的表单
    对表单内容做验证处理(正则)
    根据结果显隐提示
    提交表单时候我们还会对数据进行拼接(ajax)
  在angular中做表单验证只需要添加几个指令
  在创建表单时候,angular会根据表单(form,input等等)标签的name属性在作用域中创建一个变量
    input表单的name属性定义在form元素name属性对应的变量内部
    在作用域中第一次是根据form标签寻找name属性并映射变量(第一次不会根据)
    第二次会在form元素中遍历表单元素并映射到表单变量中
    不论是表单form元素,还是input元素对应的变量都有四个属性
      $dirty 是否被修改过
        True 已经被修改过
        False 没有被修改过
      $pristine 是否被修改过
        True 没有被修改过
        False 已经被修改过
      $valid 是否合法
        True 合法
        False 不合法
      $invalid 是否合法
        True 不合法
        False 合法


表单验证方式(指令)
  必填校验
    共同点:
      不论是否输入过,都会对表单进行验证
    不同点:
      1 required h5提供的一个属性,因此有些浏览器会做额外的校验提示
        ng-required 是个指令,不会影响浏览器的校验(浏览器校验捕获不到这个指令)
      2 ng-required 必须传递一个属性值(true),required不用
  最大长度校验和最小长度校验
    共同点:
      1 都是根据属性值做长度的校验
      2 只在输入的时候做校验,不会在未输入($dirty=false)情况下做校验(此时$invalid=true)
    不同点:
      1 maxlength和minlength是h5属性,浏览器会特殊处理(maxlength:当超过最大长度时
      ,不允许我们继续输入)
        ng-maxlength和ng-minlength是指令,不会影响浏览器
  正则验证: ng-pattren
    共同点:
      1 都是根据正则表达式做校验
      2 他们都只在输入的时候做校验,在未输入($dirty=false)时候不会做校验
    不同点
      1 ng-pattern 他的值是标准正则表达式/abc/
        pattern 它的值是一个正则表达式内的内容abc
      2 pattern 使用的时候,一些浏览器会做校验
        ng-pattern 使用时候,浏览器不会做校验


ng-disabled 表单会变成灰色
  true 表示不能操作
  false 表示可以继续 操作
ng-readonly 表单不变色
  true 表示是只读的
  false 表示可以操作的
  ng-disabled和bg-readonly都可以控制表单元素什么时候可以操作,
  什么时候不可以操作,他们只是样式的不同
ng-checked
  表示是否被选中
  true 表示被选中
  false 表示没有被选中
  ng-model 绑定的数据值只能是布尔值,设置value或者true-value是没有用的
ng-change
  在angular为表单绑定change事件跟绑定click事件是一样的,都是通过ng-指令实现的
  ng-change事件使用方式跟ng-click唯一的不同点,是在ng-change中无法访问您$event
  ng-change事件是依赖于ng-model指令来实现的
ng-submit
  给form表单绑定的一个指令事件
  当表单触发提交事件时候,可以通过该指令捕获回调函数,该指令与ng-click指令使用方式
  是一样的,这个指令也能访问到事件对象


Run:应用程序启动起来的时候,会调用该方法,这个方法会在根作用域上执行,这个方法是app对象上的方法
  这个方法作用域是全局作用域,默认参数是空
  我们想在该方法中使用跟作用域就要将跟作用域注入进来
  在run方法中只能访问根作用域($rootScope)不能访问$scope


作用域层级
  angular作用域是基于原型模式实现的
    1 子作用域可以继承父作用域中的变量以及属性(变量值定义在作用域$scope上的变量)
    2 父作用域无法使用子作用域的变量以及属性
    3 子作用域一旦定义与父作用域相同的变量就会覆盖父作用域中的变量,此时子作用域中如何展现
    不会受父作用域中变量值的影响
  在子作用域中访问父作用域可以通过$parent属性访问
  在某个作用域中访问兄弟作用域 $$prevSibling 访问前一个兄弟作用域, $$nextSibling 访问后一个兄弟作用域
    这几种情况是不建议使用的,因为会将作用域耦合在一起


ng-href动态创建a标签的href属性
  与href直接插值相比,具有的优越性就是,可以提高用户体验
    当没有数据时候,作为普通元素展示
    当有数据展示的时候作为a标签展示
    这个指令比较特殊,插值的时候要加上{{}}


ng-src 动态创建img的src属性
  他对于体验的提高是很有价值的
  当没有数据时候,不会创建src属性,当有数据的时候会创建src属性
  这个指令比较特殊,插值的时候要加上{{}}


类绑定
  在angluar中绑定类分三种情况
    第一种传递一个对象
      对象的属性名称就是类的名称
      对象属性值是一个布尔值
        true保留这个类
        false删除这个类
    第二种 传递一个变量
      变量的值就是类的名称
    第三种 传递一个数组
      数组中的每个成员表示一个类的名称
    无论是变量还是数组中的成员,我们可以写字符串,(字符串要有'')
样式的绑定
  绑定样式只有两种方式
    第一种方式 传递一个对象
      对像的属性名称表示样式的数据名称
      对象的属性值表示样式的属性值
    第二种方式 传递一个变量
      这个变量是一个对象
      对象的属性名称表示样式名称
      对象的属性值,表示样式的属性值
  angular与vue不同的是,他不能接收一个数组


ng-show,ng-hide,来显隐一个元素,实现原理是通过类实现
ng-if 来决定元素是否创建
  true 显示这个元素
  false 隐藏这个元素
  angular 根据页面中注释位置来决定元素的创建位置


ng-switch 可以控制多个页面的切换
  on 绑定一个控制变量
  ng-switch-default 设置默认页面
  ng-switch-when 当满足when条件适合,渲染该页面
  注意:不论比设置多少ng-switch-when,或者ng-switch-default,那么只能同时显示一个页面


循环渲染模板指令
  ng-repeat 参数使用方式与vue中v-for是一样的
    ng-repeat="item in list"
      $index 循环的次数,从0开始计数的
      $first 是否是第一次,布尔值
      $last 是否是最后一次 布尔值
      $middle 是否是中间一次(除了首尾) 布尔值
      $event 偶数次 布尔值
      $odd 奇数次 布尔值


ng-include
  动态加载模板的
  原理是通过异步请求实现,所以我们要创建一个服务器
  他的值是文件的路径,是个字符串或者变量


自定义指令
  是angular很重要的一个部分
  指令?
  指令在angular表示对dom元素功能的拓展
    例如,div没有显隐功能,我们可以对他添加ng-show可以让其具有显隐功能
      li元素没有循环动态创建的功能,我们可以添加一个ng-repeat指令,让这些li元素 可以动态的创建
    我们学习内置的指令就是学习angular对dom元素拓展新功能,我们学习自定义指令就是要学会自己为dom
    元素拓展自己需要的功能
      在angular中创建自定义指令需要directive方法,这个方法跟filter方法一样
      filter是在应用程序app上调用的,directive方法也是在应用程序app上调用的
      ,同filter一样,使用自定义指令分两步
        1 是在页面中添加到dom,在页面中使用
        2 在js中定义指令,通过directive方法
          接收两个参数
            第一个参数表示自定义指令名称(在页面中使用-分隔单词,在自定义指令中通过驼峰式命名)
            第二个参数表示自定义指令处理函数
              参数是空
              作用域是window
              整个生命周期中,只执行一次
              返回值是一个对象,用来描述我们自定义指令的
      描述自定义指令的对象有一些属性
      restrict表示自定义指令的类型,四大类ECMA(这四类书写顺序是任意的,可以组合使用)
        E: 元素自定义元素类型的自定义指令
          语法 <my-title></my-title>
        C: class类自定义指令
          语法 <div class="my-title"></div>
        M: 注释中指令(应用很少)
          语法 <!-- directive: my-title -->
        A: 元素属性自定义指令
          语法 <div my-title></div>
      template 表示自定义指令模板
      replace 表示是否替换该元素(dom中元素是否删除)


自定义指令作用域
  每一个自定义指令都会拥有一个作用域,我们可以通过$scope属性来约束这个作用域
  可以通过controller定义控制器,来创建一个作用域
  controller他的值是一个函数,这个函数有三个常用的参数
    $scope 作用域服务,我们通过这个服务,可以创建一些数据
    $element 获取页面中的元素
      如果没有jquery类库,获取的是一个jqlite对象
      如果有jquery类库,获取的是一个jquery实例化对象
      但是这两个对象方法是一样的,使用方式也是一样的
    $attrs 根据自定义元素上的一些属性,创建一个对象
      每一个属性值代表一个自定义元素上的属性,注意(属性名称是驼峰式命令的)
      $attr:他的值也是一个对象
        对象的属性名称表示$attrs对象上的属性名称
        对象属性值表示指令元素上真是的属性名称
    scope 自定义指令,默认会使用父作用域中的数据(并且是一致的)
      默认在没有定义作用域$scope时候,会使用父作用域(父控制器作用域)
      我们可以通过scope属性来约束这个作用域
      scope值有三种
        值是true,此时自定义指令的作用域是一个独立的,不会受到父作用域中的影响当然也不会影响到父作用域
        值是false(默认值),此时自定义指令的作用域与父作用域是同一个作用域,因此在自定义指令作用域中修改
        数据会影响到父作用域,同样在父作用域中修改数据,也会影响到自定义指令的作用域
        值是{},此时自定义指令会创建一个独立的作用域,但是在自定义指令模板中是使用不了的,使用时候
        还是父作用域中的数据


模板作用域
  scope 有三种情况
    未定义scope(默认情况,未定义scope的时候)时候,自定义指令作用域与父作用域是同一个作用域,他们的变量行为是一致的
    值是true,自定义指令作用域是独立的,因此父作用域中修改数据不会影响子作用域,
    子作用域修改变量也不会影响父作用域
    值是一个{},跟值为true效果是一样的,自定义指令用其自身数据渲染页面
  这三种情况在angular中叫隔离作用域
    当值是一个对象的时候,我们想使用父作用域中的数据怎么办?
    通过作用域的修饰符来实现


作用域的修饰符,跟vue中props属性很像
  在angular中,使用父作用域中的数据,可以通过属性的传递方式来实现
@修饰符
  实现父作用域像子作用域中传递数据的方式的一种
  第一步 在自定义元素上创建属性(这个属性是一个普通字符串,其值就是一个字符串,因此,想将
    父作用域的变量传递进来,就要使用插值语法)
  第二步,在scope属性中通过@符号将属性值与作用域变量绑定起来
  特点
    1 此时在自定义指令作用域中,无法修改父作用域中的数据,数据传递是单向的
    2 该数据绑定方式,会将自定义作用域中的相应变量覆盖


link 方法
  对自定义指令的编译方法
  到目前为止,我们只是操作自定义指令的内容,作用域,对于指令具体实现什么功能,我们还没有办法实现
  有三个参数
    scope 自定义指令的作用域
    jqlite 获取自定义指令的元素(jqlite对象)
    attrs 自定义指令元素的属性对象
  在link方法中,我们可以对指令元素添加功能
  scope.$watch方法,可以实现对属性值的监听


complie
  (这里有个小问题是,视频中自定义指令作用域在link之前是指向window的,但是自己测试的话是指向他自己的作用域)
  表示指令编译的全过程
  特征
    1 页面中有几个自定义指令就会调用几次,跟link是一样的
    2 参数有两个(默认情况)
      第一个参数表示jqlite对象
      第二个是attrs属相对象
    3 作用域就是自定义指令对象(通过this访问自定义指令对象上的属性方法)
    4 返回值就是link函数,使用方法跟link方法是一致的
    5 在该方法中(返回函数的前面)我们是无法使用作用域的,也就是说自定义指令作用域是在link方法执行前创建的
    6 link方法和complie都是在每次创建自定义指令时候调用的方法,但是complie方法不论页面中有多少各自定义
    指令元素,那么它一定在link方法执行之前执行


transclude
  作用: 是将自定义指令元素中的未知内容,插入到模板中,这个指令要有模板配合(内部或者外部模板)
  内部模板童工template定义
  外部模板通过templateUrl定义
  模板会告诉我们这些未知的内容会放在哪里,这个元素就要有ng-transclude指令
  必须设置transclude属性,并且属性值必须是true


require
  为自定义指令添加依赖指令的,他的值是一个数组,我们可以将多个指令传递进来
    如果依赖的指令只有一个,我们可以不用数组,直接书写,此时link方法中第四个参数就是该指令
  当添加这个属性的时候,link函数会增加一个参数来表示它
0 0