000 (H5*) 常见代码

目录:

1:HTML

 

1:块级元素(block-level)

2:行内元素(inline-level)

3:行内块元素(inline-block)

4: img标签

5:表单元素

6:自定义列表  dl

7:表格  Table

 

2:CSS

 

1:标签选择器:

2:class选择器

3:id选择器

4:通配选择器

5:后代选择器

6:子代选择器

7:交集选择器

8:并集选择器

9:链接伪类选择器  LV hao

10:font 风格权重  大小字体

11:装饰  text-decoration

12:背景  background

13: 阴影  shadow

14:边框 border

14:边框 border

15:内边距 padding

16:浮动

17:定位(覆盖、脱标)

 

3:JS

 

1:js是一门什么语言,包含什么

2:js中的原始数据类型: number,string,boolean,undefined,null,object

3:类型转换

4:变量

5: 操作符:一些符号-----用来计算

6:数组:存储一组有序的数据,数据类型可以不一样

7:函数

8:变量、作用域、作用域链

9:函数作为参数

10:函数作为返回值

11: 预解析和函数预解析分段不冲突、变量不分段

12:对象

13:简单数据类型和复杂数据类型

14:Math

15:日期:date 

16:字符串

17:Array  数组的方法

18:包装类型

19:构造函数、原型对象、实例对象之间的关系

20:原型对象的简单写法--必须手动添加构造器

21:实例对象访问属性和方法

22:call和apply方法调用  修改原型指向,调用

23:bind方法复制 

24:闭包

25:沙箱:虚拟测试和真实世界结果一样,不影响真实世界。

26:原型和原型链

27:构造函数的原型指向可以改变

28: 原型的最终指向

29:先修改原型指向在添加方法。

30:  一个神奇的原型链

31:原型链

32:继承(通过原型来修改原型执行实现继承) 

33:利用call,在构造函数中修改原型指向

34:组合继承

35:拷贝继承

36:函数声明和函数表达式的区别

37:函数中this的指向

38:浅拷贝

39:深拷贝

40:遍历DOM树

41:正则表达式

42:正则表达式的创建方式

43:字符创中的正则表达式

44:真数组和伪数组

 

4:Vue

 

1:MVC和MVVM(背诵)

2:常见的指令

3:  五大事情修饰符

4:在Vue中使用CSS

5:v-for遍历

7:v-if和v-show指令 

8:  过滤器

9: 自定义指令

10:Vue的生命周期

11:按键修饰符号

12:Vue动画

13:组件化开发

14:组件中的数据和方法

15:组件之间的切换

16:父组件向子组件传值,通过属性绑定的方式

17:父组件向子组件传递事件--实现向父组件传值

18:  ref获取dom元素和组件

19:路由6部曲

20:路由传递参数

21:路由嵌套

22:watch

 

5:webpackage

 

 

 

 

6:算法

 

 

 

正文

1:HTML

 1:块级元素(block-level)

<div> 、<p>

<ul>、<ol>、<li>

<h1>~<h6>

 

2行内元素(inline-level)

<span>、<a>

<strong>、<b>、<em>、<i>、<del>、<s>、<ins>、<u>

 

3:行内块元素(inline-block

<img />、<input />、<td>

 

4: img标签

 <img src="timg.gif" title="梅长苏"  alt="我是梅长苏, 没了"  border="10"/> 

src:图像路径

title:鼠标悬浮的时候显示的文本

alt:图片不显示的时候,替换文本

border:边框

 

5:表单元素

<input type="text" value="北京" style="color: #ccc;" 

<input type="password" value="北京" style="color: #ccc;"

 

<input type="radio" value="北京" style="color: #ccc;" 

<input type="checkbox" value="北京" style="color: #ccc;" 

 

<input type="button" value="北京" style="color: #ccc;" 

<input type="submit" value="北京" style="color: #ccc;" 

<input type="reset" value="北京" style="color: #ccc;" 

<input type="image" value="北京" style="color: #ccc;" 

 

<input type="file" value="北京" style="color: #ccc;" 

 

text   password 文本  密码

radio checkbox(要有name属性)  单选框 复选框

button submit  reset image    普通按钮  提交按钮 重置按钮  背景图片按钮

file 上传文件按钮

 

6:自定义列表  dl

<dl

   <dt>css网站</dt> 

   <dd>网址为www.divcss5.com</dd> 

   <dt>div css网站</dt> 

   <dd>网址为www.divcss5.com</dd> 

   <dt>div+css网站</dt> 

   <dd>网址为www.divcss5.com</dd> 

</dl>

 

dl:defined list 自定义列表

dt:  defined title 列表项标题

dd:  defined  description  列表项描述

 

7:表格  Table

 <table width="500" >

       <caption>个人信息表</caption>

       <thead>

          <tr>

             <th>姓名</th>

          </tr>

        </thead>

        <tbody>

            <tr>

              <td>小王</td>    

            </tr>

         </tbody>

</table>

 

table:表格

caption:标题

thead  表头

tbody:表格主体

tr:一行

th:表头的单元格

td:  表格主体单元格

 

 

2:CSS

标签 类 id 通配符

后代 子代

交集  并集

伪类

 

 

1:标签选择器:

th {

 color:red;

}

 

2:class选择器

.suibian {

   color: blue;

}

 

 

3:id选择器

#last {

  color: pink;

}

 

4:通配选择器

* {  /** 代表所有标签的意思 使用较少 */

   color: pink;

}

 

5:后代选择器

div p  {  

  color: pink;

}

 

6:子代选择器

ul > li > a {

   color: pink; 

}

 

7:交集选择器

标签选择器和类选择器

div.red {  /*交集选择器  既是 div  又 叫 red  满足条件 用的较少 特殊情况使用  了解 */

  color: red;

}

 

 

8:并集选择器

div, 

p, 

span {   /*并集选择器  用逗号隔开  , 代表  和  集体声明 适合于相同样式   */

 color: red;

}

 

 

9:链接伪类选择器  LV hao

a:link {  /* 未访问过的连接状态*/

        color: #3c3c3c;

}

a:visited {  /*这个链接我们已经点过的样子  已访问过链接*/

        color: orange;

}

a:hover {  /*鼠标经过连接时候的样子*/

        color: #f10215;

}

a:active {  /*鼠标按下时候的样子*/

        color: green;

}

 

10:font 风格 权重  大小 字体

选择器{font: font-style  font-weight  font-size/line-height  font-family;  风格 权重  大小 字体}

h1 {

        font: italic 700 12px "微软雅黑";

}

 

11:装饰  text-decoration

div {

          /*text-decoration: none;  取消装饰*/

          text-decoration: underline; /*下划线*/

          /*text-decoration: overline; 上划线*/

          /*text-decoration: line-through;  删除线*/

}

 

12:背景  background

background: red url(image.jpg) repeat-y  scroll 50% 0 ; 

background:背景颜色 背景图片地址 背景平铺 背景滚动 背景位置x轴  y轴

如果是关键字

top center bottom

left center right

 

13: 阴影  shadow

box-shadow: 5px 5px 3px 4px rgba(0, 0, 0, .4) outset/inset;
box-shadow:水平位置 垂直位置 模糊距离 阴影尺寸(影子大小) 阴影颜色  外/内阴影;

 

14:边框 border

border: 1px solid red; /*上边框*/

大小 风格 颜色

none:没有边框即忽略所有边框的宽度(默认值)

solid:边框为单实线(最为常用的)

dashed:边框为虚线  

dotted:边框为点线

 

15:内边距 padding

/*上下左右都是 20px*/

padding: 20px; 

 /*上下 10  左右 20*/

padding: 10px 20px;

/*上 10  左右 20  下 是 30*/

padding: 10px 20px 30px; 

/* 上 10  右20  下 30 左 40*/

padding: 10px 20px 30px 40px;  

 

16:浮动 为了让块元素在一行展示

1:float      浮 漏 特   

浮:    加了浮动的元素盒子是浮起来的,漂浮在其他的标准流盒子上面。

漏:    加了浮动的盒子,不占位置的,它浮起来了,它原来的位置漏 给了标准流的盒子。

特:    特别注意,首先浮动的盒子需要和标准流的父级搭配使用, 其次 特别的注意浮动可以使元素显示模式体现为行内块特性。

不会超过内边距

影响下面的元素

 

2: 清除浮动本质

清除浮动主要为了解决父级元素因为子级浮动引起内部高度为0 的问题。

 

3:清除浮动的方法

1:额外标签法

<!-- 最后一个浮动标签的后,新添加一个标签 清除浮动 -->
<div style="clear:both"></div>  

 

2: 父级添加overflow属性方法

/*别加错位置了,给 父亲加*/
<div class="overflow: hidden">

3:after伪元素清除浮动

 .clearfix:after {  content: ""; display: block; height: 0; clear: both; visibility: hidden;  }   

 .clearfix {*zoom: 1;}   /* IE6、7 专有 */

 

4:双元素清除浮动

 

     .clearfix:before, .clearfix:after {

        content: "";
        display: table;
    }
.clearfix:after {
        clear: both;
    }

.clearfix {
        *zoom: 1;
    }

 

17:定位(完成飘起来、脱标)

1:静态定位 static

标准流

 

2:相对定位relative(自恋型):占有位置

1. 脱标、占有位置

2. 每次移动的位置,是以自己的左上角为基点移动(相对于自己来移动位置)

3:那么定位的主要价值就是 移动位置, 让盒子到我们想要的位置上去。

 

3:绝对定位absolute (拼爹型):浮动、不占位置(浮动之后,margin失效)

绝对定位是将元素依据最近的已经定位(绝对、固定或相对定位)的父元素(祖先)进行定位。 

 

4:固定定位fixed(认死理型):脱标、不占位置

固定定位有两点:

 1. 固定定位的元素跟父亲没有任何关系,只认浏览器。

2. 固定定位完全脱标,不占有位置,不随着滚动条滚动。

 

5:子绝父相

 

3:JS

1:js是一门什么语言,包含什么

  脚本语言:  不需要编译,直接运行

 

  解释性语言:  遇到一样代码就解释一行代码

 

  动态

  基于对象

  弱类型语言:声明变量的时候都使用var

 

  JS分三个部分:
    * 1. ECMAScript标准: js的基本的语法
    * 2. DOM
    * 3. BOM

 

2:js中的原始数据类型: number,string,boolean,undefined,null,object

     number数据类型----无论是整数还是小数都是number数据类型的
     string数据类型----字符串,获取字符串的长度:变量名.length
     boolean数据类型---两个值,true,false
     null----只有一个,null
     undefined----只有一个,undefined,一个变量声明了,没有赋值
     object---对象-----面向对象的时候讲解

     null和undefined数据是没有太大意义的,null是很有意义的---对象的位置讲
     NaN----不是一个数字,不是一个数字和一个数字计算--->结果就是NaN
     isNaN()--->判断这个变量或者这个值是不是 不是一个数字---如果不是一个数字结果是true,如果是一个数字结果false

 

3:类型转换

   1:其他类型转数字
     parseInt()---->转整数
     parseFloat()--->转小数
     Number()---->转数字-----要比上面两个严格

//    console.log(parseInt("10"));//10
//    console.log(parseFloat("10"));//10
//    console.log(Number("10"));//10
   2: 其他类型转字符串
     .toString()
     String();
    
//    var num=10;
//    console.log(num.toString());//字符串类型
// //2 String(); // var num1=20; // console.log(String(num1));

3:其他类型转布尔类型 Boolean()---->要么是true要么是false
    //1  Boolean(值);
//
//    console.log(Boolean(1));//true
//    console.log(Boolean(0));//false
//    console.log(Boolean(11));//true
//    console.log(Boolean(-10));//true
//    console.log(Boolean("哈哈"));//true
//    console.log(Boolean(""));//false
//    console.log(Boolean(null));//false
//    console.log(Boolean(undefined));//false

4:变量

1:作用,存储数据的或者是操作数据

2:获取变量的类型    var num = 10;

    var str = "小白";
    var flag = true;
    var nll = null;
    var undef;
    var obj = new Object();
    //是使用typeof 获取变量的类型
    console.log(typeof num);//number
    console.log(typeof str);//string
    console.log(typeof flag);//boolean
    console.log(String(nll));//是null
    console.log(typeof nll);//不是null
    console.log(typeof undef);//undefined
    console.log(typeof obj);//object
    console.log(typeof(num));


5: 操作符:一些符号-----用来计算
     
      1:算数运算符:  +  -  * / %
      2:算数运算表达式:由算数运算符连接起来的表达式
      3:一元运算符: 这个操作符只需要一个操作数就可以运算的符号  ++  --
      4:二元运算符: 这个操作符需要两个操作数就可以运算,
      5:三元运算符: -----不讲,明天讲
      6:复合运算符: +=  -=  *= /= %=
      7:复合运算表达式:由复合运算符连接起来的表达式
     
      var num=10;
      num+=10;------>就是:num=num+10;
      console.log(num);20
     
     
      8:关系运算符: >  <  >=  <=  ==不严格的 ===严格的 !=不严格的不等 !==严格的不等
      9:关系运算表达式:由关系运算符连接起来的表达式
           关系运算表达式的结果是布尔类型
      10:逻辑运算符:
      &&---逻辑与--并且
      ||---逻辑或---或者
      !---逻辑非---取反--取非
      
      11:逻辑运算表达式:由逻辑运算符连接起来的表达式
       表达式1&&表达式2
      如果有一个为false,整个的结果就是false
      表达式1||表达式2
      如果有一个为true,整个的结果为true
      !表达式1
      表达式1的结果是true,整个结果为false
      表达式1的结果是false,整个结果为true
     
      12: 赋值运算符:  =


6:数组:存储一组有序的数据,数据类型可以不一样

 1: 数组的作用:一次性存储多个数据
      数组元素:数组中存储的每个数据,叫数组元素,存储了5个数据,有5个数组元素
      数组的长度:数组的元素的个数,叫数组的长度:数组名.length--->就是长度,数组的长度是可以改变的
      索引(下标):存储数组元素的编号,从0开始,到数组的长度-1结束
      索引是用来存储和读取数组元素的
      遍历数组:通过循环的方式找到数组中的每个数据
     
     
  2: 数组定义的方式:
      1. 通过构造函数定义数组
      var 数组名=new Array();空数组 Array()就是构造函数
      var 数组名=new Array(长度);是设置数组的初始的长度,长度是可以改变的
      var 数组名=new Array(值,值,值...);定义数组并设置数组中的元素值
2. 字面量的方式定义数组 var 数组名=[];空数组 var 数组名=[10];这个数组有一个元素,值是10,长度是1
3:存储和读取
    通过下标设置数组的元素值: 数组名[索引]=值
    通过下标访问数组的元素值: 数组名[索引]


7:函数
    1:函数:把一些重复的代码封装起来,在需要的时候直接调用这个函数就可以了
      函数作用:代码的重用
