从es6基础到vue---有这一篇就够了!

1. es5和es6基础知识

1.1 前后端分离项目

前后端未分离项目:html文件渲染在django后端完成
--------------------------------------------------------------
前后端分离项目:ajax异步请求,django只负责读取数据和加工数据
前端做前端的事情:页面+交互+兼容+封装+class+优化 (技术栈:vue+vue-router+vuex+axios+element-ui)
后端做后端的事情:接口+表操作+业务逻辑+封装+class+优化 (技术栈:restframework框架+django框架+mysql\redis等)

在这里插入图片描述

1.2 MTV模式和MVVM框架

Vue 前端框架(数据驱动视图)   MVVM -- model -- view -- viewmodel      ---  template模板渲染
    model--数据
    view -- 视图   -- html标签   类似于jquery  $('#d1').text('xxx')
    viewmodel:数据驱动视图 vue的核心,model数据直接驱动到视图中(html标签中)

django  -- MTV模式   
	model  template  view + url控制器    
	template这一块功能就去掉了
	view--视图:  后端逻辑  FBV和CBV

img

1.3 ES6基本语法

1.let声明变量

let 声明的变量只在let命令所在的代码块内有效 ( js里面大括号表示一个代码块 )

{
  let a = 10;
  var b = 1;  //相当于将b的声明放在了作用域的外面前面,var b;然后这里只是赋值
}

不存在变量提升

// var 的情况
console.log(foo); // 输出undefined
var foo = 2;

// let 的情况
console.log(bar); // 报错ReferenceError
let bar = 2;

暂时性死区

var tmp = 123;

if (true) {
  tmp = 'abc'; // ReferenceError
  let tmp;
}
-----------------------------------------------------------------------------------
上面代码中,存在全局变量tmp,但是块级作用域内let又声明了一个局部变量tmp,导致后者绑定这个块级作用域,所以在let声明变量前,对tmp赋值会报错。

ES6 明确规定,如果区块中存在letconst命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错

不允许重复声明

// 报错
function func() {
  let a = 10;
  var a = 1;
}

// 报错
function func() {
  let a = 10;
  let a = 1;
}

//let不允许在相同作用域内,重复声明同一个变量。
2.作用域

let实际上为 JavaScript 新增了块级作用域。

function f1() {
  let n = 5;
  if (true) {
    let n = 10;
  }
  console.log(n); // 5
}
3.const声明常量

const声明一个只读的常量。一旦声明,常量的值就不能改变。

const PI = 3.1415;
PI // 3.1415

PI = 3;
// TypeError: Assignment to constant variable.
4.模板字符串

模板字符串就是两个反引号,括起来的字符串,就是模板字符串,var或者let声明的变量都可以被模板字符串直接通过${变量名}来使用

var aa = 'chao';
let bb = 'jj';

var ss = `你好${aa}`;
ss
"你好chao"

var ss2 = `你好${bb}`;
ss2
"你好jj"

let ss3 = `你好${aa}`;
ss3
"你好chao"
5.函数

匿名函数

let add = function (x) {
    return x
};
add(5);

箭头函数 (就是上面方法的简写形式)

//ES6的箭头函数,就是上面方法的简写形式
let add = (x) => {
    return x
};
console.log(add(20));
//更简单的写法,但不是很易阅读
let add = x => x;
console.log(add(5));
多个参数的时候必须加括号,函数返回值还是只能有一个,没有参数的,必须写一个()
let add = (x,y) => x+y;

自定义对象中封装函数(注意this指向问题)

//ES6中自定义对象中来封装箭头函数的写法
let person2 = {
    name:'超',
    age:18,
    f1: () => {  //在自定义的对象中放函数的方法
        console.log(this); //this指向的不再是当前的对象了,而是指向了person的父级对象(称为上下文),而此时的父级对象是我们的window对象,Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
        console.log(window);//还记得window对象吗,全局浏览器对象,打印结果和上面一样:Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
        console.log(this.name)  //啥也打印不出来
    }
};
person2.f1(); //通过自定对象来使用函数

//而我们使用this的时候,希望this是person对象,而不是window对象,所以还有下面这种写法
let person3 = {
    name:'超',
    age:18,
    f1(){  //相当于f1:function(){},只是一种简写方式,称为对象的单体模式写法,写起来也简单,vue里面会看用到这种方法
        console.log(this);//this指向的是当前的对象,{name: "超", age: 18, f1: ƒ}
        console.log(this.name)  //'超'
    }
};
person3.f1()

2.vue的基本使用

1.下载安装

官网地址:https://cn.vuejs.org/

方式1:

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>

方式2:

<script src="vue.js"></script>

2.vue基本模板

1)在body标签里圈地

2)script 引入vue

3)实例化对象

<div id="app">
    <!-- vue的模板语法,和django的模板语法类似 -->
    <h2>{{ msg }}</h2><!-- 放的是变量,就会去下面的Vue对象中的data属性中的键去找对应的数据,注意语法规范,中间的数据前后都有一个空格 -->
    <h2>{{ 'xxxxx' }}</h2> <!-- 写个字符串就直接显示这个字符串 -->  
</div>
<!-- 1.引包 -->
<script src="vue.js"></script>
<script>
//2.实例化对象
    new Vue({  //实例化的时候要传一个参数,options配置选项,是一个自定义对象,下面就看看这些配置选项都是什么,是我们必须要知道的东西,el和data是必须要写的
        
        el:'#app', //el是当前我们实例化对象绑定的根元素(标签),会到html文档中找到这个id属性为app的标签,在html里面写一个id属性为app的div标签,意思就是说,我现在实例化的这个Vue对象和上面这个id为app的div绑定到了一起,在这个div里面使用vue的语法才能生效,就像一个地主圈了一块地一样,那么接下来就要种东西了
        
        data:{  //data是数据属性,就是我们要在地里面种的东西了,是一个自定义对象
            msg:'黄瓜',  //这些数据以后是通过数据库里面调出来,然后通过后端代码的接口接收到的,现在写死了,先看看效果,我们在上面的div标签里面写一个其他的标签,然后写上{{ msg }},这样就相当于我们在id为app的div标签的这个地里面种了一个种子,这个种子产的是黄瓜,那么我们打开页面就直接看到黄瓜了
        }
    })