2: 函数定义: function 函数名(){ 函数体 }
3: 函数调用: 函数名();
4: 参数:形参和实参
      形参:函数定义的时候函数名字后面的小括号里的变量就是参数,是不需要写var   实参:函数调用的时候小括号里传入的变量或者是值,都是实参
      arguments----->可以获取函数调用的时候,传入的实参的个数
              arguments是一个对象,是一个伪数组
           arguments.length--->是实参的个数
           arguments[索引]---->实参的值

5:返回值:函数中如果有return,那么这个函数就有返回值 如果函数中没有return,那么这个函数没有返回值 如果函数中有return,但是后面什么内容都没有,这个函数没有明确返回值 如果一个函数没有明确的返回值,函数调用了,并且接收了,那么此时接收的结果undefined 如果直接输出函数名字,那么是这个函数的代码
无参数无返回值的函数 function f1(){ }
有参数无返回值的函数,2个参数 function f2(x,y){ }
无参数有返回值的函数 function f3(){ return 100; }
有参数有返回值的函数 function f4(x){ return "您好"; }

8:变量、作用域、作用域链

1:作用域:变量的使用范围
     全局作用域:全局变量在任何位置都可以使用的范围
     局部作用域:局部变量只能在某个地方使用---函数内
全局变量,如果页面不关闭,那么就不会释放,就会占空间,消耗内存
   隐式全局变量:声明的变量没有var,就叫隐式全局变量
    全局变量是不能被删除的,隐式全局变量是可以被删除的
    定义变量使用var是不会被删除的,没有var是可以删除的

2: 作用域链:
    在一个函数中使用一个变量,先在该函数中搜索这个变量,找到了则使用,找不到则继续向外面找这个变量,找到则使用,一直找到全局作用域,找不到则是undefined
 <script>


    var num=10;
    function f1() {
      var num=20;
      function f2() {
        var num=30;
        function f3() {
          var num=50;
          console.log(num);
        }
        f3();
      }
      f2();
    }
    f1();
  </script>

 

 

 


3:变量
   全局变量:只要是在函数外面声明的变量都可以看成或者是理解成是全局变量 局部变量:在函数中定义的变量


9:函数作为参数
<script>

    //函数可以作为参数使用,如果一个函数作为参数,那么我们说这个参数(函数)可以叫回调函数
    //只要是看到一个函数作为参数使用了,那就是回调函数


    function sayHi(fn) {
      console.log("您好啊");
      fn();//fn此时应该是一个函数
    }
    function suSay() {
      console.log("我猥琐,我邪恶,我龌龊,小苏说");
    }


    sayHi(suSay);
</ script>



10:函数作为返回值
<script>
    //结论:函数是可以作为返回值使用的:
    function f1() {
      console.log("f1函数调用了");
      return function () {
        console.log("这是一个函数");
      };
    }

    var ff=f1();//调用
    //ff就是一个函数了
    ff();

  </script>

 

11: 预解析 和 函数预解析分段不冲突、变量不分段

<script>
    //预解析:提前解析代码
    /*
    *
    * 预解析:就是在解析代码之前
    * 预解析做什么事?
    * 把变量的声明提前了----提前到当前所在的作用域的最上面
    * 函数的声明也会被提前---提前到当前所在的作用域的最上面
    *
    *
    * */

    //1****:函数调用的时候,把会函数的声明提升到作用域的上面
//    f1();//调用
//    var num=20;//这个变量的声明会提升到变量使用之前
//    function f1() {
//      console.log(num);
//      //var num=10;
//    }


  // 2:函数的声明提前 // function f1() { // console.log("小苏好猥琐"); // } // // f1(); // function f1() { // console.log("小苏没有助教猥琐"); // } // f1(); //把变量的声明提前了 // var num; // console.log(num); // num=10; // function f1() { // console.log("哈哈,助教好猥琐哦"); // } //f1();//报错 </script>

  <script>
    //预解析中,变量的提升,只会在当前的作用域(script)中提升,提前到当前的作用域的最上面
    //函数中的变量只会提前到函数的作用域中的最前面,不会出去
    //预解析会分段(多对的script标签中函数重名,预解析的时候不会冲突)

    // 1:  变量
  //  function f1() {

  //   console.log(num);//undefined
  //   var num=10;
  //   }
  //  f1();
  //  console.log(num);// 报错


    // 2:函数预解析分段不冲突,

    // f1();  // 预解析分段。只会提升到当前的script标签
    // function f1() {
    //   console.log("哈哈");
    // }

      // 3:变量预解析变量不分段
      var num = 10;

  </script>
  <script>
    
    // function f1() {
    //   console.log("嘎嘎");
    // }


     console.log(num);
     var num = 30;
     console.log(num);

  </script>

 

12:对象

1:创建对象三种方式:

 1.调用系统的构造函数创建对象

     var 变量名= new Object();

2:构造函数创建对象
 //工厂模式创建对象
    function createObject(name,age) {
      var obj = new Object();//创建对象
      //添加属性
      obj.name = name;
      obj.age = age;
      //添加方法
      obj.sayHi = function () {
        console.log("阿涅哈斯诶呦,我叫:" + this.name + "我今年:" + this.age);
      };
      return obj;
    }

 

3:自定义构造函数

   /*
    *
    * 1. 在内存中开辟(申请一块空闲的空间)空间,存储创建的新的对象
    * 2. 把this设置为当前的对象
    * 3. 设置对象的属性和方法的值
    * 4. 把this这个对象返回
    *
    * */
//自定义构造函数创建对象,我要自己定义一个构造函数,自定义构造函数,创建对象
    //函数和构造函数的区别;名字是不是大写(首字母是大写)
    // 自定义构造函数可以直接调用(和普通函数一样。) Person();
    function Person(name,age) {
      this.name=name;
      this.age=age;
      this.sayHi=function () {
        console.log("我叫:"+this.name+",年龄是:"+this.age);
      };
    }

 

4:字面量创建函数

var obj2={
      name:"小明",
      age:20,
      sayHi:function () {
        console.log("我是:"+this.name);
      },
      eat:function () {
        console.log("吃了");
      }
    };


13:简单数据类型和复杂数据类型

1:原始数据类型: number,string,boolean,undefined, null,object
    基本类型(简单类型),值类型: number,string,boolean
    复杂类型(引用类型):object
    空类型:undefined,null

2:值类型的值在哪一块空间中存储? 栈中存储
   引用类型的值在哪一块空间中存储?对象在堆上存储,地址在栈上存储

    var num=10;//值类型,值在栈上
    var obj={};//复杂类型,对象在堆,地址(引用)在栈

 3:值类型之间传递,传递的是值
    引用类型之间传递,传递的是地址(引用)

 4: 值类型作为函数的参数,传递的是值
    引用类型作为函数的参数,传递的是地址

14:Math

  1:实例对象、静态对象
实例对象:通过构造函数创建出来,实例化的对象 静态对象:不需要创建,直接就是一个对象,方法(静态方法)直接通过这个对象名字调用, 实例方法必须通过实例对象调用 静态方法必须通过大写的对象调用
2: Math是对象,不是构造函数 Math.PI----π--- Math.E----常数的底数 Math.abs(值)-----绝对值
Math.ceil(值)----向上取整 Math.floor(值)---向下取整
Math.max(值)---求最大值 Math.min(值)---求最小值
Math.pow(2,4)---求2的4次方 Math.sqrt(16)---求16开方

15:日期:date 
1:函数
    dt.getFullYear();//年
    dt.getMonth();//月---从0开始
    dt.getDate();//日
    dt.getHours();//小时
    dt.getMinutes();//分钟
    dt.getSeconds();//秒
    dt.getDay();//星期---从0开始

dt.toDateString();//日期 dt.toLocaleDateString();//日期
dt.toTimeString();//时间 dt.toLocaleTimeString

2:格式化日期
/**
 * 获取指定格式的时间
 * @param dt 日期的对象
 * @returns {string} 返回的是字符串的日期时间
 */
function getDate(dt) {
    //获取年
    var year = dt.getFullYear();
    //获取月
    var month = dt.getMonth() + 1;
    //获取日
    var day = dt.getDate();
    //获取小时
    var hour = dt.getHours();
    //获取分钟
    var minute = dt.getMinutes();
    //获取秒
    var second = dt.getSeconds();
    month = month < 10 ? "0" + month : month;
    day = day < 10 ? "0" + day : day;
    hour = hour < 10 ? "0" + hour : hour;
    minute = minute < 10 ? "0" + minute : minute;
    second = second < 10 ? "0" + second : second;
    return year + "年" + month + "月" + day + "日 " + hour + ":" + minute + ":" + second;
}
 

16:字符串

   实例方法---->必须要通过new的方式创建的对象(实例对象)来调用的方法
     静态方法---->直接通过大写的构造函数的名字调用的方法(直接通过大写的对象名字调用的)
   
     1:字符串的常用属性:
      .length------>字符串的长度
      .charAt(索引),返回值是指定索引位置的字符串,超出索引,结果是空字符串
      .fromCharCode(数字值,可以是多个参数),返回的是ASCII码对应的值
    .indexOf(要找的字符串,从某个位置开始的索引);返回的是这个字符串的索引值,没找到则返回-1 .lastIndexOf(要找的字符串);从后向前找,但是索引仍然是从左向右的方式,找不到则返回-1

    .concat(字符串1,字符串2,...);返回的是拼接之后的新的字符串
    .replace("原来的字符串","新的字符串");用来替换字符串的
    .trim();干掉字符串两端的空格
    .slice(开始的索引,结束的索引); 从索引5的位置开始提取,到索引为10的前一个结束,没有10,并返回这个提取后的字符串 
    .split("要干掉的字符串",切割后留下的个数);切割字符串

    .substr(开始的位置,个数);返回的是截取后的新的字符串
    .substring(开始的索引,结束的索引),返回截取后的字符串,不包含结束的索引的字符串

    .toLocaleLowerCase();转小写
    .toLowerCase();转小写
    .toLocaleUpperCase()转大写
    .toUpperCase();转大写
 
  <script>
    /*
     *
     * 实例方法---->必须要通过new的方式创建的对象(实例对象)来调用的方法
     * 静态方法---->直接通过大写的构造函数的名字调用的方法(直接通过大写的对象名字调用的)
     *
     * */
    /*
     *
     * 字符串的常用属性:
     * .length------>字符串的长度
     * .charAt(索引),返回值是指定索引位置的字符串,超出索引,结果是空字符串
     * .fromCharCode(数字值,可以是多个参数),返回的是ASCII码对应的值
     * .concat(字符串1,字符串2,...);返回的是拼接之后的新的字符串
     * .indexOf(要找的字符串,从某个位置开始的索引);返回的是这个字符串的索引值,没找到则返回-1
     * .lastIndexOf(要找的字符串);从后向前找,但是索引仍然是从左向右的方式,找不到则返回-1
     * .replace("原来的字符串","新的字符串");用来替换字符串的
     * .slice(开始的索引,结束的索引); 从索引5的位置开始提取,到索引为10的前一个结束,没有10,并返回这个提取后的字符串
     * .split("要干掉的字符串",切割后留下的个数);切割字符串
     * .substr(开始的位置,个数);返回的是截取后的新的字符串
     * .substring(开始的索引,结束的索引),返回截取后的字符串,不包含结束的索引的字符串
     * .toLocaleLowerCase();转小写
     * .toLowerCase();转小写
     * .toLocaleUpperCase()转大写
     * .toUpperCase();转大写
     * .trim();干掉字符串两端的空格
     *
     *
     * */


    //    var str="12345";
    //    console.log(str.length);
    //
    //    var str="whatareyounoshalei";
    //    var result=str.charAt(1000);
    //    console.log(result);

    //    var str=String.fromCharCode(107,108,109);
    //    console.log(str);


    //sos


    //    var str=String.fromCharCode(83,79,83);
    //    console.log(str);


    //    var str="what";
    //    console.log(str+"are"+"you"+"no"+"sha"+"lei");


    //    var str="小苏";
    //    console.log(str.concat("喜欢","凤姐","这是","真的"));


    //    var str="小苏真的好猥好琐啊";
    //    var index=str.indexOf("好",5);
    //    console.log(index);

    //    var str="helo amen";
    //    var index=str.lastIndexOf("Y");
    //    console.log(index);

    //    var str="小苏好帅哦,真的好勇敢哦";
    //    if(str.indexOf("帅")!=-1){
    //      str=str.replace("帅","猥琐");
    //    }else{
    //      console.log("不存在");
    //    }
    //    console.log(str);


//    var str = "如果有一天我邪恶了,请记住,我曾纯洁过";
//    //从索引5的位置开始提取,到索引为10的前一个结束,没有10,并返回这个提取后的字符串
//    str = str.slice(5, 10);
//    console.log(str);

//    var str="乔峰|慕容|凤姐|梅超风|小苏|大蛇丸";
//    var arr=str.split("|");
//    for(var i=0;i<arr.length;i++){
//      console.log(arr[i]);
//    }


//    var str="哈哈,小苏真的是好帅哦";
//    str=str.substr(5,5);
//    console.log(str);


//    var str="哈哈,小苏真的是好帅哦";
//    str=str.substring(5,9);
//    console.log(str);

//    var str="HELLO";
//    //str=str.toLocaleLowerCase();
//    str=str.toLowerCase();
//    console.log(str);


//    var str="hello";
//    str=str.toLocaleUpperCase();
//    //str=str.toUpperCase();
//    console.log(str);

    var str="   哦,这    是一个神奇的一天   ";
    str=str.trim();
    console.log("===="+str+"====");
  </script>

 

   

17:Array  数组的方法

    Array.isArray(对象)---->判断这个对象是不是数组
      instanceof关键字
      .concat(数组,数组,数组,...) 组合一个新的数组
      .every(函数)--返回值是布尔类型,函数作为参数使用,函数中有三个参数,第一个参数是元素的值,第二个参数是索引值,第三个参数是原来的数组(没用)
      如果这个数组中的每个元素的值都符合条件,最后才返回的是true
     
     .filter(函数);返回的是数组中每一个元素都复合条件的元素,组成了一个新的数组
     
      .push(值);--->把值追加到数组中,加到最后了---返回值也是追加数据之后的数组长度
      .pop();--->删除数组中最后一个元素,返回值就是删除的这个值
      .shift();--->删除数组中第一个元素,返回值就是删除的这个值
      .unshift();--->向数组的第一个元素前面插入一个新的元素,----返回值是插入后的程度
.forEach(函数)方法---遍历数组用---相当于for循环 .indexOf(元素值);返回的是索引,没有则是-1 .join("字符串");----返回的是一个字符串 .map(函数);--->数组中的每个元素都要执行这个函数,把执行后的结果重新的全部的放在一个新的数组中
.reverse();----->反转数组 .sort();---排序的,可能不稳定,如果不稳定,请写MDN中的那个固定的代码 .arr.slice(开始的索引,结束的索引);把截取的数组的值放在一个新的数组中,但是不包含结束的索引对应的元素值 .splice(开始的位置,要删除的个数,替换的元素的值);一般是用于删除数组中的元素,或者是替换元素,或者是插入元素
  <script>

    /*
     *
     * Array.isArray(对象)---->判断这个对象是不是数组
     * instanceof关键字
     * .concat(数组,数组,数组,...) 组合一个新的数组
     * .every(函数)--返回值是布尔类型,函数作为参数使用,函数中有三个参数,第一个参数是元素的值,第二个参数是索引值,第三个参数是原来的数组(没用)
     * 如果这个数组中的每个元素的值都符合条件,最后才返回的是true
     *
     * .filter(函数);返回的是数组中每一个元素都复合条件的元素,组成了一个新的数组
     *
     * .push(值);--->把值追加到数组中,加到最后了---返回值也是追加数据之后的数组长度
     * .pop();--->删除数组中最后一个元素,返回值就是删除的这个值
     * .shift();--->删除数组中第一个元素,返回值就是删除的这个值
     * .unshift();--->向数组的第一个元素前面插入一个新的元素,----返回值是插入后的程度
     * .forEach(函数)方法---遍历数组用---相当于for循环
     * .indexOf(元素值);返回的是索引,没有则是-1
     * .join("字符串");----返回的是一个字符串
     * .map(函数);--->数组中的每个元素都要执行这个函数,把执行后的结果重新的全部的放在一个新的数组中
     * .reverse();----->反转数组
     * .sort();---排序的,可能不稳定,如果不稳定,请写MDN中的那个固定的代码
     * .arr.slice(开始的索引,结束的索引);把截取的数组的值放在一个新的数组中,但是不包含结束的索引对应的元素值
     * .splice(开始的位置,要删除的个数,替换的元素的值);一般是用于删除数组中的元素,或者是替换元素,或者是插入元素
     *
     *
     * */
    //构造函数
    //    var arr1=new Array();
    //    //字面量的方式
    //    var arr2=[];


    //对象是不是数组类型:两种
    //1   instanceof
    //    var obj=[];
    //    console.log(obj instanceof Array);//false
    //
    //    //2 使用数组的
    //    console.log(Array.isArray(obj));//


    //    var arr=["a","b","c"];
    //    var newArr=Array.from(arr);
    //    console.log(newArr);

    //    var arr1=[10,20,30];
    //    var arr2=[40,50,60];
    //    console.log(arr1.concat(arr2));

    //    var arr=[1000,2000,3000];
    //    //a----: 元素的值
    //    //b----: 索引的值
    //    //c----:谁调用了这个方法,那么c就是谁---->arr
    //   var flag= arr.every(function (a,b) {
    //      //console.log(a+"==="+b+"===="+c);
    //      return a>2000;//数组中的每个元素的值都要大于2000的情况,最后才返回true
    //    });


    //    var arr=["小明明lkko","小曹操674","小白白bd","笑眯眯a"];
    //   var flag=arr.every(function (ele,index) {
    //      //数组中的每个元素的长度是不是大于4
    //      return ele.length>4;
    //    });


    //console.log(flag);


    //    var arr=[10,20,30,40,50,60,70,80];
    //    var newArr=arr.filter(function (ele) {//ele---每个元素
    //      return ele>40;
    //    });
    //    console.log(newArr);

    //    var arr=[10,0,20,0,40,0,60,100];
    //    var newArr=arr.filter(function (ele) {
    //      return ele!=0;
    //    });
    //    console.log(newArr);

    //    var arr=[10,20,30,40,50];
    //    var result=arr.unshift(100);
    //    console.log(result);
    //    console.log(arr);
//
//    var arr = [10, 20, 30, 40];
//    arr.forEach(function (ele,index) {
//      console.log(ele+'======'+index);
//    });

//    var arr=[10,20,30,40];
//    var index=arr.indexOf(300);
//    console.log(index);


//    var arr=["小白","小黑","小红","小芳","小绿","小苏"];
//    var str=arr.join("|");
//    console.log(str);


//    var numbers = [1, 4, 9];
//    var roots = numbers.map(Math.sqrt);
//    console.log(roots);


//    var arr=[10,20,30,40,50];
//    arr.reverse();//反转
//    console.log(arr);


//    var arr=[1,40,20,10,100];
//    //a---arr[j]
//    //b---arr[j+1]
//    arr.sort(function (a,b) {
//      if(a>b){
//        return 1;
//      }else if(a==b){
//        return 0;
//      }else{
//        return -1;
//      }
//    });
//    console.log(arr);


//
//    var arr=[10,20,30,40,50,60,70,80,90,100];
//    var newArr= arr.slice(3,7);
//    console.log(newArr);


    var myFish = ['angel', 'clown', 'mandarin', 'sturgeon'];

   // myFish.splice(2, 0, 'drum'); // 在索引为2的位置插入'drum'

    // myFish 变为 ["angel", "clown", "drum", "mandarin", "sturgeon"]

    myFish.splice(2, 1); // 从索引为2的位置删除一项(也就是'drum'这一项)

    console.log(myFish);
    // myFish 变为 ["angel", "clown", "mandarin", "sturgeon"]
  </script>

 

18:包装类型

  <script>
    //基本包装类型

    //普通变量不能直接调用属性或者方法
    //对象可以直接调用属性和方法

    //基本包装类型:本身是基本类型,但是在执行代码的过程中,如果这种类型的变量调用了属性或者是方法,那么这种类型就不再是基本类型了,而是基本包装类型,这个变量也不是普通的变量了,而是基本包装类型对象
    //string number boolean


//    var str="hello";
//    str=str.replace("ll","HH");
//    console.log(str);


//    var str=new String("hello");
//    str=str.replace("ll","HH");
//    console.log(str);
//    str=null;

//    var num=10;//number---->
//    console.log(num.toString());


    //如果是一个对象&&true,那么结果是true
    //如果是一个true&&对象,那么结果是对象


//    var flag=new Boolean(false);
//    var result=true&&flag;
//    console.log(result);


//    var num=10;
//    var num2=Number("10");//转换,没有new---类型转
//    var num3=new Number("10");//基本包装类型


  </script>

 


19:构造函数、原型对象、实例对象之间的关系
   1 构造函数可以实例化对象
   2 构造函数中有一个属性叫prototype,是构造函数的原型对象
   3 构造函数的原型对象(prototype)中有一个constructor构造器,这个构造器指向的就是自己所在的原型对象所在的构造函数
   4 实例对象的原型对象(__proto__)指向的是该构造函数的原型对象
   5 构造函数的原型对象(prototype)中的方法是可以被实例对象直接访问的

20:原型对象的简单写法--必须手动添加构造器

<script>
    function Student(name, age, sex) {
      this.name = name;
      this.age = age;
      this.sex = sex;
    }
    //简单的原型写法
    Student.prototype = {
      //手动修改构造器的指向
      constructor:Student,
      height: "188",
      weight: "55kg",
      study: function () {
        console.log("学习好开心啊");
      },
      eat: function () {
        console.log("我要吃好吃的");
      }
    };

    var stu=new Student("段飞",20,"");
    stu.eat();
    stu.study();
    console.dir(Student);
    console.dir(stu);

  </script>

 

21:实例对象访问属性和方法

<script>
    function Person(age,sex) {
      this.age=age;//年龄
      this.sex=sex;
      this.eat=function () {
        console.log("构造函数中的吃");
      };
    }
    Person.prototype.sex="";
    Person.prototype.eat=function () {
      console.log("原型对象中的吃");
    };


    var per=new Person(20,"");
    console.log(per.sex);//
    per.eat();

    // console.log(per.height);//男
    // per.play();

    console.dir(per);


    /*
    * 实例对象使用的属性或者方法,先在实例中查找,找到了则直接使用,找不到则,去实例对象的__proto__指向的原型对象prototype中找,找到了则使用
    *  找不到属性:undefined
    *  找不到方法: 报错 Uncaught TypeError: per.play is not a function
    * */


  </script>

 

22:call和apply方法调用  修改原型指向,调用

call:参数个数

apply:参数数组

<script>
        function f1 (x, y) {
            console.log("结果是:"+(x+ y) + this);
        }
        
        // 函数的调用
        f1(10, 20);

        console.log("===========");

        //1:  此时的f1实际上是当成对象来使用的,对象可以调用方法,apply和call方法也是函数的调用的方式
        
        f1.apply();
        f1.call();


        //2:  apply和call都可以让函数或者方法来调用,传入参数和函数自己调用的写法不一样,但是效果是一样的, apply传入的是数组,  call,传入的是参数
    
        f1.apply(null, [100, 200]);

        f1.call(null, 100, 200);
        console.log("===========");

        function f2(x, y){
            console.log("这个函数是window对象的一个方法"+ (x+y) + this);
            console.dir(this);
        }

        window.f2(10, 20);

        var obj = {
            age: 10,
            name: "张三",
        }

        //3:  apply和call可以改变this的指向,
        window.f2.call(obj, 10, 20);
        window.f2.apply(obj, [10,20]);


        // 4:apply和call方法实际上并不在函数这个实例对象中,而是在Function的prototype,原型对象中。
        原型对象可以看成+方法,实例方法可以当成-方法。调用+方法时候可以当成对象。
        console.log(f2.__proto__ == Function.prototype);

        console.log(Function.prototype); //{ [native code] }

        console.dir(Function);

    
    </script>

 


23:bind方法复制 

修改原型指向,没有调用

<script>
        
        console.log("=====  11 =====")
        function f1 (x, y ){
            console.log((x+y) + " :======>>>>"+this );
            console.dir(this);
        }    
        
        f1.bind();

        //  方法复制了一份,并且传递参数,结果还是方法,方法没有调用。此时f1是对象。
        //   bind方法是复制的意思,可以在复制的时候传递参数,也可以在复制之后传递参数
        //  apply 和 call 是调用的时候改变this的指向
        //  bind是 复制的时候修改this的指向
        var ff = f1.bind(null, 10, 20);

        console.log (ff);

        ff();


        var f2 = f1.bind(null);
        f2(10, 20);
        console.log("=====  22 =====")


        // bind是方法复制,apply和call是方法调用
        function Person (){
            this.age = 10;
        }

        Person.prototype.eat = function () { 
            console.log("这个是吃");
         };

         var per = new Person;

         var ff = f1.bind(per);

         ff(10, 20);


         console.log("=====  33 =====")

         function Person(age) {
             this.age = age;
         }

         Person.prototype.play = function () {
             console.log(this + "========>>>>" + this.age);
         }


         function Student (age) {
             this.age = age;
         }

         var per = new Person(10);
         var stu = new Student(20);

         var paly2 = per.play.bind(stu);

         paly2();

    </script>

 

24:闭包

1:闭包的定义:

函数A中,有一个函数B,函数B中可以访问函数A中定义的变量或者数据,此时就行程了闭包。
 闭包缓存数据
 总结:如果想要缓存数据,需要把数据放在外层函数和内层函数之间。
 
 闭包的作用:缓存数据。优点也是缺点,没有及时释放
 局部变量在函数中,函数使用结束后,局部变量就会被自动释放。
 闭包后,里面的局部变量的使用作用域链就会被延长。
   <script>
        /* 闭包
         * 闭包的概念:函数A中,有一个函数B,函数B中可以访问函数A中定义的变量或者数据,此时就行程了闭包。

         *闭包的模式:函数闭包和对象闭包

         * 闭包的作用:缓存数据,延长作用域链

         * 闭包的优点和缺点:缓存数据

         * 闭包的应用:

         * ****/


         console.log("=======  11  ========");
        //  1:函数式闭包
         function f1() {
             var num = 10;

             // 函数
             function f2() {
                 console.log(num);
             }

             f2();
         }

         f1();

         console.log("=======  22  ========");
        //  2:对象是闭包
        function  f3() {

            var num1 = 20;

            // 对象
            var obj = {
                age : num1,
            }

            console.log(obj.age);
        }

        f3();

        console.log("=======  33  ========");

        function f4() {
            var num4 = 40;
            return function () { 
                console.log(num4); 
                return num4;
            };
        }
 
        var ff1 = f4();
        var result =  ff1();
        console.log(result);
        

        console.log("=======  44  ========");
        function f5() {
            var num5 = 50;
            var obj = {
                age : num5,
            }
            return obj;
        }

        var resultObj = f5();
        var result5 = resultObj.age;
        console.log(result5);
    </script>

 

 

25:沙箱:虚拟测试和真实世界结果一样,不影响真实世界。

1:沙箱的定义和2种格式

<script>
       //沙箱:环境,黑盒,在一个虚拟的环境中模拟真实世界,做实验,实验结果和真实世界的结果是一样,但是不会影响真实世界 
        
       // 沙箱 函数的自调用

       console.log("========  11  ========");
       // 沙箱的模板,函数自调用两种格式
        //   格式一:       ()();
       (function () {  
        var num = 10;
        console.log(num + 10);
       })();



       // 格式二:使用的比较多.    (());
       (function () {  
        var num = 10;
        console.log(num + 20);
       }());

     
    </script>

 

26:原型和原型链

<script>
        // 1:使用对象---->使用对象中的属性和方法,就需要先有构造函数

        // 1.1:构造函数。
        function Person (name, age){
            this.name = name;
            this.age = age;
            this.sayHi = function () {  
                console.log("您好,您真帅");
            };
        }    
        
        // 1.2:实例化对象,并初始化
        var per = new Person("小明", 20);

        // 1.3: 如果想要使用一些属性和方法,并且属性的值在每个对象中都是一样的,方法在每个对象中的操作也是一样的,那么,为了共享数据,节约内存空间,是可以把属性和方法通过原型的方法进行赋值
        
        Person.prototype.sex = "";
        Person.prototype.sayHello = function (){
            console.log("您怎么可以这么帅呀");
        };

        console.dir(per);     // 实例对象
        console.dir(Person);  // 构造函数

        // 实例对象中的原型__proto__和构造函数中的原型prototype指向是一样的,指向的是原型对象
        // 实例对象的原型__proto__原型指向的是  构造函数中的原型prototype,原型对象

        // 原型对象中的构造器指向的是原型对象所在的构造函数
        // 实例对象和原型对象通过原型来联系的

        // 实例对象中的原型__proto__是游览器使用的,不是正规的
        // 构造函数中的prototype是原型,是程序员使用的

        // 原型链:是一种关系,实例对象和原型对象之间的关系,关系是通过原型(__proto__)来联系的
        console.log(per.__proto__ == Person.prototype);
    </script>

 

 

1:实例对象中的原型__proto__和构造函数中的原型prototype指向是一样的,指向的是原型对象

2:实例对象的原型__proto__原型指向的是 构造函数中的原型prototype,原型对象

3:原型对象中的构造器指向的是原型对象所在的构造函数,实例对象和原型对象通过__proto__来联系的

4:  原型链:是一种关系,实例对象和原型对象之间的关系,关系是通过原型(__proto__)来联系的

 

 




27:构造函数的原型指向可以改变