</script>

data属性的其他写法:

// 方式2
 data:function () {
    return {
    'msg':'掀起你的盖头来1!'
    }
}

// 方式3 (常用)
data(){   // 单体模式  这种写法用的居多,并且后面学习中有个地方一定要这样写,所以我们就记下来这种写法就可以了
    return {
    'msg':'掀起你的盖头来2!',
}
}

3.vue的指令系统

指令会在vm对象的data属性的数据发生变化时,会同时改变元素中的其控制的内容或属性。

因为vue的历史版本原因,所以有一部分指令都有两种写法:

vue1.x写法             vue2.x的写法
v-html         ---->   {{  }}   # vue2.x 也支持v-html
v-bind:属性名   ---->   :属性
v-on:事件名     ---->   @事件名
3.1 v-text 和 v-html 文本指令

v-text相当于js代码的innerText

v-html相当于innerHtml,识别标签

<body>

<div id="app">
    <!-- vue的模板语法 -->
    <div>{{ msg }}</div>
    <div v-text="msg"></div>
    <div v-html="msg"></div>
</div>

<script src="vue.js"></script>
<script>
    new Vue({
        el:'#app',
        data(){
            //记着data中是一个函数,函数中return一个对象,可以是一个空对象,但必须return
            return{
                msg:'<h2>超</h2>', //后端返回的是标签,那么我们就可以直接通过v-html渲染出来标签效果
            }
        }
    })
</script>
</body>
</html>
3.2 v-if 和 v-show 条件渲染指令
v-if是标签的添加和删除,v-show是标签的显示和隐藏
---------------------------------------------------------------
一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。
因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。

v-if:

----------------v-if------------------------------------- 
标签元素:
      <!-- vue对象最终会把条件的结果变成布尔值 -->
			<h1 v-if="ok">Yes</h1>
data数据:
  		data:{
      		ok:false    // true则是显示,false是隐藏
      }
-------------v-if 和 v-else-------------------------------
标签元素:
			<h1 v-if="ok">Yes</h1>
			<h1 v-else>No</h1>
data数据:
  		data:{
      		ok:false    // true则是显示,false是隐藏
      }
-------------v-else-if-----------------------------------
标签元素:
			<h1 v-if="num===1">num的值为1</h1>
			<h1 v-else-if="num===2">num的值为2</h1>
		  <h1 v-else>num的值是{{num}}</h1>
data数据:
  		data:{
      		num:2
      }

v-show:

标签元素:
			<h1 v-show="ok">Hello!</h1>
data数据:
  		data:{
      		ok:false    // true则是显示,false是隐藏
      }
3.3 v-bind 操作属性

格式:

<标签名 :标签属性="data属性"></标签名>
<a :href="url2">淘宝</a>
<a v-bind:href="url1">百度</a>  <!-- v-bind是vue1.x版本的写法 -->
3.4 事件绑定v-on和methods属性

有两种操作时间的写法,

//方式1:
<button v-on:click="num++">按钮</button>   <!-- v-on 是vue1.x版本的写法 -->
//方式2:
<button @click="num+=5">按钮2</button>
3.5 v-model 标签数据的双向绑定

v-model : 实现标签和数据的双向绑定,是数据驱动视图的典型表现

v-model本质上是一个语法糖。如下代码<input v-model="test">本质上是<input :value="test" @input="test = $event.target.value">

如:在input标签中的应用

<div id="app">
<input v-model="text">
<sapn>{{text}}</sapn>
</div>

-------------------------------

<script src="vue.js"></script>
<script>
    let vm = new Vue({
        el:'#app',
        data(){
            return {
                text:'',
            }
        }
    })
</script>

如:在单选框中的应用:

<div id="app">
    <select v-model="selected">
        <option value="A被选">A</option>
        <option value="B被选">B</option>
        <option value="C被选">C</option>
	</select>
	<span>被选的是: {{ selected }}</span>
<div>
-----------------------------------------------
<script src="vue.js"></script>
<script>
    let vm = new Vue({
        el:'#app',
        data(){
            return {
                selected: '',
            }
        }
    })
</script>
例1:wifi密码切换显示
<div id="index">
    <img :src="url" :alt="title"><br>
    <input :type="type" placeholder="请输入wifi密码">
    <button @click="clickhander">{{type_tips}}</button>
  	<button @mouseover="clickhander">{{type_tips}}</button> <!--事件名称都是按照js中的事件名称来的,所以可以使用的事件很多-->
    <button v-on:click="clickhander">{{type_tips}}</button>
</div>

----------------------------------------------------------------

<script>
    let vm = new Vue({
        el:"#index",
        // 在data可以定义当前vue对象调用的属性,调用格式: this.变量名,例如: this.title
        data:{
          url:"https://www.luffycity.com/static/img/head-logo.a7cedf3.svg",
          title:"路飞学成",
          type:"password",
          type_tips: "显示密码",
        },
        methods:{ // 在methods中可以定义当前vue对象调用的方法,调用格式:this.方法名(),例如: this.clickhander()
            clickhander(){
                // alert(this.type); // 调用上面的data里面的数据
                if(this.type=="password"){
                    this.type="text";
                    this.type_tips="隐藏密码";
                }else{
                    this.type="password";
                    this.type_tips="显示密码";
                }
            }
        }
    })
</script>
例2:完成商城的商品增加减少数量
<div id="box">
        <button @click="++num">+</button>
        <input type="text" v-model="num">
        <button @click="sub">-</button>
</div>

----------------------------------------------------

<script>
        let vm = new Vue({
            el:"#box",
            data:{
                num:0,
            },
            methods:{
              	// sub:function(){},下面是这个写法的缩写
                sub(){
                    if(this.num<=1){
                        this.num=0;
                    }else{
                        this.num--;
                    }
                }
            }
        })
</script>

3.6控制标签class类名
格式:
   <h1 :class="值">元素</h1>  值可以是对象、对象名、数组(数组的方式用的比较少)

方式1:布尔值控制

<div id="app">
    <div :class="{c1:num==0,c3:num==0}" class="c2">{{msg}}</div>
    <input type="text" v-model="num">  //通过v-model控制
</div>

---------------------------------------------------------------------

<script src="vue.js"></script>
<script>
    let vm  = new Vue({
        el:'#app',
        data(){
            return {
                msg:'hello',
                num:0,
            }
        }
    })
</script>

方式2:三目运算符

<div id="app">
    <div :class="status?'c1':'c2'">{{msg}}</div>
</div>

---------------------------------------------------------------------

<script src="vue.js"></script>
<script>
    let vm  = new Vue({
        el:'#app',
        data(){
            return {
                msg:'hello',
                status:false,
            }
        }
    })
</script>

方式3:数组控制(不常用)

<div id="app">
    <div :class="[m1,]">xxxxx</div>
</div>

----------------------------------------------------------------------

<script src="vue.js"></script>
<script>
    let vm  = new Vue({
        el:'#app',
        data(){
            return {
                msg:'hello',
                m1:{
                    c1:false,
                    c2:false,
                }
            }
        }
    })

</script>
3.7 控制标签style样式

方式1:值是json对象,对象写在元素的:style属性中

//标签元素:
<div :style="{color: activeColor, fontSize: fontSize + 'px' }"></div><!-- 注意:不能出现中横杠,有的话就套上'font-size',或者去掉横杠,后一个单词的首字母大写,比如fontSize -->

-----------------------------------------------------------------------

//data数据如下:
data: {
    activeColor: 'red',
    fontSize: 30
}

方式2:值是对象变量名,对象在data中进行声明

标签元素:
	<div v-bind:style="styleObject"></div>

---------------------------------------------------------------

data数据如下:
data: {
    styleObject: {
        color: 'red',
        fontSize: '13px'  
    }
}

方式3:值是数组

标签元素:
	<div v-bind:style="[style1, style2]"></div>

--------------------------------------------------------------

data数据如下:
data: {
    style1:{
    	color:"red"
    },
    style2:{
        background:"yellow",
        fontSize: "21px"
    }
}
例:vue版本选项卡
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        #card{
            width: 500px;
            height: 350px;
        }
        .title{
            height:50px;
        }
        .title span{
            width: 100px;
            height: 50px;
            background-color:#ccc;
            display: inline-block;
            line-height: 50px; /* 设置行和当前元素的高度相等,就可以让文本内容上下居中 */
            text-align:center;
        }
        .content .list{
            width: 500px;
            height: 300px;
            background-color: yellow;
            display: none;
        }
        .content .active{
            display: block;
        }

        .title .current{
            background-color: yellow;
        }
    </style>
    <script src="vue.js"></script>
</head>
    
<body>
    <div id="card">
        <div class="title">
            <span @click="num=1" :class="{current:num===1}">国内新闻</span>
            <span @click="num=2" :class="{current:num===2}">国际新闻</span>
            <span @click="num=3" :class="{current:num===3}">银河新闻</span>
            <!--<span>{{num}}</span>-->
        </div>
        <div class="content">
            <div class="list" :class="{active:num===1}">国内新闻列表</div>
            <div class="list" :class="{active:num===2}">国际新闻列表</div>
            <div class="list" :class="{active:num===3}">银河新闻列表</div>
        </div>
    </div>
    
    <script>
        // 思路:
        // 当用户点击标题栏的按钮[span]时,显示对应索引下标的内容块[.list]
        // 代码实现:
        var card = new Vue({
            el:"#card",
            data:{
                num:1,
            },
        });
    </script>
</body>  
</html>
3.8 v-for 列表渲染指令
<div id="app">
    <ul>
        <!--<li v-for="(value,index) in data_list" :key="index">-->
        <!--<li v-for="value in data_list" :key="value.id">-->
        <li v-for="value in data_list" :key="value.id">    //value.id---> 1  4
            {{value.name}}
        </li>
        <li v-for="(value,index) in personInfo">
            {{value}} -- {{index}}
        </li>
    </ul>
</div>

-------------------------------------------------------------------

<script src="vue.js"></script>
<script>
    let vm  = new Vue({
        el:'#app',
        data(){
            return {
                data_list:[
                    {id:1,name:'鑫伟1'},
                    {id:4,name:'鑫伟4'},
                ],
                personInfo:{
                    name:'chao',
                    age:18
                }
            }
        }
    })
</script>

关于key的说明

v-for不仅可以遍历数组,还可以遍历对象,这里大家记住v-for里面的一个东西 :key, 就是v-bind:key,这个key是干什么的呢,就是为了给现在已经渲染好的li标签做个标记,以后即便是有数据更新了,也可以在这个li标签里面进行数据的更新,不需要再让Vue做重新生成li标签的dom操作,提高页面渲染的性能,因为我们知道频繁的添加删除dom操作对性能是有影响的,我现在将数据中的id绑定到这里,如果数据里面有id,一般都用id,如果没有id,就绑定v-for里面那个index(当然你看你给这个索引取的变量名是什么,我这里给索引取的名字是index),这里面它用的是diff算法.
练习:商品循环实例
goods:[
	{"name":"python入门","price":150},
	{"name":"python进阶","price":100},
	{"name":"python高级","price":75},
	{"name":"python研究","price":60},
	{"name":"python放弃","price":110},
]