<script>

        console.log("=======  11  =======");  
        // 1:构造函数中的this是实例对象
        function Person (age){
            this.age = age;
            console.log(this);
        }    
        
        // 2:原型对象中的方法中的this是实例对象
        Person.prototype.eat = function (){
            console.log(this);
            console.log("人吃了吗?");
        };

        var per = new Person(20);
        
        per.eat();


        console.log("=======  22  ======="); 
        // 3:学生
        function Student (){

        };


        // 原型的指向是可以改变的
        // 构造函数的原型对象(prototype)指向如果改变了,实例对象的原型(__proto__)指向也会发生改变

        // 原型的指向是可以改变的
        // 实例对象和原型对象之间的关系是通过__proto__原型来联系起来的,这个关系就是原型链
        Student.prototype = new Person(20);

        var stu = new Student();
        stu.eat();
    </script>

 

1:  原型的指向是可以改变的
2:  构造函数的原型对象(prototype)指向如果改变了,实例对象的原型(__proto__)指向也会发生改变
3:   实例对象和原型对象之间的关系是通过__proto__原型来联系起来的,这个关系就是原型链

 

 

 

28: 原型的最终指向

<script>
    
        // 1:  只要是对象就有__proto__.
        // 2:  只要有__proto__,他就指向某个构造函数的prototype、
    
        function Person() {

        }
        Person.prototype.eat=function () {
        console.log("吃东西");
        };

        var per=new Person();
        console.dir(per);
        console.dir(Person);

        //实例对象中有__proto__原型
        //构造函数中有prototype原型
        //prototype是对象
        //所以,prototype这个对象中也有__proto__,那么指向了哪里
        //实例对象中的__proto__指向的是构造函数的prototype
        //所以,prototype这个对象中__proto__指向的应该是某个构造函数的原型prototype

        //Person的prototype中的__proto__的指向
        //console.log(Person.prototype.__proto__);

        //per实例对象的__proto__------->Person.prototype的__proto__---->Object.prototype的__proto__是null

        console.log(per.__proto__==Person.prototype);
        console.log(per.__proto__.__proto__==Person.prototype.__proto__);
        console.log(Person.prototype.__proto__==Object.prototype);
        console.log(Object.prototype.__proto__);
    </script>

1:实例对象per的__proto__指向的是构造函数Person的prototype对象。

2:prototype是一个对象。

3:prototype的__proto__指向的是某个构造函数的prototype对象。  某个指的是:NSobject。

4:NSObject的原型对象prototype对象,他的__proto__指向的是null。

 

 

 

29:先修改原型指向在添加方法。

<script>
    
        function Person (age){
            this.age = age;
        };

        Person.prototype.eat = function () {  
            console.log("人在吃饭");
        };
    
        function Student(sex){
            this.sex = sex;
        };

        // 1: 修改原型指向
        Student.prototype = new Person(10);

        // 2: 添加原型方法,要想问原型添加新方法,一定要再原型指向修改后添加原型方法。
        Student.prototype.sayHi = function (){
            console.log("您好呀,学生!!");
        };

        var stu = new Student("");
        console.dir(stu);

    </script>

1:先添加原型方法,在修改原型指向。

 

 

2:先修改原型指向,在添加原型方法。方法添加在实例对象中。

 

 

 

30:  一个神奇的原型链

 

<body>
    <div id="dv"></div>
    <script>
      //原型链:实例对象和原型对象之间的关系,通过__proto__来联系
      var divObj=document.getElementById("dv");
      console.dir(divObj);

      //divObj.__proto__---->HTMLDivElement.prototype的__proto__--->HTMLElement.prototype的__proto__---->Element.prototype的__proto__---->Node.prototype的__proto__---->EventTarget.prototype的__proto__---->Object.prototype没有__proto__,所以,Object.prototype中的__proto__是null
    </script>
</body>

1:首先从f3中找age,之后在f2中找age,最后在f1中找age,如果没有就是undefined。

 

 

31:原型链

1:原型链是实例对象之间的关系,实例对象中__proto__之间的关系。

 

 

32:继承(通过原型来修改原型执行实现继承) 

<script>

    /*
    *
    * 面向对象编程思想:根据需求,分析对象,找到对象有什么特征和行为,通过代码的方式来实现需求,要想实现这个需求,就要创建对象,要想创建对象,就应该显示有构造函数,然后通过构造函数来创建对象.,通过对象调用属性和方法来实现相应的功能及需求,即可
    * 首先JS不是一门面向对象的语言,JS是一门基于对象的语言,那么为什么学习js还要学习面向对象,因为面向对象的思想适合于人的想法,编程起来会更加的方便,及后期的维护....
    * 面向对象的编程语言中有类(class)的概念(也是一种特殊的数据类型),但是JS不是面向对象的语言,所以,JS中没有类(class),但是JS可以模拟面向对象的思想编程,JS中会通过构造函数来模拟类的概念(class)
    *
    *
    * 小明,小红,小丽,小白,小花 都是人
    * 共同的特征和行为
    * 特征--->属性
    * 行为---方法
    *
    * 面向对象的特性:封装,继承,多态
    *
    * 封装:就是包装
    * 一个值存储在一个变量中--封装
    * 一坨重复代码放在一个函数中--封装
    * 一系列的属性放在一个对象中--封装
    * 一些功能类似的函数(方法)放在一个对象中--封装
    * 好多相类似的对象放在一个js文件中---封装
    *
    * 继承: 首先继承是一种关系,类(class)与类之间的关系,JS中没有类,但是可以通过构造函数模拟类,然后通过原型来实现继承
    * 继承也是为了数据共享,js中的继承也是为了实现数据共享
    *
    * 原型作用之一:数据共享,节省内存空间
    * 原型作用之二:为了实现继承
    *
    * 继承是一种关系:
    *
    * 父类级别与类级别的关系
    *
    * 例子:
    *
    * 小杨--->人, 姓名, 有钱, 帅, 有功夫--降龙十八掌
    * 小杨子-->人,
    * 继承:
    * 姓氏----继承
    * 外表----继承
    * 财产----继承
    * 功夫---继承
    *
    *
    * 人:  姓名, 性别, 年龄 ,吃饭, 睡觉
    *
    * 学生类别: 姓名, 性别, 年龄 ,吃饭, 睡觉 学习行为
    * 老师类别: 姓名, 性别, 年龄 ,吃饭, 睡觉 工资,教学行为
    * 程序员: 姓名, 性别, 年龄 ,吃饭, 睡觉 工资, 敲代码
    * 司机类别: 姓名, 性别, 年龄 ,吃饭, 睡觉 工资 开车
    *
    *
    * 动物类别:  体重, 颜色, 吃
    * 狗类别:   体重,颜色, 吃, 咬人
    * 二哈类别: 体重,颜色, 吃, 咬人 逗主人开心,汪汪,你好帅
    *
    * 多态:一个对象有不同的行为,或者是同一个行为针对不同的对象,产生不同的结果,要想有多态,就要先有继承,js中可以模拟多态,但是不会去使用,也不会模拟,
    * */



    //例子:
    //人,都有姓名,性别,年龄, 吃饭, 睡觉, 玩
    //学生,都有姓名,性别,年龄, 成绩, 吃饭, 睡觉, 玩 ,学习的行为


    //js中通过原型来实现继承

    function Person(name,age,sex) {
      this.name=name;
      this.sex=sex;
      this.age=age;
    }
    Person.prototype.eat=function () {
      console.log("人可以吃东西");
    };
    Person.prototype.sleep=function () {
      console.log("人在睡觉");
    };
    Person.prototype.play=function () {
      console.log("生活就是不一样的玩法而已");
    };


    function Student(score) {
      this.score=score;
    }
    //改变学生的原型的指向即可==========>学生和人已经发生关系
    Student.prototype=new Person("小明",10,"");
    Student.prototype.study=function () {
      console.log("学习很累很累的哦.");
    };

    //相同的代码太多,造成了代码的冗余(重复的代码)

    var stu=new Student(100);
    console.log(stu.name);
    console.log(stu.age);
    console.log(stu.sex);
    stu.eat();
    stu.play();
    stu.sleep();
    console.log("下面的是学生对象中自己有的");
    console.log(stu.score);
    stu.study();
 </script>

 

33:利用call,在构造函数中修改原型指向

父类中的方法无法继承


<script>
    
    //解决方案:继承的时候,不用改变原型的指向,直接调用父级的构造函数的方式来为属性赋值就可以了------借用构造函数:把要继承的父级的构造函数拿过来,使用一下就可以了    

    //借用构造函数:构造函数名字.call(当前对象,属性,属性,属性....);
    //解决了属性继承,并且值不重复的问题
    //缺陷:父级类别中的方法不能继承

    function Person(name, age, sex, weight) {
      this.name = name;
      this.age = age;
      this.sex = sex;
      this.weight = weight;
    }
    Person.prototype.sayHi = function () {
      console.log("您好");
    };
    function Student(name,age,sex,weight,score) {
      //借用构造函数
      Person.call(this,name,age,sex,weight);
      this.score = score;
    }
    var stu1 = new Student("小明",10,"","10kg","100");
    console.log(stu1.name, stu1.age, stu1.sex, stu1.weight, stu1.score);

    var stu2 = new Student("小红",20,"","20kg","120");
    console.log(stu2.name, stu2.age, stu2.sex, stu2.weight, stu2.score);

    var stu3 = new Student("小丽",30,"","30kg","130");
    console.log(stu3.name, stu3.age, stu3.sex, stu3.weight, stu3.score);


  </script>

 

34:组合继承

1:构造函数call解决属性继承

2:原型继承解决方法继承。

<script>


    //原型实现继承
    //借用构造函数实现继承
    //组合继承:原型继承+借用构造函数继承

    function Person(name,age,sex) {
      this.name=name;
      this.age=age;
      this.sex=sex;
    }
    Person.prototype.sayHi=function () {
      console.log("阿涅哈斯诶呦");
    };
    function Student(name,age,sex,score) {
      //借用构造函数:属性值重复的问题
      Person.call(this,name,age,sex);
      this.score=score; 
    }
    //改变原型指向----继承
    Student.prototype=new Person();//不传值
    Student.prototype.eat=function () {
      console.log("吃东西");
    };
    var stu=new Student("小黑",20,"","100分");
    console.log(stu.name,stu.age,stu.sex,stu.score);
    stu.sayHi();
    stu.eat();
    var stu2=new Student("小黑黑",200,"男人","1010分");
    console.log(stu2.name,stu2.age,stu2.sex,stu2.score);
    stu2.sayHi();
    stu2.eat();

    //属性和方法都被继承了



  </script>

 

 

35:拷贝继承

拷贝继承;把一个对象中的属性或者方法直接复制到另一个对象中
<script>

    //拷贝继承;把一个对象中的属性或者方法直接复制到另一个对象中

//    var obj1={
//      name:"小糊涂",
//      age:20,
//      sleep:function () {
//       console.log("睡觉了");
//      }
//    };
//
//    //改变了地址的指向
//    var obj2=obj1;
//    console.log(obj2.name,obj2.age);
//    obj2.sleep();



//    var obj1={
//      name:"小糊涂",
//      age:20,
//      sleep:function () {
//        console.log("睡觉了");
//      }
//    };
//
//
//    var obj2={};
//    for(var key in obj1){
//      obj2[key]=obj1[key];
//    }
//    console.log(obj2.name);



    function Person() {
    }
    Person.prototype.age=10;
    Person.prototype.sex="";
    Person.prototype.height=100;
    Person.prototype.play=function () {
      console.log("玩的好开心");
    };
    var obj2={};
    //Person的构造中有原型prototype,prototype就是一个对象,那么里面,age,sex,height,play都是该对象中的属性或者方法

    for(var key in Person.prototype){
      obj2[key]=Person.prototype[key];
    }
    console.dir(obj2);
    obj2.play();



  </script>

 

 

36:函数声明和函数表达式的区别

以后宁愿用函数表达式,都不用函数声明
<script>

    //函数声明
//
//    if(true){
//      function f1() {
//        console.log("哈哈,我又变帅了");
//      }
//    }else{
//      function f1() {
//        console.log("小苏好猥琐");
//      }
//    }
//    f1();


    //函数表达式

    var ff;
    if(true){
      ff=function () {
        console.log("哈哈,我又变帅了");
      };
    }else{
      ff=function () {
        console.log("小苏好猥琐");
      };
    }
    ff();

    //函数声明如果放在if-else的语句中,在IE8的浏览器中会出现问题
    //以后宁愿用函数表达式,都不用函数声明



  </script>

 

37:函数中this的指向

<script>

    /*
     *
     * 函数中的this的指向
     *
     *
     * 普通函数中的this是谁?-----window
     * 对象.方法中的this是谁?----当前的实例对象
     * 定时器方法中的this是谁?----window
     * 构造函数中的this是谁?-----实例对象
     * 原型对象方法中的this是谁?---实例对象
     *
     *
     * */

    //严格模式:
//    "use strict";//严格模式
//    function f1() {
//      console.log(this);//window
//    }
//    f1();


    //普通函数
    //    function f1() {
    //      console.log(this);
    //    }
    //   f1();

    //定时器中的this
    //    setInterval(function () {
    //      console.log(this);
    //    },1000);

    //构造函数
    //    function Person() {
    //      console.log(this);
    //对象的方法
    //      this.sayHi=function () {
    //        console.log(this);
    //      };
    //    }
    //原型中的方法
    //    Person.prototype.eat=function () {
    //      console.log(this);
    //    };
    //    var per=new Person();
    //    console.log(per);
    //    per.sayHi();
    //    per.eat();


    //BOM:中顶级对象是window,浏览器中所有的东西都是window的




  </script>

38:浅拷贝

<script>
    
        //浅拷贝:拷贝就是复制,就相当于把一个对象中的所有的内容,复制一份给另一个对象,直接复制,或者说,就是把一个对象的地址给了另一个对象,他们指向相同,两个对象之间有共同的属性或者方法,都可以使用
        
        
        var obj1={
          age:10,
          sex:"",
          car:["奔驰","宝马","特斯拉","奥拓"]
        };
        //另一个对象
        var obj2={};
        
        //写一个函数,作用:把一个对象的属性复制到另一个对象中,浅拷贝
        //把a对象中的所有的属性复制到对象b中
        function extend(a,b) {
          for(var key in a){
            b[key]=a[key];
          }
        }
        extend(obj1,obj2);

        obj2.sex = "";
        console.dir(obj2);//开始的时候这个对象是空对象
        console.dir(obj1);//有属性

    
        console.log(obj1 == obj2);
        
        
    </script>

 

浅拷贝:示意图

 

39:深拷贝

// 只要不是基本类型,比如数组和对象的话,就需要重新开始开辟一块内存,来存储。之后把地址给这个属性。