# 把上面的数据采用table表格输出到页面,价格大于60的那一条数据需要添加背景色
<div id="app">
    <table border="1">
        <thead>
        <tr>
            <th>name</th>
            <th>price</th>
        </tr>
        </thead>
        <tbody>
        <tr v-for="(value,index) in goods" :key="index">
            <td>{{value.name}}</td>
            <td v-if="value.price>60" style="background-color: red;">{{value.price}}</td>
            <td v-else>{{value.price}}</td>
        </tr>
        </tbody>
    </table>
</div>
<script src="vue.js"></script>
<script>
    let vm = new Vue({
        el:'#app',
        data(){
            return {
                goods:[
                    {"name":"python入门","price":150},
                    {"name":"python进阶","price":100},
                    {"name":"python高级","price":75},
                    {"name":"python研究","price":60},
                    {"name":"python放弃","price":110},
                ]
            }
        }
    })
</script>

3.Vue对象提供的属性功能

3.1过滤器

过滤器,就是vue允许开发者自定义的文本格式化函数,可以使用在两个地方:输出内容和操作数据中。

定义过滤器的方式有两种,全局和局部过滤器

<div id="app">

    <p>{{price}}</p>
    <p>{{price.toFixed(2)}}</p>
    <p>{{price|yuan}}</p>
    <p>{{price|xx}}</p>
    <p>{{price|xx|yuan}}</p>
    <!-- 过滤器传额外参数 -->
    <p>{{price2|yuan2(2)}}</p>

</div>
<script src="vue.js"></script>
<script>
    // 全局过滤器
    Vue.filter('xx',function (value) {
       return value.toFixed(3) + '圆'
    });

    let vm  = new Vue({
        el:'#app',
        data(){
            return {
                price:100,
                price2:100.126, //四舍五入
            }
        },
        // 局部过滤器
        filters:{
            yuan(value){
                return value + ' 元'
            },
            yuan2(value,n){
                return value.toFixed(n) + ' 元'
            }
        }
    })

3.2 计算属性

<div id="app">
    <p>{{add}}</p>  //200.126
</div>
<script src="vue.js"></script>
<script>
    let vm  = new Vue({
        el:'#app',
        data(){
            return {
                price1:100,
                price2:100.126, //四舍五入
            }
        },
        // 计算属性
        computed:{
            add(){
                return this.price1 + this.price2
            }
        }
    })
</script>

3.3 监听属性

监听属性,可以帮助我们侦听data某个数据的变化,从而做相应的自定义操作。

监听属性是一个对象,它的键是要监听的对象或者变量,值一般是函数。

当侦听的data数据发生变化时,会自定执行的对应函数,这个函数在被调用时,vue会传入两个形参,第一个是变化后的数据值,第二个是变化前的数据值。

<div id="app">
    <p>{{ num }}</p>
    <button @click="num++">按钮</button>
</div>
<script src="js/vue.js"></script>
<script>
    var vm = new Vue({
        el:"#app",
        data:{
            num:20
        },
        watch:{
            num:function(newval,oldval){
                //num发生变化的时候,要执行的代码
                console.log("num已经发生了变化!",newval,oldval);
            }
        }
    })
</script>

例:用户名长度限制4-10位

<div id="app">
    <form action="">
        账号:<input type="text" v-model="form.username"><span :style="user_style">{{user_text}}</span><br><br>
        密码:<input type="password" v-model="form.password"><br><br>
        确认密码:<input type="password" v-model="form.password2"><br><br>
    </form>
</div>
<script src="js/vue.js"></script>
<script src="js/filters.js"></script>
<script>
    var vm1 = new Vue({
        el:"#app",
        data:{
            form:{
                username:"",
                password:"",
                password2:"",
            },
            user_style:{
                color: "red",
            },
            user_text:"用户名长度只能是4-10位"
        },
        // 监听属性
        // 监听属性的变化
        watch:{
            "form.username":function(value){ //注意,使用数据属性中的某个属性的时候,如果使用的是该数据中的内部属性,别忘了加双引号
                if(value.length>=4 && value.length<=10){
                    this.user_style.color="blue";
                    this.user_text="用户名长度合法!";
                }else{
                    this.user_style.color="red";
                    this.user_text="用户名长度只能是4-10位!";
                }
            }
        }
    })
</script>

3.4 vue对象的生命周期钩子函数

每个Vue对象在创建时都要经过一系列的初始化过程。在这个过程中Vue.js会自动运行一些叫做生命周期的的钩子函数,我们可以使用这些函数,在对象创建的不同阶段加上我们需要的代码,实现特定的功能。

<body>
    <div id="app">
        <p>{{num}}</p>
        <button @click="num++">按钮</button>
    </div>
</body>
<script src="js/vue.min.js"></script>
<script>
    window.onload = function(){
        //$(function(){})()  $.ready() -- window.onload = function(){}
        var vm = new Vue({
            el:"#app",
            data:{
                num:0
            },
            beforeCreate:function(){
                console.log("beforeCreate,vm对象尚未创建,num="+ this.num);  //undefined,就是说data属性中的值还没有放到vm对象中
                this.name=10; // 此时没有this对象呢,所以设置的name无效,被在创建对象的时候被覆盖为0
              	console.log(this.$el) //undefined
            },
            created:function(){
              	// 用的居多,一般在这里使用ajax去后端获取数据,然后交给data属性
                console.log("created,vm对象创建完成,设置好了要控制的元素范围,num="+this.num );  // 0 也就是说data属性中的值已经放到vm对象中
                this.num = 20;
                console.log(this.$el) //undefined
            },
            beforeMount:function(){
                console.log( this.$el.innerHTML ); // <p>{{num}}</p> ,vm对象已经帮我们获取到了这个视图的id对象了
                console.log("beforeMount,vm对象尚未把data数据显示到页面中,num="+this.num ); // 20,也就是说vm对象还没有将数据添加到我们的视图中的时候
                this.num = 30;
            },
            mounted:function(){
              	// 用的居多,一般在这里使用ajax去后端获取数据然后通过js代码对页面中原来的内容进行更改 
                console.log( this.$el.innerHTML ); // <p>30</p>
                console.log("mounted,vm对象已经把data数据显示到页面中,num="+this.num); // 30,也就是说vm对象已经将数据添加到我们的视图中的时候
            },
            
          	// 后面两个简单作为了解吧,测试的时候最好单独测试下面两个方法
            beforeUpdate:function(){
                // this.$el 就是我们上面的el属性了,$el表示当前vue.js所控制的元素#app
                console.log( this.$el.innerHTML );  // <p>30</p>
                console.log("beforeUpdate,vm对象尚未把更新后的data数据显示到页面中,num="+this.num); // beforeUpdate----31
                
            },
            updated:function(){
                console.log( this.$el.innerHTML ); // <p>31</p>
                console.log("updated,vm对象已经把过呢更新后的data数据显示到页面中,num=" + this.num ); // updated----31
            },
        });
    }
</script>

img

用法:

在vue使用的过程中,如果要初始化操作,把初始化操作的代码放在 mounted 中执行。
mounted阶段就是在vm对象已经把data数据实现到页面以后。一般页面初始化使用。例如,用户访问页面加载成功以后,就要执行的ajax请求。

另一个就是created,这个阶段就是在 vue对象创建以后,把ajax请求后端数据的代码放进 created

3.5 阻止事件冒泡和刷新页面

使用.stop和.prevent

阻止事件冒泡:

<style>
        .c1{
            background-color: red;
            height: 200px;
        }
        .c2{
            background-color: green;
            height: 100px;
            width: 100px;
        }
</style>

<div id="app">

  <div class="c1" @click="f1">
      <!--<div class="c2" @click.stop="f2" ></div>-->
      <div class="c2" @click.stop.prevent="f2" ></div>
      <!-- 阻止标签自带的动作 -->
      <!--<a href="http://www.baidu.com" @click.stop.prevent="">百度</a>-->
  </div>

</div>
<script src="vue.js"></script>
<script>
    let vm  = new Vue({
        el:'#app',
        data(){
            return {
                price1:100,
            }
        },
        methods:{
            f1(){
                alert('111');
            },
            f2(){
                alert('222');
            }
        }
    })
</script>

例:todolist

<head>
	<meta charset="UTF-8">
	<title>todolist</title>
	<style type="text/css">
		.list_con{
			width:600px;
			margin:50px auto 0;
		}
		.inputtxt{
			width:550px;
			height:30px;
			border:1px solid #ccc;
			padding:0px;
			text-indent:10px;
		}
		.inputbtn{
			width:40px;
			height:32px;
			padding:0px;
			border:1px solid #ccc;
		}
		.list{
			margin:0;
			padding:0;
			list-style:none;
			margin-top:20px;
		}
		.list li{
			height:40px;
			line-height:40px;
			border-bottom:1px solid #ccc;
		}

		.list li span{
			float:left;
		}

		.list li a{
			float:right;
			text-decoration:none;
			margin:0 10px;
		}
	</style>
</head>
<body>
	<div class="list_con">
		<h2>To do list</h2>
		<input type="text" name="" id="txt1" class="inputtxt" v-model="sm">
		<input type="button" name="" value="增加" id="btn1" class="inputbtn" @click="add">

		<ul id="list" class="list">
			<!-- javascript:; # 阻止a标签跳转 -->
			<li v-for="(value,index) in dolist" :key="value.id">
				<span>{{value.dosm}}</span>
				<a href="javascript:;" class="up" @click="up(index)"></a>
				<a href="javascript:;" class="down" @click="down(index)"></a>
				<a href="javascript:;" class="del" @click="del(index)">删除</a>
			</li>

		</ul>
	</div>
</body>
<script src="vue.js"></script>
<script>
    let vm = new Vue({
        el:'.list_con',
        data(){
            return {
                sm:'',
                dolist:[
                    {id:1,dosm:'学习html'},
                    {id:2,dosm:'学习css'},
                    {id:3,dosm:'学习javascript'},
                    {id:4,dosm:'学习python'},
                    {id:5,dosm:'学习推油'},

                ]
            }
        },
        methods:{
            add(){
                let last_ele = this.dolist[this.dolist.length-1];
                if (last_ele){
                    let ele = {
                        id:++last_ele.id,
                        dosm:this.sm,
                    };
                    this.dolist.push(ele);
                }else {
                    this.dolist.push({id:1,dosm:this.sm});
                }

                // console.log(this.dolist);
            },
            del(index){
                this.dolist.splice(index,1);
            },
            up(index){
                if (index > 0){
                    let delEle = this.dolist.splice(index,1)[0];
                    // console.log(delEle);
                    this.dolist.splice(index-1,0,delEle)
                }

            },
            down(index){
                let delEle = this.dolist.splice(index,1)[0];
                this.dolist.splice(index+1,0,delEle)
            }
        }
    })
</script>

补充:a标签的href属性

<a href="#">百度</a>
<!--href属性为空时,刷新页面-->
<!--不写href属性,就是普通文本标签-->
<!-- 当href属性等于某个值时,页面跳转到对应的页面 -->
<!-- 当href属性等于javascript:void (0);简写javascript:;时,不刷新也不跳转 -->
<!-- 当href属性等于#时,不刷新也不跳转,但是会在url上加个#号结尾 -->