<script>
        //深拷贝:拷贝还是复制,深:把一个对象中所有的属性或者方法,一个一个的找到.并且在另一个对象中开辟相应的空间,一个一个的存储到另一个对象中
    
        var obj1={
          age:10,
          sex:"",
          car:["奔驰","宝马","特斯拉","奥拓"],
          dog:{
            name:"大黄",
            age:5,
            color:"黑白色"
          }
        };
    
        var obj2={};//空对象
        //通过函数实现,把对象a中的所有的数据深拷贝到对象b中
        function extend(a,b) {
          for(var key in a){
            //先获取a对象中每个属性的值
            var item=a[key];
            //判断这个属性的值是不是数组
            if(item instanceof Array){
              //如果是数组,那么在b对象中添加一个新的属性,并且这个属性值也是数组
              b[key]=[];
              //调用这个方法,把a对象中这个数组的属性值一个一个的复制到b对象的这个数组属性中
              extend(item,b[key]);
            }else if(item instanceof Object){//判断这个值是不是对象类型的
         //如果是对象类型的,那么在b对象中添加一个属性,是一个空对象
              b[key]={};
              //再次调用这个函数,把a对象中的属性对象的值一个一个的复制到b对象的这个属性对象中
              extend(item,b[key]);
            }else{
              //如果值是普通的数据,直接复制到b对象的这个属性中
              b[key]=item;
            }
          }
        }
    
        extend(obj1,obj2);
        console.dir(obj1);
        console.dir(obj2);

    </script>

深拷贝示意图

 

 

40:遍历DOM树

<script>

  //获取页面中的根节点--根标签
  var root=document.documentElement;//html
  //函数遍历DOM树
  //根据根节点,调用fn的函数,显示的是根节点的名字
  function forDOM(root1) {
    //调用f1,显示的是节点的名字
   // f1(root1);
    //获取根节点中所有的子节点
    var children=root1.children;
    //调用遍历所有子节点的函数
    forChildren(children);
  }
  //给我所有的子节点,我把这个子节点中的所有的子节点显示出来
  function forChildren(children) {
    //遍历所有的子节点
    for(var i=0;i<children.length;i++){
      //每个子节点
      var child=children[i];
      //显示每个子节点的名字
      f1(child);
      //判断child下面有没有子节点,如果还有子节点,那么就继续的遍历
      child.children&&forDOM(child);
    }
  }
  //函数调用,传入根节点
  forDOM(root);
  function f1(node) {
    console.log("节点的名字:"+node.nodeName);
  }

  //节点:nodeName,nodeType,nodeValue


//  第一个函数:给我根节点,我会找到所有的子节点:forDOM(根节点)
//  获取这个根节点的子节点
//  var children=根节点的.children
//  调用第二个函数
//
//  第二个函数:给我所有的子节点,我把每个子节点的名字显示出来(children)
//  for(var i=0;i<children.length;i++){
//    每个子节点
//    var child=children[i];
//    f1(child);给我节点,我显示该节点的名字
//    child是子节点,但是如果child里面还有子节点,此时child就是爹了
//    child.children&&第一个函数(child)
//
//  }

</script>

 

 

41:正则表达式

<script>

    /*
    *
    * 正则表达式:也叫规则表达式,按照一定的规则组成的一个表达式,这个表达式的作用主要是匹配字符串的,
    * "我的电话:10086,他的电话:10010,你的电话:10000" 正则表达式,把这个字符串中的所有的数字找到
    *
    * 正则表达式的作用:匹配字符串的
    *
    * 在大多数编程语言中都可以使用
    *
    * 正则表达式的组成:是由元字符或者是限定符组成的一个式子
    *
    *
    * 元字符:
    *
    * 1:  .  表示的是:除了\n以外的任意的一个字符   "fdsfs238"
    *
    *
    * 2:  [] 表示的是:范围,  [0-9] 表示的是0到9之间的任意的一个数字,  "789" [0-9]
    * [1-7] 表示的是1到7之间的任意的一个数字
    * [a-z] 表示的是:所有的小写的字母中的任意的一个
    * [A-Z] 表示的是:所有的大写的字母中的任意的一个
    * [a-zA-Z] 表示的是:所有的字母的任意的一个
    * [0-9a-zA-Z] 表示的是: 所有的数字或者是字母中的一个
    * [] 另一个函数: 把正则表达式中元字符的意义干掉    [.] 就是一个.
    *
    *
    * 3:  | 或者     [0-9]|[a-z] 表示的是要么是一个数字,要么是一个小写的字母
    *
    *
    * 4:  () 分组 提升优先级   [0-9]|([a-z])|[A-Z]
    * ([0-9])([1-5])([a-z]) 三组, 从最左边开始计算
    * (()(()))
    *
    *
    * 都是元字符,但是也可以叫限定符,下面的这些
    *   5:   *   表示的是:前面的表达式出现了0次到多次
    *    [a-z][0-9]* 小写字母中的任意一个 后面是要么是没有数字的,要么是多个数字的
    *    "fdsfs3223323"  [a-z][0-9]*
    *
    *
    *   6:  +  表示的是:前面的表达式出现了1次到多次
    *    [a-z][9]+  小写字母一个后面最少一个9,或者多个9
    *    "fesfewww9fefds"
    *
    *
    *    7:  ?  表示的是:前面的表达式出现了0次到1次,最少是0次,最多1次 ,另一个含义:阻止贪婪模式
    *    [4][a-z]? "1231234ij"
    *  
    *
    *   限定符:限定前面的表达式出现的次数
    *  
    *   
    *   8:   {} 更加的明确前面的表达式出现的次数
    *  {0,} 表示的是前面的表达式出现了0次到多次,和 *一样的
    *  {1,} 表示的是前面的表达式出现了1次到多次,和 +一样的
    *  {0,1} 表示的是前面的表达式出现了0次到1次,和 ?一样的
    *  {5,10} 表示的是前面的表达式出现了5次到10次
    *  {4} 前面的表达式出现了4次
    *  {,10} 错误的========不能这么写
    *
    *
    *  9:   ^ 表示的是以什么开始,或者是取非(取反) ^[0-9] 以数字开头
    *  ^[a-z] 以小写字母开始
    *  [^0-9] 取反,非数字
    *  [^a-z] 非小写字母
    *  [^0-9a-zA-Z_]   特殊字符
    * 
    *
    *  10:   $ 表示的是以什么结束   [0-9][a-z]$  必须以小写字母结束
    *  ^[0-9][a-z] 相当于是严格模式   "3f2432e"  "4f"
    *
    *
    *  11:  \d 数字中的任意一个,   digit 数字
    *        \D 非数字中的一个
    *  12:  \s 空白符中的一个     Space  空白符号
    *        \S 非空白符
    *   13:  \w 非特殊符号   Word,单词.\w匹配包括下划线的任何单词字符.等价于'[A-Za-z0-9_]'.
    *         \W 特殊符号
    *   \b 单词的边界
    *   "what are you no sha lei"
    *
    *
    *    . 除了\n以外的任意一个单个字符
    *    []  范围
    *    () 分组,提升优先级
    *    | 或者
    *    * 0-多次
    *    + 1-多次
    *    ? 0-1次
    *    {0,} 和*一样
    *    {1,} 和+
    *    {0,1} 和?
    *
    *    \d 数字中的一个
    *    \D 非数字
    *    \s 空白符
    *    \S 非空白符
    *     \W  特殊符号
    *     \w 非特殊符号 _
    *     ^ 取反,以什么开始
    *     $ 以什么结束
    *
    *     \b 单词边界
  
    * */
  </script>

 

42:正则表达式的创建方式

<script>

   //创建正则表达式对象

    //两种:
    /*
    *
    * 1.通过构造函数创建对象
    *
    *
    * 2.字面量的方式创建对象
    *
    *
    * 正则表达式的作用:匹配字符串的
    *
    * */
//   //对象创建完毕---
//    var reg=new RegExp(/\d{5}/);
//   //字符串
//    var str="我的电话是10086";
//   //调用方法验证字符串是否匹配
//    var flag=reg.test(str);
//    console.log(flag);



//   //对象创建完毕---
//   var reg=new RegExp(/\d{5}/);
//   //调用方法验证字符串是否匹配
//   var flag=reg.test("我的电话是10086");
//   console.log(flag);


    //字面量的方式创建正则表达式对象
    var reg=/\d{1,5}/;
    var flag=reg.test("小苏的幸运数字:888");
    console.log(flag);



  </script>

 

 

43:字符创中的正则表达式

<script>
    //正则表达式中:g 表示的是全局模式匹配
    //正则表达式中:i 表示的是忽略大小写
    // match是匹配的意思
    // replace是替换的意思

    
       var str="中国移动:10086,中国联通:10010,中国电信:10000";
       //把里面所有的数字全部显示出来
       var array=str.match(/\d{5}/g);
       console.log(array);


    //
    //    var str = "123123@xx.com,fangfang@valuedopinions.cn 286669312@qq.com 2、emailenglish@emailenglish.englishtown.com 286669312@qq.com...";
    //    var array = str.match(/\w+@\w+\.\w+(\.\w+)?/g);
    //    console.log(array);


    //提取这里的日
    //    var str="2017-11-12";
    //    var array=str.match(/(\d{4})[-](\d{2})[-](\d{2})/g);
    //    //console.log(array);
    //    //正则表达式对象.$3
    //    console.log(RegExp.$3);


    //    var email="shuaiyangtaishuaile@itcast.com.cn";
    //    email.match(/([0-9a-zA-Z_.-]+)[@]([0-9a-zA-Z_-]+)(([.][a-zA-Z]+){1,2})/);
    //    console.log(RegExp.$1);//用户名
    //    console.log(RegExp.$2);//126
    //    console.log(RegExp.$3);//域名


    //    var str="小苏好帅哦,真的是太帅了,帅,就是真帅";
    //    str=str.replace(/帅/g,"猥琐");
    //    console.log(str);

    //    var str="  哦买噶的    ,太幸福了  ";
    //    str=str.trim();
    //    console.log("==="+str+"===");


    //    var str = "  哦买噶的    ,太幸福了  ";
    //    str = str.replace(/\s+/g, "");
    //    console.log("===" + str + "===");


    //所有的h都替换成S
    //    var str="HhpphH";//SSppSS
    //    str=str.replace(/[h]/gi,"S");
    //    console.log(str);


    //    var reg = new RegExp(/[h]/gi);
    //    var str = "HhpphH";//SSppSS
    //    str = str.replace(reg, "S");
    //    console.log(str);

//
//    var str = "中国移动:10086,中国联通:10010,中国电信:10000";
//    //把里面所有的数字全部显示出来
//    //var array = str.match(/\d{5}/g);
//    //正则表达式对象.exec方法传入字符串
//    var reg=/\d{5}/g;
//    //var array=reg.exec(str);
////    console.log(array);
////    console.log(reg.exec(str));
////    console.log(reg.exec(str));
////    console.log(reg.exec(str));
//
//    var result=reg.exec(str);
//    while(result!=null){
//      console.log(result);
//      result=reg.exec(str);
//    }



//    var str = "中国移动:10086,中国联通:10010,中国电信:10000";
//    var reg=/\d{5}/g;
//    //通过正则表达式匹配这个字符串
//    var array=reg.exec(str);
//    console.log(array);
//    console.log(reg.exec(str));
//    console.log(reg.exec(str));
//    console.log(reg.exec(str));//null
//


    var str = "中国移动:10086,中国联通:10010,中国电信:10000";
    var reg=/\d{5}/g;
    //通过正则表达式匹配这个字符串
    var array=reg.exec(str);
    while (array!=null){
      //输出匹配的内容
      console.log(array[0]);
      array=reg.exec(str);
    }

  </script>

 

44:真数组和伪数组

<script>
        //伪数组和数组的区别
        //真数组的长度是可变的
        //伪数组的长度不可变
        //真数组可以使用数组中的方法
        //伪数组不可以使用数组中的方法
        
    
    //    function f1() {
    //      var sum=0;
    //      for(var i=0;i<arguments.length;i++){
    //        sum+=arguments[i];
    //      }
    //      console.log(sum);
    //    }
    //    //arguments得到的是实参的个数及实参的每个值
    //
    //    f1(10,20,30,40);
    
    
    //    function f1() {
    //     var sum=0;
    //      arguments.forEach(function () {
    //
    //      });
    //    }
    //    //arguments得到的是实参的个数及实参的每个值
    //
    //    f1(10,20,30,40);
    
    //    var arr=[10,20,30];
    //    arr.forEach(function () {
    //
    //    });
    
    
    
        var arr=[10,20];
        arr.forEach()
        console.dir(arr);
    
        // 数组实例对象的__proto__----->Array的prototype
    
        //数组
    //    var arr=[10,20,30];
    //    arr[3]=100;
    //    console.log(arr.length);
    //    //对象---假的数组
    //    var obj={
    //      0:10,
    //      1:20,
    //      2:30,
    //      length:3
    //    };
    //
    //    console.log(obj[0]);
    //    console.log(obj[1]);
    //    console.log(obj[2]);
    //    console.log(obj.length);
    //    obj[3]=1000;
    //    console.log(obj[3]);
    //    console.log(obj.length);
    
        //遍历数组
    //    for(var i=0;i<arr.length;i++){
    //      console.log(arr[i]);
    //    }
    //
    //    for(var i=0;i<obj.length;i++){
    //      console.log(obj[i]);
    //    }
    </script>

 


 

4:Vue

1:MVC和MVVM(背诵)

 
前端的主要工作?主要负责MVC中的V这一层;主要工作就是和界面打交道,来制作前端页面效果;

 

2:常见的指令

1:  {{}}    插值表达式   
2:v-cloak  解决插值表达式的闪烁问题。原理是标签的显示隐藏。
3:v-text  用来实现数据。
4:  v-html  用来展示html文本
5:v-bind:   是Vue中,提供用于绑定属性的指令。
   v-bind:可以简写成:
6:v-on  Vue中提供了v-on:事件绑定机制。
  v-on:可以简写成@
 
7:v-model  双向数据绑定。
 v-mdoel可以实现model和view的双向绑定 v-model只能用在表单元素中 。
input(radio, text, address, email....) select  checkbox  textarea 
 
区别:
1:v-text:没有插值表达式闪烁的问题。
2: v-text会覆盖元素内容。但是插值表达式只会修改插值表达式,不会把整个内容覆盖。
 
1:插值表达式
<div id="app">
        <!-- 3:插值表达式  -->
        <p>{{ msg}} </p>
    </div>
   <!-- 2:创建一个vue对象 {}配置对象 几个属性:el:元素 -->
   <script>
       var vm = new Vue ({
        el : '#app',
        data : {
            msg : '欢迎学习Vue' //通过vue提供的指令,去渲染数据,不是通过操作DOM。
        }
   })
   </script>

 

2:实例

<div id="app">
            <p>{{msg}}</p>
            <p v-text="msg"></p>
            <div>{{msg2}}</div>
            <div v-text="msg2"></div>
             <div v-html="msg2"></div>
             <input type="button" value="按钮" v-bind:title="myTitle" v-on:click='show'>
             <!-- <input type="button" value="按钮" v-bind:title="myTitle" v-on:mouseover='show'> -->
    </div>

    

    <script>
        var vm = new Vue({
            el : "#app",
            data : {
                msg : "123",
                msg2: "<h1>我是一个大大的H1标签</h1>",
                myTitle:'这是一个自定义按钮的标题',
            },
            methods:{
                show : function (){
                    alert("Hello")
                }
            }
        })    
        
    </script>

 