4.axios–实现数据请求

4.1axios的基础知识

什么是axios?

vue.js默认没有提供ajax功能的。
所以使用vue的时候,一般都会使用axios的插件来实现ajax与后端服务器的数据交互。
注意,axios本质上就是javascript的ajax封装,所以会被同源策略限制。

axios的下载地址:

https://unpkg.com/axios@0.18.0/dist/axios.js
https://unpkg.com/axios@0.18.0/dist/axios.min.js

4.2 axios常用发送请求的方法

axios.get()和axios.post()

// 发送get请求
    // 参数1: 必填,字符串,请求的数据接口的url地址,例如请求地址:http://www.baidu.com?id=200
    // 参数2:可选,json对象,要提供给数据接口的参数
    // 参数3:可选,json对象,请求头信息
	axios.get('服务器的资源地址',{ // http://www.baidu.com
    	params:{
    		参数名:'参数值', // id: 200,
    	}
    
    }).then(function (response) { // 请求成功以后的回调函数
    		console.log("请求成功");
    		console.log(response);
    
    }).catch(function (error) {   // 请求失败以后的回调函数
    		console.log("请求失败");
    		console.log(error.response);
    });

	// 发送post请求,参数和使用和axios.get()一样。
    // 参数1: 必填,字符串,请求的数据接口的url地址
    // 参数2:必填,json对象,要提供给数据接口的参数,如果没有参数,则必须使用{}
    // 参数3:可选,json对象,请求头信息
    axios.post('服务器的资源地址',{
    	username: 'xiaoming',
    	password: '123456'
    },{
        responseData:"json",
    })
    .then(function (response) { // 请求成功以后的回调函数
      console.log(response);
    })
    .catch(function (error) {   // 请求失败以后的回调函数
      console.log(error);
    });

	
	// b'firstName=Fred&lastName=Flintstone'

例:获取天气信息

<body>

<div id="app">
    <h1>{{msg}}</h1>

</div>



</body>
<script src="vue.js"></script>
<script src="jquery.js"></script>
<script src="axios.js"></script>
<script>
    let vm  = new Vue({
        el:'#app',
        data(){
            return {
                price1:100,
                msg:'',
            }
        },
        created(){
            // let ths = this;
            // axios.get('http://wthrcdn.etouch.cn/weather_mini?city=北京&city2=xx',{
            axios.get('http://wthrcdn.etouch.cn/weather_mini',{
                params:{
                    city:'北京',
                    //city:'北京',
                }
            })
                .then( (res) => {
                    // console.log(res);
                    // console.log(res.data.data.ganmao);
                    // console.log(this);

                    // 注意this指向问题
                    // ths.msg = res.data.data.ganmao;
                    this.msg = res.data.data.ganmao;
                }).catch(function (res) {
            })
            
            // $.ajax({
            //     url:'http://wthrcdn.etouch.cn/weather_mini?city=北京',
            //     type:'get',
            //
            //     success:function (res) {
            //         console.log(res);
            //     }
            //
            // })
        }
    })
</script>

4.3 同源策略

4.3.1 什么是同源策略
同源策略,是浏览器为了保护用户信息安全的一种安全机制。所谓的同源就是指代通信的两个地址(例如服务端接口地址与浏览器客户端页面地址)之间比较,是否协议、域名(IP)和端口相同。不同源的客户端脚本[javascript]在没有明确授权的情况下,没有权限读写对方信息。

总之,协议+域名+端口都相同时,两个网站同源,否则浏览器会拦截读取的信息
4.3.2 同源拦截的报错
Access to XMLHttpRequest at 'http://tingapi.ting.baidu.com/v1/restserver/ting?method=baidu.ting.search.catalogSug&query=%E6%88%91%E7%9A%84%E4%B8%AD%E5%9B%BD%E5%BF%83' from origin 'http://localhost:63342' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
上面错误,关键词:Access-Control-Allow-Origin

只要出现这个关键词,就是访问受限。出现同源策略的拦截问题。
4.3.3 django中跨域(跨源)方案
CORS:
    CORS是一个W3C标准,全称是"跨域资源共享",它允许浏览器向跨源的后端服务器发出ajax请求,从而克服了AJAX只能同源使用的限制。
    实现CORS主要依靠后端服务器中响应数据中设置响应头信息返回的。

在django的视图函数中:

def data(request):
    ret = HttpResponse('ba jie ok!')
    ret['Access-Control-Allow-Origin'] = '*' # 所有源请求我, 都行,浏览器不要阻拦
    # ret['Access-Control-Allow-Origin'] = 'http://127.0.0.1:8000' # 所有源请求我, 都行,浏览器不要阻拦
    return ret

5.组件化开发

什么是组件

组件(Component)是自定义封装的功能。在前端开发过程中,经常出现多个网页的功能是重复的,而且很多不同的网站之间,也存在同样的功能。


而在网页中实现一个功能,需要使用html定义功能的内容结构,使用css声明功能的外观样式,还要使用js来定义功能的特效,因此就产生了把一个功能相关的[HTML、css和javascript]代码封装在一起组成一个整体的代码块封装模式,我们称之为“组件”。


所以,组件就是一个html网页中的功能,一般就是一个标签,标签中有自己的html内容结构,css样式和js特效。

这样,前端人员就可以在开发时,只需要书写一次代码,随处引入即可使用。

我们在进行vue开发的时候,还记得我们自己创建的vm对象吗,这个vm对象我们称为一个大组件,根组件(页面上叫Root),在一个网页的开发中,根据网页上的功能区域我们又可以细分成其他组件,或称为子组件

5.1局部组件和全局组件

局部组件:

1 声明子组件

2 挂载子组件

3 使用子组件

<div id="app">
    <div class="vheader">
        这是头部{{msg}}
    </div>
    <App/>  <!--3 使用子组件-->