3:v-model

 <div id="app">
        <h4>{{msg}}</h4>
        <!-- <input type="text" :value="msg"> -->

        <!-- v-mdoel可以实现model和view的双向绑定 v-model只能用在表单元素中 -->
        <input type="text" v-model="msg">

    </div>

    <script>
        var vm = new Vue({
            el : '#app',
            data : {
                msg : '我的单向数据',
            }, 
            metheds : {

            },
        });
    </script>

 

3:  五大事情修饰符

事件修饰符:
.stop        阻止冒泡
.prevent    阻止默认事件
.capture    添加事件侦听器时使用事件捕获模式
.self       只当事件在该元素本身(比如不是子元素)触发时触发回调
.once       事件只触发一次
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="./lib/vue-2.4.0.js"></script>
  <style>
    .inner {
      height: 150px;
      background-color: darkcyan;
    }

    .outer {
      padding: 40px;
      background-color: red;
    }
  </style>
</head>

<body>
  <div id="app">

    <!-- 使用  .stop  阻止冒泡 -->
    <!-- <div class="inner" @click="div1Handler">
      <input type="button" value="戳他" @click.stop="btnHandler">
    </div> -->

    <!-- 使用 .prevent 阻止默认行为 -->
    <!-- <a href="http://www.baidu.com" @click.prevent="linkClick">有问题,先去百度</a> -->

    <!-- 使用  .capture 实现捕获触发事件的机制 -->
    <!-- <div class="inner" @click.capture="div1Handler">
      <input type="button" value="戳他" @click="btnHandler">
    </div> -->

    <!-- 使用 .self 实现只有点击当前元素时候,才会触发事件处理函数 -->
    <!-- <div class="inner" @click="div1Handler">
      <input type="button" value="戳他" @click="btnHandler">
    </div> -->

    <!-- 使用 .once 只触发一次事件处理函数 -->
    <!-- <a href="http://www.baidu.com" @click.prevent.once="linkClick">有问题,先去百度</a> -->


    <!-- 演示: .stop 和 .self 的区别 -->
    <!-- <div class="outer" @click="div2Handler">
      <div class="inner" @click="div1Handler">
        <input type="button" value="戳他" @click.stop="btnHandler">
      </div>
    </div> -->

    <!-- .self 只会阻止自己身上冒泡行为的触发,并不会真正阻止 冒泡的行为 -->
    <!-- <div class="outer" @click="div2Handler">
      <div class="inner" @click.self="div1Handler">
        <input type="button" value="戳他" @click="btnHandler">
      </div>
    </div> -->

  </div>

  <script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {},
      methods: {
        div1Handler() {
          console.log('这是触发了 inner div 的点击事件')
        },
        btnHandler() {
          console.log('这是触发了 btn 按钮 的点击事件')
        },
        linkClick() {
          console.log('触发了连接的点击事件')
        },
        div2Handler() {
          console.log('这是触发了 outer div 的点击事件')
        }
      }
    });
  </script>
</body>

</html>

 



4:在Vue中使用CSS

1:  使用内联样式

<h1 :style="{color: 'red', 'font-size': '40px'}">这是一个善良的H1</h1>

 

 <div id="app">
    <!-- 对象就是无序键值对的集合 -->

  // 方式一:直接写样式
    <!-- <h1 :style="{color: 'red', 'font-size': '40px'}">这是一个善良的H1</h1>  -->
  // 方式二  一个class
<!-- <h1 :style="styleObj1">这是一个h1</h1> -->
  // 方式三 两个class <h1 :style="[ styleObj1, styleObj2 ]">这是一个h1</h1> </div> <script> // 创建 Vue 实例,得到 ViewModel var vm = new Vue({ el: '#app', data: { styleObj1: { color: 'red', 'font-weight': 200 }, styleObj2: { 'font-style': 'italic' } }, methods: {} }); </script>

 

2:  使用class样式

4中方式:

字符串

字符串拼接

 数组

 对象

<div id="app">
    // 方式一:直接用字符串 空格拼接
<!-- <h1 class="red thin">这是一个很大的h1,大到你无法想象 </h1> -->

    // 方式二:数组的方式:字符串数组 <!-- <h1 :class="['thin', 'red']">这是一个很大的h1,大到你无法想象 </h1> -->
  
    // 方式三:对象方式 <h1 :class="{red:true, thin:true, active:true}">这是一个很大的h1,大到你无法想象 </h1>

    // 方式4:一个class 字符串 <h1 :class="classobj">这是一个很大的h1,大到你无法想象 </h1> </div> <script> var vm = new Vue({ el : "#app", data : { classobj : {red:true, thin:true, active:true}, }, methodes : { }, }); </script>

 

 

5:v-for遍历

1:遍历数组
 
 
<div id="app">
    <!-- <p>{{list[0]}}</p>
    <p>{{list[1]}}</p>
    <p>{{list[2]}}</p>
    <p>{{list[3]}}</p>
    <p>{{list[4]}}</p> -->

    <p v-for="(item, i) in list">索引值:{{i}} --- 每一项:{{item}}</p>

  </div>

  <script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        list: [1, 2, 3, 4, 5, 6]
      },
      methods: {}
    });
  </script>

 

2:遍历对象数组
<div id="app">
    <p v-for="(user, i) in list">Id:{{ user.id }} --- 名字:{{ user.name }} --- 索引:{{i}}</p>
  </div>

  <script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        list: [
          { id: 1, name: 'zs1' },
          { id: 2, name: 'zs2' },
          { id: 3, name: 'zs3' },
          { id: 4, name: 'zs4' }
        ]
      },
      methods: {}
    });
  </script>

 

3:遍历对象
key属性添加,如果出现错误的话,key的值是字符串或者数值。
<div id="app">
    <!-- 注意:在遍历对象身上的键值对的时候, 除了 有  val  key  ,在第三个位置还有 一个 索引  -->
    <p v-for="(val, key, i) in user">值是: {{ val }} --- 键是: {{key}} -- 索引: {{i}}</p>
  </div>

  <script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        user: {
          id: 1,
          name: '托尼·屎大颗',
          gender: ''
        }
      },
      methods: {}
    });
  </script>

 

 
4:遍历数字
 
<div id="app">
    <!-- in 后面我们放过  普通数组,对象数组,对象, 还可以放数字 -->
    <!-- 注意:如果使用 v-for 迭代数字的话,前面的 count 值从 1 开始 -->
    <p v-for="count in 10">这是第 {{ count }} 次循环</p>
  </div>

  <script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {},
      methods: {}
    });
  </script>

 

7:v-if和v-show指令 

 v-if的特点是:每次都会重新删除或者创建元素
 v-show的特点是:每次不会进行DOM的删除或者创建,只是切换元素的状态。
性能上:v-if有较高的性能消耗 ,v-show有较高的初始的渲染消耗
<div id="app">

    <!-- <input type="button" value="toggle" @click="toggle"> -->
    <input type="button" value="toggle" @click="flag=!flag">

    <!-- v-if 的特点:每次都会重新删除或创建元素 -->
    <!-- v-show 的特点: 每次不会重新进行DOM的删除和创建操作,只是切换了元素的 display:none 样式 -->

    <!-- v-if 有较高的切换性能消耗 -->
    <!-- v-show 有较高的初始渲染消耗 -->

    <!-- 如果元素涉及到频繁的切换,最好不要使用 v-if, 而是推荐使用 v-show -->
    <!-- 如果元素可能永远也不会被显示出来被用户看到,则推荐使用 v-if -->
    <h3 v-if="flag">这是用v-if控制的元素</h3>
    <h3 v-show="flag">这是用v-show控制的元素</h3>

  </div>

  <script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        flag: false
      },
      methods: {
        /* toggle() {
          this.flag = !this.flag
        } */
      }
    });
  </script>

 

8:  过滤器

1:全局过滤器

<div id="app">
    <p>{{ msg | msgFormat('疯狂+1', '123') | test }}</p>
  </div>

  <script>
    // 定义一个 Vue 全局的过滤器,名字叫做  msgFormat
    Vue.filter('msgFormat', function (msg, arg, arg2) {
      // 字符串的  replace 方法,第一个参数,除了可写一个 字符串之外,还可以定义一个正则
      return msg.replace(/单纯/g, arg + arg2)
    })

    Vue.filter('test', function (msg) {
      return msg + '========'
    })


    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        msg: '曾经,我也是一个单纯的少年,单纯的我,傻傻的问,谁是世界上最单纯的男人'
      },
      methods: {}
    });
  </script>

 

2:局部过滤器

<div id="app">
        <!-- 1:全局过滤器 -->
        <h1>{{ msg | appendStr("全局过滤器")}}</h1>
        <!-- 2:私有过滤器 -->
        <h1>{{ msg | appendEndStr("全局过滤器")}}</h1>
    </div>
 <script>

        // 1:全局过滤器
        Vue.filter("appendStr", function (msg, arg) {  
            return msg + arg;
        });

var vm = new Vue({
            el : "#app",
            data : {
                msg : "原始的消息",
            },
            methods : {

            },

            // 2:私有过滤器
            filters : {
                appendEndStr : function (msg, arg) {
                    return msg + arg + "~~~~";
                }
                ,
            },

       
        });
    
    </script>

9: 自定义指令

<div id="app">
        <!-- 自定义指令 -->
        <!--  传的参数是字符串,如果不是字符串的话,就是变量,。去data中找 -->
        <input type="text" v-focus v-color="'red'">
        <p v-fontweight="'red'">我是一个p标签</p>
        <p>我是一个p标签</p>
        <h1>我是一个h1标签</h1>
        <h1 v-fontweight="'red'">我是一个h1标签</h1>
    </div>

    <script>

        //  第一个参数是指令的名字,第二个参数是对象
     // 1:自定义全局指令
Vue.directive("focus", { bind : function (el) { //进行一些样式的操作 // el.style.color = "red"; }, inserted : function (el) { // 进行一些js操作 el.focus(); }, updated : function (el) { }, }); // 自定义样式指令 Vue.directive("color", { bind : function (el, binding) { el.style.color = binding.value; }, inserted : function (el) { }, updated : function (el) { }, }); var vm = new Vue({ el : "#app", data : { }, methods : { }, // 2: 自定义私有的指令 directives : { "fontweight" : { bind : function (el , binding) { el.style.color = binding.value; } }, }, }); </script>

 

10:Vue的生命周期

 

  <script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        msg: 'ok'
      },
      methods: {
        show() {
          console.log('执行了show方法')
        }
      },
      beforeCreate() { // 1:这是我们遇到的第一个生命周期函数,表示实例完全被创建出来之前,会执行它
        // console.log(this.msg)
        // this.show()
        // 注意: 在 beforeCreate 生命周期函数执行的时候,data 和 methods 中的 数据都还没有没初始化
      },
      
      created() { // 2:这是遇到的第二个生命周期函数
        // console.log(this.msg)
        // this.show()
        //  在 created 中,data 和 methods 都已经被初始化好了!
        // 如果要调用 methods 中的方法,或者操作 data 中的数据,最早,只能在 created 中操作
      },

      beforeMount() { // 3: 这是遇到的第3个生命周期函数,表示 模板已经在内存中编辑完成了,但是尚未把 模板渲染到 页面中
        // console.log(document.getElementById('h3').innerText)
        // 在 beforeMount 执行的时候,页面中的元素,还没有被真正替换过来,只是之前写的一些模板字符串
      },

      mounted() { // 4: 这是遇到的第4个生命周期函数,表示,内存中的模板,已经真实的挂载到了页面中,用户已经可以看到渲染好的页面了
        // console.log(document.getElementById('h3').innerText)
        // 注意: mounted 是 实例创建期间的最后一个生命周期函数,当执行完 mounted 就表示,实例已经被完全创建好了,此时,如果没有其它操作的话,这个实例,就静静的 躺在我们的内存中,一动不动
      },


      // 5: 接下来的是运行中的两个事件
      beforeUpdate() { // 这时候,表示 我们的界面还没有被更新【数据被更新了吗?  数据肯定被更新了】
        /* console.log('界面上元素的内容:' + document.getElementById('h3').innerText)
        console.log('data 中的 msg 数据是:' + this.msg) */
        // 得出结论: 当执行 beforeUpdate 的时候,页面中的显示的数据,还是旧的,此时 data 数据是最新的,页面尚未和 最新的数据保持同步
      },

      // 6:
      updated() {
        console.log('界面上元素的内容:' + document.getElementById('h3').innerText)
        console.log('data 中的 msg 数据是:' + this.msg)
        // updated 事件执行的时候,页面和 data 数据已经保持同步了,都是最新的
      }
    });
  </script>

 

7:当执行beforeDestory钩子函数的时候,Vue实例从运行阶段进入到销毁阶段
当执行beforeDestory钩子函数的时候,Vue实例身上所有的data和methods和过滤器和指令都处于可以利用的状态。此时还没有真正的销毁。
 
8:当执行Destoryed钩子函数的时候,Vue实例身上所有的data和methods和过滤器和指令都处于不利用的状态。


11:按键修饰符号

  • .enter
  • .tab
  • .delete (捕获“删除”和“退格”键)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

 自定义全局键盘码:

Vue.config.keycodes.f2 = 113;


12:Vue动画

1:transition动画



<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="./lib/vue-2.4.0.js"></script>
  <!-- 2. 自定义两组样式,来控制 transition 内部的元素实现动画 -->
  <style>
    /* v-enter 【这是一个时间点】 是进入之前,元素的起始状态,此时还没有开始进入 */
    /* v-leave-to 【这是一个时间点】 是动画离开之后,离开的终止状态,此时,元素 动画已经结束了 */
    .v-enter,
    .v-leave-to {
      opacity: 0;
      transform: translateX(150px);
    }

    /* v-enter-active 【入场动画的时间段】 */
    /* v-leave-active 【离场动画的时间段】 */
    .v-enter-active,
    .v-leave-active{
      transition: all 0.8s ease;
    }
  </style>
</head>

<body>
  <div id="app">
    <input type="button" value="toggle" @click="flag=!flag">
    <!-- 需求: 点击按钮,让 h3 显示,再点击,让 h3 隐藏 -->
    <!-- 1. 使用 transition 元素,把 需要被动画控制的元素,包裹起来 -->
    <!-- transition 元素,是 Vue 官方提供的 -->
    <transition>
      <h3 v-if="flag">这是一个H3</h3>
    </transition>
  </div>

  <script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        flag: false
      },
      methods: {}
    });
  </script>
</body>

</html>

 

2:animate.css  动画

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="./lib/vue-2.4.0.js"></script>
  <link rel="stylesheet" href="./lib/animate.css">
  <!-- 入场 bounceIn    离场 bounceOut -->
</head>

<body>
  <div id="app">
    <input type="button" value="toggle" @click="flag=!flag">
    <!-- 需求: 点击按钮,让 h3 显示,再点击,让 h3 隐藏 -->
    <!-- <transition enter-active-class="animated bounceIn" leave-active-class="animated bounceOut">
      <h3 v-if="flag">这是一个H3</h3>
    </transition> -->

    <!-- 使用 :duration="毫秒值" 来统一设置 入场 和 离场 时候的动画时长 -->
    <!-- <transition enter-active-class="bounceIn" leave-active-class="bounceOut" :duration="200">
      <h3 v-if="flag" class="animated">这是一个H3</h3>
    </transition> -->

    <!-- 使用  :duration="{ enter: 200, leave: 400 }"  来分别设置 入场的时长 和 离场的时长  -->
    <transition 
    enter-active-class="bounceIn" 
    leave-active-class="bounceOut" 
    :duration="{ enter: 200, leave: 400 }">
      <h3 v-if="flag" class="animated">这是一个H3</h3>
    </transition> 
  </div>

  <script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        flag: false
      },
      methods: {}
    });
  </script>
</body>

</html>

 

3:钩子函数动画

 

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="./lib/vue-2.4.0.js"></script>
  <style>
    .ball {
      width: 15px;
      height: 15px;
      border-radius: 50%;
      background-color: red;
    }
  </style>
</head>

<body>
  <div id="app">
    <input type="button" value="快到碗里来" @click="flag=!flag">
    <!-- 1. 使用 transition 元素把 小球包裹起来 -->
    <transition
      @before-enter="beforeEnter"
      @enter="enter"
      @after-enter="afterEnter">
      <div class="ball" v-show="flag"></div>
    </transition>
  </div>

  <script>

    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        flag: false
      },
      methods: {
        // 注意: 动画钩子函数的第一个参数:el,表示 要执行动画的那个DOM元素,是个原生的 JS DOM对象
        // 大家可以认为 , el 是通过 document.getElementById('') 方式获取到的原生JS DOM对象
        beforeEnter(el){
          // beforeEnter 表示动画入场之前,此时,动画尚未开始,可以 在 beforeEnter 中,设置元素开始动画之前的起始样式
          // 设置小球开始动画之前的,起始位置
          el.style.transform = "translate(0, 0)"
        },
        enter(el, done){
          // 这句话,没有实际的作用,但是,如果不写,出不来动画效果;
          // 可以认为 el.offsetWidth 会强制动画刷新
          el.offsetWidth
          // enter 表示动画 开始之后的样式,这里,可以设置小球完成动画之后的,结束状态
          el.style.transform = "translate(150px, 450px)"
          el.style.transition = 'all 1s ease'

          // 这里的 done, 起始就是 afterEnter 这个函数,也就是说:done 是 afterEnter 函数的引用
          done()
        },
        afterEnter(el){
          // 动画完成之后,会调用 afterEnter
          // console.log('ok')
          this.flag = !this.flag
        }
      }
    });
  </script>
</body>

</html>

 

13:组件化开发

1:全局组件 extend

<div id="app">
    <!-- 如果要使用组件,直接,把组件的名称,以 HTML 标签的形式,引入到页面中,即可 -->
    <mycom1></mycom1>
  </div>

  <script>
    // 1.1 使用 Vue.extend 来创建全局的Vue组件
    // var com1 = Vue.extend({
    //   template: '<h3>这是使用 Vue.extend 创建的组件</h3>' // 通过 template 属性,指定了组件要展示的HTML结构
    // })
    // 1.2 使用 Vue.component('组件的名称', 创建出来的组件模板对象)
    // Vue.component('myCom1', com1)
    // 如果使用 Vue.component 定义全局组件的时候,组件名称使用了 驼峰命名,则在引用组件的时候,需要把 大写的驼峰改为小写的字母,同时,两个单词之前,使用 - 链接;
    // 如果不使用驼峰,则直接拿名称来使用即可;
    // Vue.component('mycom1', com1)

    // Vue.component 第一个参数:组件的名称,将来在引用组件的时候,就是一个 标签形式 来引入 它的
    // 第二个参数: Vue.extend 创建的组件  ,其中 template 就是组件将来要展示的HTML内容
    Vue.component('mycom1', Vue.extend({
      template: '<h3>这是使用 Vue.extend 创建的组件</h3>'
    }))


    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {},
      methods: {}
    });
  </script>

 

2:  对象模式

<div id="app">
    <!-- 还是使用 标签形式,引入自己的组件 -->
    <mycom2></mycom2>
  </div>

  <script>
    // 注意:不论是哪种方式创建出来的组件,组件的 template 属性指向的模板内容,必须有且只能有唯一的一个根元素
    Vue.component('mycom2', {
      template: '<div><h3>这是直接使用 Vue.component 创建出来的组件</h3><span>123</span></div>'
    })

    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {},
      methods: {}
    });
  </script>


3: 模板创建组件
<div id="app">
        <my-custom-com3></my-custom-com3>
    </div>

    <template id="com3">
        <div>
            <h1>这是通过template标签创建的组件</h1>
        </div>
    </template>
    <script>
     // 1:全局创建组件
        // Vue.component("my-custom-com3", {
        //     template : "#com3",
        // })
        var vm = new Vue({
            el : "#app",

            data : {

            },

            methods : {

            },

            filters : {

            },

            directives : {

            },
            components: { // 2:定义实例内部私有组件的
                myCustomCom3: {
                    template: '#com3'
        }
      },


        });
    
    </script>

 

14:组件中的数据和方法

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="./lib/vue-2.4.0.js"></script>
</head>
<body>
    <div id="app">
        <my-com></my-com>

    </div>

    <template id="tem">
        <h1>{{msg}}</h1>
    </template>

    <script>
        Vue.component("my-com", {
            template : "#tem",
            data : function () {  
                return {
                    msg : "组件中的数据",
                };
            },
        });
        var vm = new Vue({
            el : "#app",
        });
    </script>
</body>
</html>

 

15:组件之间的切换

1:flag切换

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>

<body>
  <div id="app">
    <a href="" @click.prevent="flag=true">登录</a>
    <a href="" @click.prevent="flag=false">注册</a>

    <login v-if="flag"></login>
    <register v-else="flag"></register>

  </div>

  <script>
    Vue.component('login', {
      template: '<h3>登录组件</h3>'
    })

    Vue.component('register', {
      template: '<h3>注册组件</h3>'
    })

    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        flag: false
      },
      methods: {}
    });
  </script>
</body>

</html>

 

 

2:v-bind:is

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>

<body>
  <div id="app">
    <a href="" @click.prevent="comName='login'">登录</a>
    <a href="" @click.prevent="comName='register'">注册</a>

    <!-- Vue提供了 component ,来展示对应名称的组件 -->
    <!-- component 是一个占位符, :is 属性,可以用来指定要展示的组件的名称 -->
    <component :is="comName"></component>

    <!-- 总结:当前学习了几个 Vue 提供的标签了??? -->
    <!-- component,  template,  transition,  transitionGroup  -->

  </div>

  <script>
    // 组件名称是 字符串
    Vue.component('login', {
      template: '<h3>登录组件</h3>'
    })

    Vue.component('register', {
      template: '<h3>注册组件</h3>'
    })

    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        comName: 'login' // 当前 component 中的 :is 绑定的组件的名称
      },
      methods: {}
    });
  </script>
</body>

</html>

 

16:父组件向子组件传值,通过属性绑定的方式

1.1:父组件声明数据

1.2:子组件声明属性

1.3:子组件引用的使用绑定属性

<div id="app">
    <!-- 3:父组件,可以在引用子组件的时候, 通过 属性绑定(v-bind:) 的形式, 把 需要传递给 子组件的数据,以属性绑定的形式,传递到子组件内部,供子组件使用 -->
    <com1 v-bind:parentmsg="msg"></com1>
  </div>

  <script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        // 1:父组件声明属性 msg
        msg: '123 啊-父组件中的数据'
      },
      methods: {},

      components: {
        // 结论:经过演示,发现,子组件中,默认无法访问到 父组件中的 data 上的数据 和 methods 中的方法
        com1: {
          data() { // 注意: 子组件中的 data 数据,并不是通过 父组件传递过来的,而是子组件自身私有的,比如: 子组件通过 Ajax ,请求回来的数据,都可以放到 data 身上;
            // data 上的数据,都是可读可写的;
            return {
              title: '123',
              content: 'qqq'
            }
          },
          template: '<h1 @click="change">这是子组件 --- {{ parentmsg }}</h1>',

          // 2:子组件声明传过来的属性  parentmsg
          // 注意: 组件中的 所有 props 中的数据,都是通过 父组件传递给子组件的
          // props 中的数据,都是只读的,无法重新赋值
          props: ['parentmsg'], // 把父组件传递过来的 parentmsg 属性,先在 props 数组中,定义一下,这样,才能使用这个数据
          directives: {},
          filters: {},
          components: {},
          methods: {
            change() {
              this.parentmsg = '被修改了'
            }
          }
        }
      }
    });
  </script>

 

17:父组件向子组件传递事件--实现向父组件传值

<body>
  <div id="app">
    <!-- 2:父组件向子组件 传递 方法,使用的是 事件绑定机制; v-on, 当我们自定义了 一个 事件属性之后,那么,子组件就能够,通过某些方式,来调用 传递进去的 这个 方法了 -->
    <com2 @func="show"></com2>
  </div>

  <template id="tmpl">
    <div>
      <h1>这是 子组件</h1>
      <input type="button" value="这是子组件中的按钮 - 点击它,触发 父组件传递过来的 func 方法" @click="myclick">
    </div>
  </template>

  <script>

    // 定义了一个字面量类型的 组件模板对象
    var com2 = {
      template: '#tmpl', // 通过指定了一个 Id, 表示 说,要去加载 这个指定Id的 template 元素中的内容,当作 组件的HTML结构
      data() {
        return {
          sonmsg: { name: '小头儿子', age: 6 }
        }
      },
      methods: {
        myclick() {
          //3: 当点击子组件的按钮的时候,如何 拿到 父组件传递过来的 func 方法,并调用这个方法???
          //  emit 英文原意: 是触发,调用、发射的意思
          // this.$emit('func123', 123, 456)

          this.$emit('func', this.sonmsg)
        }
      }
    }


    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        datamsgFormSon: null
      },
      methods: {
        // 1:声明方法
        show(data) {
          // console.log('调用了父组件身上的 show 方法: --- ' + data)
          // console.log(data);
          this.datamsgFormSon = data;
        }
      },

      components: {
        com2
        // com2: com2
      }
    });
  </script>
</body>

 

18:  ref获取dom元素和组件

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>

<body>
  <div id="app">
    <input type="button" value="获取元素" @click="getElement" ref="mybtn">

    <h3 id="myh3" ref="myh3">哈哈哈, 今天天气太好了!!!</h3>

    <hr>

    <login ref="mylogin"></login>
  </div>

  <script>

    var login = {
      template: '<h1>登录组件</h1>',
      data() {
        return {
          msg: 'son msg'
        }
      },
      methods: {
        show() {
          console.log('调用了子组件的方法')
        }
      }
    }

    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {},
      methods: {
        getElement() {
          console.log(document.getElementById('myh3').innerText);

          //  ref  是 英文单词 【reference】   值类型 和 引用类型  referenceError
          console.log(this.$refs.myh3.innerText);

          console.log(this.$refs.mylogin.msg);
          this.$refs.mylogin.show();
        }
      },
      components: {
        login
      }
    });
  </script>
</body>

</html>

 

19:路由6部曲

1. 安装 vue-router 路由模块
2. 创建一个路由对象
3:路由匹配规则
4: 将路由规则对象,注册到 vm 实例上,用来监听 URL 地址的变化,然后展示对应的组件
5:router-link 默认渲染
6:展示组件位置:
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="./lib/vue-2.4.0.js"></script>
  <!-- 1. 安装 vue-router 路由模块 -->
  <script src="./lib/vue-router-3.0.1.js"></script>

</head>

<body>
  <div id="app">

      <!-- router-link 默认渲染为一个a 标签 -->
    <!-- 5: 填写a标签 -->
    <router-link to="/login" tag="span">登录</router-link>
    <router-link to="/register">注册</router-link>


    <!-- 6:展示组件位置:
      这是 vue-router 提供的元素,专门用来 当作占位符的,将来,路由规则,匹配到的组件,就会展示到这个 router-view 中去 -->
    <!-- 所以: 我们可以把 router-view 认为是一个占位符 -->
      <router-view></router-view>

  </div>

  <script>
    // 组件的模板对象
    var login = {
      template: '<h1>登录组件</h1>'
    }

    var register = {
      template: '<h1>注册组件</h1>'
    }


    /*  Vue.component('login', {
       template: '<h1>登录组件</h1>'
     }) */

    // 2. 创建一个路由对象, 当 导入 vue-router 包之后,在 window 全局对象中,就有了一个 路由的构造函数,叫做 VueRouter
    // 在 new 路由对象的时候,可以为 构造函数,传递一个配置对象
    var routerObj = new VueRouter({
      // route // 这个配置对象中的 route 表示 【路由匹配规则】 的意思
      routes: [ // 3:路由匹配规则 
        // 每个路由规则,都是一个对象,这个规则对象,身上,有两个必须的属性:
        //  属性1 是 path, 表示监听 哪个路由链接地址;
        //  属性2 是 component, 表示,如果 路由是前面匹配到的 path ,则展示 component 属性对应的那个组件
        // 注意: component 的属性值,必须是一个 组件的模板对象, 不能是 组件的引用名称;
        // { path: '/', component: login },
        { path: '/', redirect: '/login' }, // 这里的 redirect 和 Node 中的 redirect 完全是两码事
        { path: '/login', component: login },
        { path: '/register', component: register }
      ],
      linkActiveClass: 'myactive'
    })

    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {},
      methods: {},
      router: routerObj, // 4: 将路由规则对象,注册到 vm 实例上,用来监听 URL 地址的变化,然后展示对应的组件
    });
  </script>
</body>

</html>

 

 

20:路由传递参数

1:路径传递参数

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="./lib/vue-2.4.0.js"></script>
  <script src="./lib/vue-router-3.0.1.js"></script>
</head>

<body>
  <div id="app">

    <!-- 如果在路由中,使用 查询字符串,给路由传递参数,则 不需要修改 路由规则的 path 属性 -->
    <router-link to="/login?id=10&name=zs">登录</router-link>
    <router-link to="/register">注册</router-link>

    <router-view></router-view>

  </div>

  <script>

    var login = {
      template: '<h1>登录 --- {{ $route.query.id }} --- {{ $route.query.name }}</h1>',
      data(){
        return {
          msg: '123'
        }
      },
      created(){ // 组件的生命周期钩子函数
        console.log(this.$route)
        console.log(this.$route.query.id)
      }
    }

    var register = {
      template: '<h1>注册</h1>'
    }

    var router = new VueRouter({
      routes: [
        { path: '/login', component: login },
        { path: '/register', component: register }
      ]
    })

    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {},
      methods: {},
      // router: router
      router
    });
  </script>