</div>
<script>
    //子组件的名称尽量不要叫做Header或者vHeader等,以防和最新的H5中的标签名称冲突,导致组件无法使用
    //  1 声明子组件
    let App = {
        data(){
            return { //组件中必须写成函数形式的
                'appmsg':'hello app!'
            }
        },
        template:`
            <div class="content">
                内容部分{{appmsg}}
            </div>
        `
    };
    let vm = new Vue({
        el:'#app',
        data(){
            return {
                'msg':'hello'
            }
        },
        components:{
            App,  // 2 挂载子组件
        }
    })
</script>

全局组件(默认组件)

局部组件使用时需要挂载,全局组件使用时不需要挂载。那么他们两个什么时候用呢,局部组件就在某个局部使用的时候,全局组件是大家公用的,或者说每个页面都有这么一个功能的时候,在哪里可能都会用到的时候。
<div id="app">
    <addnum></addnum>

</div>

<script>
    Vue.component("addnum",{
        template:'<div><input type="text" v-model="num"><button @click="num+=1">点击</button></div>',
        data: function(){
            // 写在这里的数据只有当前组件可以使用
            return {
                num:1,
            }
        }
    });
    var vm = new Vue({
        el:"#app",
        data:{

        }
    })
</script>

5.2 组件传值

父组件往子组件传值
1.在子组件中使用props属性声明,然后可以直接在子组件中任意使用
2.父组件要定义自定义的属性
<div id="app">
    <h1>你好</h1>
    <App></App>
</div>
<script>
    // 1 声明子组件  声子
    let Naver = {
        data(){
            return {
                navMsg:'这是顶部导航栏'
            }
        },
        template:
         `
          <div class="Naver">
                <h1>{{navMsg}}</h1>
                 <h2>2222</h2>
                 <h2>{{xx}}</h2>

        </div>
        `,
        props:['xx',]
    };
    let App = {
        data(){
            return {
                Msg:'这是App组件',
                num:100,
            }
        },
        template:
         `
          <div class="nav">

                <h1 style="color:blue;">{{Msg}}---{{num}}</h1>
                <!--
                <Naver xx="xiaobei"></Naver> 静态传值
                <Naver :xx="num"></Naver>  动态传值
                -->

                <Naver :xx="num"></Naver>

        </div>
        `,
        components:{
            Naver,
        }
    };
    let  vm = new Vue({
        el:'#app',
        data(){
            return {
            }
        },
        // 2 挂载子组件  挂子
        components:{
            // 挂载组件的简写形式
            App,
        }
    })
</script>

在这里插入图片描述

注意:

1. 传递数据是变量,则需要在属性左边添加冒号.

   传递数据是变量,这种数据称之为"动态数据传递"

   传递数据不是变量,这种数据称之为"静态数据传递"

2. 父组件中修改了数据,在子组件中会被同步修改,但是,子组件中的数据修改了,是不是影响到父组件中的数据.

   这种情况,在开发时,也被称为"单向数据流"
子组件往父组件传值
1 子组件中使用this.$emit('fatherHandler',val);fatherHandler是父组件中使用子组件的地方添加的绑定自定义事件
(注意,如果fatherHandler报错了,那么可能是你的vue版本不支持自定义键名称fatherHandler中有大写字母,所以我们改成father-handler或者直接就全部小写就可以了)

2 父组件中的methods中写一个自定义的事件函数:appFatherHandler(val){},在函数里面使用这个val,这个val就是上面子组件传过来的数据

子组件:
在这里插入图片描述

父组件:

在这里插入图片描述

<div id="app">
    <h1>你好</h1>
    <App></App>
</div>
<script>
    // 1 声明子组件  声子
    let Naver = {
        data(){
            return {
                navMsg:'这是顶部导航栏',
                sonNum:80,
            }
        },

        template:
         `
          <div class="Naver">
                <h1>{{navMsg}}</h1>
                <button @click="zouni">走你</button>
        </div>

        `,
        methods:{
            zouni(){
                //
                console.log(this);
                // 3 子组件中调用$emit方法,来实现传值动作 $emit(父组件自定义事件名称,数据)
                this.$emit('fatherHandler',this.sonNum);
            }
        }
    };

    let App = {
        data(){
            return {
                Msg:'这是App组件',
                num:100,
                xx:'',
            }
        },
        //1. 父组件使用子组件的地方加上自定事件
        template:
         `
          <div class="nav">
                <h1 style="color:blue;">{{Msg}}---子组件的num为:{{xx}}</h1>
                <Naver @fatherHandler="fuckSon"></Naver>
        </div>
        `,
        components:{
            Naver,
        },
        methods:{
            // 2  在父组件中定义自定义事件对应的方法,方法需要写参数,用来接收子组件传递过来的数据
            fuckSon(val){
                this.xx = val;
            }
        }
    };


    let  vm = new Vue({
        el:'#app',
        data(){
            return {
            }
        },
        // 2 挂载子组件  挂子
        components:{
            // 挂载组件的简写形式
            App,
        }
    })
</script>
平行传值
1 new一个vue对象,用来存放和取出数据
2 存放:bus.$emit('kkk',this.t1Num); //(别名 , 需要传递的数据)
3 取出:
	bus.$on('kkk', (val) => {      //用箭头函数指向父级对象
                console.log(this);
                this.t1msg = val;
            });

在这里插入图片描述

<div id="app">
    <h1>你好</h1>
    <App></App>