</body>

</html>

2:配置传参
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="./lib/vue-2.4.0.js"></script>
  <script src="./lib/vue-router-3.0.1.js"></script>
</head>

<body>
  <div id="app">

    <!-- 如果在路由中,使用 查询字符串,给路由传递参数,则 不需要修改 路由规则的 path 属性 -->
    <router-link to="/login/12/ls">登录</router-link>
    <router-link to="/register">注册</router-link>

    <router-view></router-view>

  </div>

  <script>

    var login = {
      template: '<h1>登录 --- {{ $route.params.id }} --- {{ $route.params.name }}</h1>',
      data(){
        return {
          msg: '123'
        }
      },
      created(){ // 组件的生命周期钩子函数
        console.log(this.$route.params.id)
      }
    }

    var register = {
      template: '<h1>注册</h1>'
    }

    var router = new VueRouter({
      routes: [
        { path: '/login/:id/:name', component: login },
        { path: '/register', component: register }
      ]
    })

    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {},
      methods: {},
      // router: router
      router
    });
  </script>
</body>

</html>

 


21:路由嵌套
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="./lib/vue-2.4.0.js"></script>
  <script src="./lib/vue-router-3.0.1.js"></script>
</head>

<body>
  <div id="app">

    <router-link to="/account">Account</router-link>

    <router-view></router-view>

  </div>

  <template id="tmpl">
    <div>
      <h1>这是 Account 组件</h1>

      <router-link to="/account/login">登录</router-link>
      <router-link to="/account/register">注册</router-link>

      <router-view></router-view>
    </div>
  </template>

  <script>

    // 组件的模板对象
    var account = {
      template: '#tmpl'
    }

    var login = {
      template: '<h3>登录</h3>'
    }

    var register = {
      template: '<h3>注册</h3>'
    }

    var router = new VueRouter({
      routes: [
        {
          path: '/account',
          component: account,
          // 使用 children 属性,实现子路由,同时,子路由的 path 前面,不要带 / ,否则永远以根路径开始请求,这样不方便我们用户去理解URL地址
          children: [
            { path: 'login', component: login },
            { path: 'register', component: register }
          ]
        }
        // { path: '/account/login', component: login },
        // { path: '/account/register', component: register }
      ]
    })

    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {},
      methods: {},
      router
    });
  </script>
</body>

</html>

 

22:watch

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="./lib/vue-2.4.0.js"></script>
  <!-- 1. 导入包 -->
  <script src="./lib/vue-router-3.0.1.js"></script>
</head>

<body>
  <div id="app">
    <router-link to="/login">登录</router-link>
    <router-link to="/register">注册</router-link>

    <!-- 容器 -->
    <router-view></router-view>

  </div>

  <script>
    // 2. 创建子组件
    var login = {
      template: '<h3>这是登录子组件,这个组件是 奔波霸 开发的。</h3>'
    }

    var register = {
      template: '<h3>这是注册子组件,这个组件是 霸波奔 开发的。</h3>'
    }

    // 3. 创建一个路由对象
    var router = new VueRouter({
      routes: [ // 路由规则数组
        { path: '/', redirect: '/login' },
        { path: '/login', component: login },
        { path: '/register', component: register }
      ],
      linkActiveClass: 'myactive' // 和激活相关的类
    })

    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {},
      methods: {},
      // router: router
      router,
      watch: {
        //  this.$route.path
        '$route.path': function (newVal, oldVal) {
          // console.log(newVal + ' --- ' + oldVal)
          if (newVal === '/login') {
            console.log('欢迎进入登录页面')
          } else if (newVal === '/register') {
            console.log('欢迎进入注册页面')
          }
        }
      }
    });
  </script>
</body>

</html>

 



5:webpackage

1:在网页中会引用哪些常见的静态资源?

JS
 - .js  .jsx  .coffee  .ts(TypeScript  类 C# 语言)
 
 CSS
 - .css  .less   .sass  .scss
 
 Images
 - .jpg   .png   .gif   .bmp   .svg
 
 字体文件(Fonts)
 - .svg   .ttf   .eot   .woff   .woff2
 
模板文件
 - .ejs   .jade  .vue【这是在webpack中定义组件的方式,推荐这么用】


2: 什么是webpack?

webpack 是前端的一个项目构建工具,它是基于 Node.js 开发出来的一个前端工具;
 经过刚才的演示,Webpack 可以做什么事情???
 1. webpack 能够处理 JS 文件的互相依赖关系;
2. webpack 能够处理JS的兼容问题,把 高级的、浏览器不是别的语法,转为 低级的,浏览器能正常识别的语法

刚才运行的命令格式:    webpack  要打包的文件的路径  打包好的输出文件的路径
 
 

3:如何完美实现上述的2种解决方案

1. 使用Gulp, 是基于 task 任务的;
2. 使用Webpack, 是基于整个项目进行构建的;
+ 借助于webpack这个前端自动化构建工具,可以完美实现资源的合并、打包、压缩、混淆等诸多功能。
+ 根据官网的图片介绍webpack打包的过程
+ [webpack官网](http://webpack.github.io/)


4:webpack安装的两种方式

1. 运行`npm i webpack -g`全局安装webpack,这样就能在全局使用webpack的命令
2. 在项目根目录中运行`npm i webpack --save-dev`安装到项目依赖中
 
 

5:创建你一个webpack工程

1:用npm init -y 创建package.json 配置工程,拿到项目的第一步骤是用包管理工具管理起来。npm
2:创建src和dist目录
3:在src文件夹下面。创建js文件夹、css文件夹、images文件夹、创建index.html、main.js、index.js
 
4:添加mode到script标签中(package.json文件中)
    "dev":"webpack --mode development",
    "bulid":"webapck --mode production"
5:npm run dev   此时加载的bundle.js是在本地中
   可以使用  webpack ./src/main.js -o ./dist/bundle.js ,但是报黄色的警告,所以:用npm run dev来解决
npm run 其实执行了package.json中的script脚本
 
6: 配置入口和出口函数,
  直接写webpack就可以打包。
const path = require('path')

//  向外暴露一个配置对象

module.exports = {
    // 1:入口,表示要使用webpack 打包哪个文件。
    entry: path.join(__dirname, './src/main.js'),
    output : {
        // 2:输出文件的相关配置
        path: path.join(__dirname, './dist'),  // 指定打包好的文件的目标
        filename: 'bundle.js' // 指定文件的名字

    },

}
 
7:使用webpack-dev-server这个工具来自动打包编译的功能
//1.运行cnpm i webpack-dev-server -D   来自动打包编译
//2: webpack-dev-server 依赖webpack包,所以需要一起安装。
cnpm i webpack -D
cnpm i webpack-cli -D
 
cnpm i webpack-dev-server webpack webpack-cli -D
 
2: webpack-dev-server --open --port 3000 --contentBase src
修改完,package.json之后,需要重新运行
--open,自动打开游览器
--port 修改端口号
--contentBase src  修改根路径
 
此时:bundle.js是在内存中,html在物理磁盘中
 

8:html-webpack-plugin 把html放到内存中

可以自动创建一个script标签,自动把打包好的 bundle.js 追加到页面中去
 
cnpm i html-webpack-plugin -D
 

9: 处理样式文件

cnpm i style-loader css-loader -D     处理css文件
cnpm i less-loader less -D          处理less文件
cnpm i sass-loader node-sass  -D  cnpm i sass fibers -D      处理scss文件
cnpm i sass-loader node-sass  sass fibers -D
 

10:处理url路径、图片、字体库

cnpm i url-loader file-loader -D
 

11:安装babel

// 通过 Babel ,可以帮我们将 高级的语法转换为 低级的语法
// 1. 在 webpack 中,可以运行如下两套 命令,安装两套包,去安装 Babel 相关的loader功能:
// 1.1 第一套包: cnpm i babel-core babel-loader babel-plugin-transform-runtime -D
cnpm i @babel/core -D
// 1.2 第二套包: cnpm i babel-preset-env babel-preset-stage-0 -D
// 2. 打开 webpack 的配置文件,在 module 节点下的 rules 数组中,添加一个 新的 匹配规则:
// 2.1 { test:/\.js$/, use: 'babel-loader', exclude:/node_modules/ }
// 2.2 注意: 在配置 babel 的 loader规则的时候,必须 把 node_modules 目录,通过 exclude 选项排除掉:原因有俩:
// 2.2.1 如果 不排除 node_modules, 则Babel 会把 node_modules 中所有的 第三方 JS 文件,都打包编译,这样,会非常消耗CPU,同时,打包速度非常慢;
// 2.2.2 哪怕,最终,Babel 把 所有 node_modules 中的JS转换完毕了,但是,项目也无法正常运行!
// 3. 在项目的 根目录中,新建一个 叫做 .babelrc  的Babel 配置文件,这个配置文件,属于JSON格式,所以,在写 .babelrc 配置的时候,必须符合JSON语法规范: 不能写注释,字符串必须用双引号
// 3.1 在 .babelrc 写如下的配置:  大家可以把 preset 翻译成 【语法】 的意思
  {
 "presets": ["env", "stage-0"],
 "plugins": ["transform-runtime"]
     }
// 4. 了解: 目前,我们安装的 babel-preset-env, 是比较新的ES语法, 之前, 我们安装的是 babel-preset-es2015, 现在,出了一个更新的 语法插件,叫做 babel-preset-env ,它包含了 所有的 和 es***相关的语法
 
/********************/
上面的做法是 Babel^6x 版本的使用方法,babel在2018年9月份升级了一个大的版本 Babel 7.x,语法有了很大的变动,所以我上面运行的指令已经被out了,必须使用新语法,如下:
新命令如下适合 Babel 7.x和webpack 4 搭配:
  • 安装babel插件
    •   运行 cnpm i @babel/core babel-loader @babel/plugin-transform-runtime -D  转换工具
    •   运行 cnpm i @babel/preset-env @babel/preset-stage-0 -D                       语法
  • 安装能够识别转换jsx语法的包 babel-preset-react
    •   运行 cnpm i @babel/preset-react -D
  • 执行命令:cnpm i @babel/plugin-proposal-class-properties -D
  • 执行命令:cnpm i @babel/runtime -D
  • 添加 .babelrc 配置文件:

 

最后在 webpack.config.js 中配置上:

{ test:/\.js$/, use: 'babel-loader', exclude: /node_modules/ } //配置 babel 转化ES6 语法
/********************/
 

12:安装vue

1:  npm i vue -S

[Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.

解决办法:

// 在webpack 中尝试使用 Vue:
// 注意: 在 webpack 中, 使用 import Vue from 'vue' 导入的 Vue 构造函数,功能不完整,只提供了 runtime-only 的方式,并没有提供 像网页中那样的使用方式;
我们用script标签导入的vue是全新的版本。

 解决办法:

1:修改引用规则。
 import Vue from '../node_modules/vue/dist/vue.js'
// 回顾 包的查找规则:
// 1. 找 项目根目录中有没有 node_modules 的文件夹
// 2. 在 node_modules 中 根据包名,找对应的 vue 文件夹
// 3. 在 vue 文件夹中,找 一个叫做 package.json 的包配置文件
// 4. 在 package.json 文件中,查找 一个 main 属性【main属性指定了这个包在被加载时候,的入口文件】

 2:直接修改 main 属性

3:导入vue,在webpack.config.js中修改引用指向 

 

2:npm i vue-loader vue-template-compiler -D
 
3:vue-loader把vue文件中的template  script stype文件统一成最终的模板。最后给组件用。

 

 13:路由

npm i vue-router -S

1:导包:

import VueRouter from 'vue-router'
 

2:绑定路由对象

Vue.use(VueRouter);
 
3:创建路由对象
var router = new VueRouter({
  routes: [
    {path: '/account', component: account},
    {path: '/goodslist', component:goodslist}
  ],
});
 
4:挂在路由实例中
 
5:显示在界面中
<router-link to="/account">Account</router-link>
 <router-link to="/goodslist">Goodslist</router-link>

  <router-view></router-view>




6:常见的Vue命令

1:全局安装

1:npm i webpack -g           全局安装webpack。
 

2:保存到项目中  -S

2:npm i webpack --save-dev     安装到项目依赖中。
3:cnpm i jquery -S          安装jquery。
4:   cnpm i bootstrap -S         安装bootstrap
5:    npm i vue -S           安装 vue
 

开发是用到  -D

3:  安装 webpack-dev-server
cnpm i webpack-dev-server -D   来自动打包编译,把bundle.js 放到内存中
cnpm i webpack -D
cnpm i webpack-cli -D
 
cnpm i webpack-dev-server webpack webpack-cli -D
 
4:  安装 html-webpack-plugin 把html放到内存中
cnpm i html-webpack-plugin -D   把html放到内存中
 
5:  处理样式文件
cnpm i style-loader css-loader -D   加载less文件
cnpm i less-loader less -D          处理less文件
cnpm i sass-loader node-sass  -D  cnpm i sass fibers -D      处理scss文件
cnpm i sass-loader node-sass  sass fibers -D
 
6:处理url路径、图片、字体库
cnpm i url-loader file-loader -D
 
7:babel 解决高级语法

安装babel插件

 1:  运行 cnpm i @babel/core babel-loader @babel/plugin-transform-runtime -D  转换工具

 2:  运行 cnpm i @babel/preset-env @babel/preset-stage-0 -D                       语法

 3:   安装能够识别转换jsx语法的包 babel-preset-react

    运行 cnpm i @babel/preset-react -D

 4:   执行命令:cnpm i @babel/plugin-proposal-class-properties -D

  5: 执行命令:cnpm i @babel/runtime -D

 

8:  Vue组件

npm i vue-loader vue-template-compiler -D

 

9:  vue-router

npm i vue-router -S 

10:其他命令

3:npm init -y            创建package.json文件。
3:webpack ./src/main.js -o ./dist/bundle.js  把main.js处理成bundle.js文件
3:npm run dev  运行项目
 
webpack-dev-server --open --port 3000 --contentBase src --hot




6:算法
1:冒泡排序
  <script>

    //冒泡排序:把所有的数据按照一定的顺序进行排列(从小到大,从大到下)

    var arr = [10, 0, 100, 20, 60, 30];
    //循环控制比较的轮数
    for (var i = 0; i < arr.length - 1; i++) {
      //控制每一轮的比较的次数
      for (var j = 0; j < arr.length - 1 - i; j++) {
        if (arr[j] < arr[j + 1]) {
          var temp = arr[j];
          arr[j] = arr[j + 1];
          arr[j + 1] = temp;
        }
      }
    }
    console.log(arr);
  </script>

 

 

 

 

 

 

posted on 2019-10-05 10:53  风zk  阅读(1170)  评论(0编辑  收藏  举报

导航