</div>
let bus = new Vue();

    Vue.component('T1',{
        data(){
            return {
                t1Msg:'我是t1组件',
                t1Num:120,
            }
        },
        template:`
            <div class="t1">
                <h3>{{t1Msg}}--{{t1Num}}</h3>
                <button @click="zouni">走你</button>
            </div>
        `,
        methods:{
            zouni(){
              bus.$emit('kkk',this.t1Num);
            }
        }
    });
    Vue.component('T2',{
        data(){
            return {
                t2Msg:'我是t2组件',
                t2Num:130,
                t1msg:'',
            }
        },
        template:`
            <div class="t1">
                <h3>{{t2Msg}}</h3>
                <h3>t1组件传递过来的数据:{{t1msg}}</h3>
            </div>
        `,
        created(){
            bus.$on('kkk', (val) => {
                console.log(this);
                this.t1msg = val;
            });
        },
    });
    let App = {
        data(){
            return {
                Msg:'这是App组件',
                num:100,
                xx:'',
            }
        },
        template:
         `
          <div class="nav">
                <T1></T1>
                <T2></T2>
        </div>
        `,
    };

    let  vm = new Vue({
        el:'#app',
        data(){
            return {

            }
        },
        // 2 挂载子组件  挂子
        components:{
            // 挂载组件的简写形式
            App,
        }
    });

6.vue-router的使用

单页应用,看下图:(react、angular也都是做单页面应用,很多大型的网站像网易云音乐,豆瓣等都是react写的单页面应用)

img

6.1vue-router的下载安装及简单操作

官方地址:https://router.vuejs.org/zh/

下载vue-router的cnd链接地址:https://unpkg.com/vue-router/dist/vue-router.js

你也可以像 https://unpkg.com/vue-router@2.0.0/dist/vue-router.js 这样指定 版本号 或者 Tag。

官网简单操作:

// 0. 如果使用模块化机制编程,导入Vue和VueRouter,要调用 Vue.use(VueRouter)

// 1. 定义 (路由) 组件。
// 下面两个组件可以从其他文件 import 进来
const Foo = { template: '<div>foo</div>' }
const Bar = { template: '<div>bar</div>' }

// 2. 定义路由
// 每个路由应该映射一个组件。 其中"component" 可以是
// 通过 Vue.extend() 创建的组件构造器,
// 或者,只是一个组件配置对象。
// 我们晚点再讨论嵌套路由。
const routes = [
  { path: '/foo', component: Foo },
  { path: '/bar', component: Bar }
]

// 3. 创建 router 实例,然后传 `routes` 配置
// 你还可以传别的配置参数, 不过先这么简单着吧。
const router = new VueRouter({
  routes // (缩写) 相当于 routes: routes
})

// 4. 创建和挂载根实例。
// 记得要通过 router 配置参数注入路由,
// 从而让整个应用都有路由功能
const app = new Vue({
  router
}).$mount('#app')

// 现在,应用已经启动了!

6.2简单实例

<div id="app">
    <h1>你好</h1>
    <App></App>
</div>
// 1. 定义 (路由) 组件
let Home = {
    data(){
        return {
            msg:'这是home页面'
        }
    },
    template:`
<div class="home">
<h1>{{msg}}</h1>
</div>
`
};
// 1. 定义 (路由) 组件
let Course = {
    data(){
        return {
            msg:'这是Course页面'
        }
    },
    template:`
    <div class="course">
    <h1>{{msg}}</h1>

    </div>
	`
};
let App = {
    data(){
        return {

        }
    },
  //使用 router-link 组件来导航. 
  //通过传入 `to` 属性指定链接.
  //<router-link> 默认会被渲染成一个 `<a>` 标签 
    template:
    `
    <div class="nav">
    <router-link to="/home">首页</router-link>
    <router-link to="/course">课程页</router-link>

    <router-view></router-view>
    </div>
    `,
    //路由出口
    //路由匹配到的组件将渲染在这里
};
// 2. 定义路由
const routes = [
    {path:'/home', component:Home},
    {path:'/course', component:Course},
];
// 3. 创建 router 实例,然后传 `routes` 配置
let router = new VueRouter({
    routes,// (缩写) 相当于 routes: routes
})
let  vm = new Vue({
    el:'#app',
    router,
    data(){
        return {

        }
    },
    // 2 挂载子组件  挂子  
    components:{
        // 挂载组件的简写形式
        App,
    }

7.vue cli自动化工具

7.1 安装vue cli

Vue CLI 需要 Node.js 8.9 或更高版本 (推荐 8.11.0+)。

nodejs下载地址:https://nodejs.org/en/download/

使用npm来安装vue-cli

npm install -g vue-cli
npm install -g vue-cli --registry https://registry.npm.taobao.org
npm config -g set registry https://registry.npm.taobao.org  # 设置淘宝镜像
npm install -g @vue/cli
npm install -g @vue/cli-init  # vue2.x版本需要安装桥接工具

7.2 创建一个vue项目

1 切换目录

在这里插入图片描述

2 创建一个项目

vue init webpack ceshi1

在这里插入图片描述
3 运行项目

npm run dev

7.3 项目目录结构

├── build/
├── config/
├── index.html
├── node_modules/    # 项目运行的依赖库存储目录[非常大]
├── package.json     # 项目运行需要的依赖库记录配置
├── src/
│   ├── App.vue      # 父级组件
│   ├── assets/      # 静态资源目录,图片存放在这里
│   ├── components/  # 单文件组件保存目录
│   └── main.js
└── static/          # 静态资源目录,所有的测试时用的,但是不需要交给线上服务器的css,js等文件放在这个目录

src 主开发目录,要开发的单文件组件全部在这个目录下的components目录下

static 静态资源目录,所有的css,js文件放在这个文件夹

dist 项目打包发布文件夹,最后要上线单文件项目文件都在这个文件夹中[后面打包项目,让项目中的vue组件经过编译变成js 代码以后,dist就出现了]

node_modules目录是node的包目录,

config是配置目录,id和端口等等

build是项目打包时依赖的目录

src/router 路由,后面需要我们在使用Router路由的时候,自己声明.

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值