Vue

6.Vue

6.1.Vue介绍
  • Vue.js------ 渐进式框架。与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计。Vue 的核心库只关注视图层,并且非常容易学习,非常容易与其它库或已有项目整合。另一方面,Vue 完全有能力驱动采用单文件组件和Vue生态系统支持开发复杂单页应用。
    • 渐进式:从核心到完备的全家桶
    • 增量:从少到多,从一页到多页,从简单到复杂
    • 单文件组件:一个文件描述一个组件
    • 单页应用:经过打包生成一个单页的html文件和一些js文件
    
    <html>
    <head>
    <meta charset="utf-8" />
    <title>快速入门title>
        
        
        
        
        <script src="vue.js">script>
    head>
        
    <body>
        <div id="app">
            {{message}}
        div>
        
        <script>
            new Vue({
                el:'#app', //表示当前vue对象接管了div区域
                data:{
                    message:'hello world' //注意不要写分号结尾
                }
            });
        script>
    body>
        
    html>
    
    
    

    使用Vue的js文件之前,记得先引用

6.2.插值表达式
  • 数据绑定最常见的形式就是使用“Mustache”语法 (双大括号) 的文本插值,Mustache 标签将会被替代为对应数据对象上属性的值。无论何时,绑定的数据对象上属性发生了改变,插值处的内容都会更新。
  • Vue.js 都提供了完全的 JavaScript 表达式支持。这些表达式会在所属 Vue 实例的数据作用域下作为 JavaScript 被解析。有个限制就是,每个绑定都只能包含单个表达式
    //下面的两个表达式都可以
    {{ number + 1 }}
    {{ ok ? 'YES' : 'NO' }}
    
    //下面的不会生效
    <!-- 这是语句,不是表达式 -->
    {{ var a = 1 }}
    <!-- 流控制也不会生效,请使用三元表达式 -->
    {{ if (ok) { return message } }}
    
6.3.VueJS 常用系统指令(V指令)
6.3.1.V-bind: 单向绑定
  • v-bind: 单向绑定, 在html中使用v-bind: 给一个html属性绑定一个参数, 这个参数是对应vue对象中自定义的参数

<html>
<head>
    <meta charset="utf-8" />
    <title>v-bindtitle>
    <script src="vue.js">script>
head>
<body>
    <div id="app">
        <font size="5" v-bind:color="ys1">Javafont>
        <font size="5" :color="ys2">C++font>
        <hr>
        itcasta>
	div>
<script>
    new Vue({
        el:'#app', //表示当前vue对象接管了div区域
        data:{
            ys1:"red",
            ys2:"green",
            id:1
        }
    });
script>
body>
html>

对于上述Vue代码,过程可以解析如下:

  1. 创建了一个Vue对象(根据Vue语法)
  2. 这个Vue对象一旦创建, 会立即检查 它的el属性,
  3. 他会根据el属性找到一个对应id的html代码
  4. 如果找到了, 把找到的html代码所对应的作用域 和 这个Vue对象’绑定起来’
  5. 这个html代码所对应的作用域 就不在仅仅是html代码作用域, 还是这个Vue对象作用域
  6. 这个作用域代码 会重新, 按照Vue语法再解析一边
  7. Vue固有属性
    • el
    • data
    • computed
6.3.2.V-model: 双向绑定
  • v- model: 双相绑定,在html中表单的value上使用,一个表单的value属性绑定一个参数,这个参数是对应vue对象中自定义的参数。
  • 如果绑定之后, 表单元素的vulue发生了改变, 那么, 对应自定义属性也会发生改变。
  • v-model绑定的是data的key值,也就是属性里的数据,表单元素的输入影响了数据,进而影响了div里的插值表达式。

    只能用于表单元素的value上


<html>
<head>
    <meta charset="utf-8" />
    <title>v-modeltitle>
    <script src="vue.js">script>
head>
<body>
    <div id="app">
    	姓名:<input type="text" id="username" v-model="user.username"><br>
    	密码:<input type="password" id="password" v-model="user.password"><br>
    	<input type="button" @click="fun" value="获取">
    div>
    
    <script>
        new Vue({
        	el:'#app', //表示当前vue对象接管了div区域
            data:{
            	user:{username:"",password:""}
            },
            methods:{
            	fun:function(){
            		alert(this.user.username+" "+this.user.password);
            		this.user.username="tom";
            		this.user.password="11111111";
            	}
            }
        });
    script>
body>
html>




<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
    <script src="vue.js">script>
head>
<body>

    <div id="root">
        {{num}}
        <input v-bind:value="num">

        <select v-model="num">
            <option value="1">1option>
            <option value="2">2option>
            <option value="3">3option>
            <option value="4">4option>
        select>

        <textarea v-model="num">textarea>

        <input v-model:value="num">
        
        <input v-model="num">
    div>
    <script>
        new Vue({
            el: "#root",
            data: {
                num: 2
            }
        })
    script>

body>
html>
6.3.3.v-text、v-html
  • 和innerText innerHTML 几乎一样

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
    <script src="vue.js">script>
head>
<body>

    <div id="root">
        <div v-text="obj.name">

        div>
        <div v-text="obj.age">

        div>

        <div v-html="obj.name">
            
        div>
        <div v-html="obj.age">
            
        div>
    div>
    <script>
        new Vue({
            el: "#root",
            data: {
                obj:{
                    name: "zs",
                    age: 18
                }
            }
        })
    script>

body>
html>
6.3.4.v-show
  • 隐藏和显示

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
    <script src="vue.js">script>
head>
<body>

    <div id="root">
        <div v-show="bool">
            <img src="https://dss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=3363295869,2467511306&fm=26&gp=0.jpg">
        div>
        
        <button @click="changeimg">改变button
            
        
        <button v-on:click="f">改变button>
        <button @click="f"> 改变button>
    div>
    <script>
        new Vue({
            el: "#root",
            data: {
               bool: false
            },
            methods: {
                f: function () {
                    // 一定要加this
                  this.bool = !this.bool
                }
            }
        })

        function f() {
            alert('?')
        }
    script>

body>
html>
  • v-on:keydown

<html>
<head>
    <meta charset="utf-8" />
    <title>事件处理title>
    <script src="vue,js">script>
head>
<body>
    <div id="app">
    	
    div>
    <script>
        new Vue({
        	el:'#app', //表示当前vue对象接管了div区域
            methods:{
                fun:function(msg,event){
                    if(!((event.keyCode>=48&&event.keyCode<=57)||event.keyCode==8||event.keyCode==46)){
                    	event.preventDefault();
                    }
                }
            }
        });
    script>
body>
html>
  • v-on:mouseover

<html>
<head>
    <meta charset="utf-8" />
    <title>事件处理title>
    <script src="vue.js">script>
head>
<body>
    <div id="app">
    <div v-on:mouseover="fun1" id="div">
    <textarea v-on:mouseover="fun2($event)">这是一个文件域textarea>
    div>
    div>
    <script>
    new Vue({
        el:'#app', //表示当前vue对象接管了div区域
        methods:{
        	fun1:function(){
        		alert("div");
        	},
        	fun2:function(event){
        		alert("textarea");
        		event.stopPropagation();//阻止冒泡
        	}
        }
    });
    script>
body>
html>
  • 事件修饰符
    • Vue.js 为 v-on 提供了事件修饰符来处理 DOM 事件细节,如:event.preventDefault() 或event.stopPropagation()。
    • Vue.js通过由点(.)表示的指令后缀来调用修饰符。
      • .stop
      • .prevent
      • .capture
      • .self
      • .once
    
    <html>
    <head>
        <meta charset="utf-8" />
        <title>v-on 事件修饰符title>
        <script src="vue.js">script>
    head>
    <body>
        <div id="app">
            <form @submit.prevent action="http://www.itcast.cn" method="get">
                <input type="submit" value="提交">
            form>
            <div @click="fun">
            	<a @click.stop href="http://www.itcast.cn">itcasta>
            div>
        div>
        <script>
            new Vue({
                el:'#app', //表示当前vue对象接管了div区域
                methods:{
                    fun:function(){
                    	alert("hello itcast");
                    }
                }
            });
    	script>
    body>
    html>
    
    • 按键修饰符
      • Vue 允许为 v-on 在监听键盘事件时添加按键修饰符
        • .enter
        • .tab
        • .delete (捕获 “删除” 和 “退格” 键)
        • .esc
        • .space
        • .up
        • .down
        • .left
        • .right
        • .ctrl
        • .alt
        • .shift
        • .meta
    
    <html>
    <head>
        <meta charset="utf-8" />
    	<title>v-on 按钮修饰符title>
    	<script src="vue.js">script>
    head>
    <body>
    	<div id="app">
    		<input type="text" v-on:keyup.enter="fun">
    	div>
        <script>
            new Vue({
            	el:'#app', //表示当前vue对象接管了div区域
            	methods:{
                    fun:function(){
                        alert("你按了回车");
                    }
            	}
            });
        script>
    body>
    html>
    
    
    
    
    <p>
    <input @keyup.alt.67="clear">
    
    <div @click.ctrl="doSomething">Do somethingdiv>
    
6.3.7.v-for: 循环结构
  • v-for:写在哪个标签上, 循环遍历的就是哪个标签
  • 对于v-for遍历语法采用 in/of 都可以, 没有什么区别
  • 在vue中如果使用v-for这个指令, 那么必须给每一个v-for指令所遍历出的元素/标签, 加一个key=”唯一值” ,注意key不可重复
  • Key是一个底层标记是给底层代码用的: 不是给程序员用的

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
    <script src="../vue.js">script>
head>
<body>

    <div id="root">

		
        <div v-for="(item, index)  of arr" :key="index" @click="deletediv(xxx)">
            {{item}}--{{index}}
        div>

        <input v-model="inputstr">
        <button @click="add">添加button>

    div>
    <script>
        new Vue({
            el: "#root",
            data: {
                inputstr: '',
                arr: ["zs", "ls", "wu", "zl"]
            },
            methods: {
                //添加列表项目
                add: function () {
                    this.arr.push(this.inputstr)
                },
                //点击某一项即可删除
                deletediv: function (index) {
                    this.arr.splice(index, 1)
                }
            }
        })
    script>

body>
html>
6.3.8.v-pre:阻止预编译

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
    <script src="../vue.js">script>
head>
<body>

    <div id="root">
        
        <div v-pre>
            {{msg}}
        div>


    div>
    <script>
        new Vue({
            el: "#root",
            data: {
                msg: "zs"
            }
        })
    script>

body>
html>
6.3.9.v-once:只加载一次

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
    <script src="../vue.js">script>
head>
<body>

    <div id="root">

        <div v-once>
            {{msg}}
        div>

        
        {{msg}}
        
        <input v-model="msg">
        
    div>
    <script>
        new Vue({
            el: "#root",
            data: {
                msg: "zs"
            }
        })
    script>


body>
html>
6.3.10.v-cloak:延迟加载
  • Vue对象一旦创建,就会绑定并查看绑定作用域,代码要重新按照vue语法解释一遍, 在这个解释的过程中, 一旦发现V-cloak属性, 会立刻清除。

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
    <script src="../vue.js">script>
    <style>
        
        /*属性选择器*/
        [v-cloak]{
            /*display: none;*/
            font-size: 100px;
        }
    style>
head>
<body>

    <div id="root">
        	
            <div v-cloak>
                {{msg}}
            div>
    div>
    <script>

        //10秒之后执行方法f()
        setTimeout('f()', 10000)
        function f() {
            new Vue({
                el: "#root",
                data: {
                    msg: "zs"
                }
            })
        }
    script>

body>
html>
6.3.11.v-slot
6.4.Vue属性
  • el属性:绑定某个标签的id值,写法如上。
  • data属性:数据属性,一般用于替换插值表达式,key:value写法。
  • method属性:方法属性,用于触发某个事件。
  • computed属性:计算属性,用于实时计算,显示结果。
  • component属性:组件,下一节介绍

    把Vue对象里的可以作为 字符串:{代码块} 写法的均看做属性(key-value性质),不是属性的在这里作为属性统一看待

    
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Titletitle>
        <script src="vue.js">script>
    head>
    <body>
    
        <div id="root">
        	
            {{sum}}
            
            <br>
            <input v-model="num1" ><br>
            <input v-model="num2" >
            
            <hr>
            {{sum2}}
            
        div>
        <script>
            new Vue({
                el: "#root",
                data: {
                    num1: 0,
                    num2: 0
                },
                computed: {
                    // 不是方法, 外在表现是一个属性
                    sum: function () {
                        // 计算属性, 是通过别的属性计算而来, 他是依赖于别的属性的
                        return parseInt(this.num1) + parseInt(this.num2)
                    },
                    sum2: function () {
                        return parseInt(this.num1) + parseInt(this.num2) + this.sum
                    }
                }
            })
        script>
    
    body>
    html>
    
  • watch属性:监听器,监听一个属性改变, 触发一个事件
    
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Titletitle>
        <script src="vue.js">script>
    head>
    <body>
    
    
    <div id="root">
    
        {{sum}}<br>
        <input v-model="num1">
        <input v-model="num2">
    
    div>
    <script>
        new Vue({
            el: "#root",
            data: {
                sum: 0,
                num1: 0,
                num2: 0
            },
            watch: {// 侦听器: 侦听一个属性的改变, 然后触发一个方法
    
                // 方法名, 就是要侦听的属性
                num1: function () {
                   this.sum = parseInt(this.num1) + parseInt(this.num2)
                },
                num2: function () {
                    this.sum = parseInt(this.num1) + parseInt(this.num2)
                }
            }
        })
    script>
    
    body>
    html>
    
  • template属性:模板属性,一个字符串模板作为 Vue 实例的标识使用。模板将会 替换 挂载的元素。挂载元素的内容都将被忽略。
    
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Titletitle>
        <script src="vue.js">script>
    head>
    <body>
        <div id="root">div>
        <script>
            // 以后html写代码, html只需要提供一个入口,
            // html js 都可以在一个vue对象中实现
            new Vue({
                el: "#root",
                data: {
                    msg: "123"
                },
                template:
                	//语法强制要求,template外层必须要有div标签包裹
                	"<div>
                		<div @click='clickdiv'>
                			{{msg}}
            		 	</div>" +
                        "<p @click='clickp'>
                            {{msg}}
                        </p>
            		</div>",
                methods: {
                    clickdiv: function () {
                        this.msg = "div"
                    },
                    clickp: function () {
                        this.msg = "p"
                    }
                }
            })
        script>
    
    body>
    html>
    
  • Example:使用Vue的v指令来实现汇率转换器
    
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Titletitle>
        <script src="../vue.js">script>
    
        <style>
            td {
                width: 200px;
                height: 30px;
                text-align: center;
            }
    
            [colspan] {
                background: red;
            }
    
            div {
                margin: 0 0 5px 0;
            }
    
            select {
                height: 35px;
                text-align: center;
            }
    
            button {
                height: 33px;
            }
    
            input {
                height: 30px;
            }
        style>
    head>
    <body>
    
    <div id="root">
        <div>
            <select v-model="currency1" @change="getrate">
                <option value="0">美元option>
                <option value="1">人民币option>
                <option value="2">欧元option>
                <option value="3">日元option>
                <option value="4">韩币option>
                <option value="5">港币option>
            select>
    
            <button @click="changeselected">互换button>
    
            <select v-model="currency2" @change="getrate">
                <option value="0">美元option>
                <option value="1">人民币option>
                <option value="2">欧元option>
                <option value="3">日元option>
                <option value="4">韩币option>
                <option value="5">港币option>
            select>
    
            数额:
            <input v-model="num" @change="getrate">
            保留小数:
            <select v-model="point" @change="getrate">
                <option value="0">0option>
                <option value="1">1option>
                <option value="2">2option>
                <option value="3">3option>
                <option value="4">4option>
                <option value="5">5option>
                <option value="6">6option>
            select>
    
        div>
        <table border="1">
            <tr>
                <td colspan="3">按当前汇率换算结果td>
            tr>
            <tr>
                <td>{{td11}}td>
                <td>汇率td>
                <td>{{td13}}td>
            tr>
            <tr>
                <td id="td21">{{td21}}td>
                <td id="td22">{{td22}}td>
                <td id="td23">{{td23}}td>
            tr>
    
        table>
    div>
    
    <script>
    
        new Vue({
            el: "#root",
            data: {
                arrRate: [1, 6, 0.9, 100, 1000, 7],
                currencies: ['美元', '人民币', '欧元', '日元', '韩币', '港币'],
                currency1: 1,
                currency2: 0,
                num: 0,
                td11: "人民币",
                td13: "美元",
                td21: 0,
                td22: 0.1667,
                td23: 0,
                point:4
            },
            methods: {
                changeselected: function () {
                    var mid = this.currency1;
                    this.currency1 = this.currency2;
                    this.currency2 = mid;
                    this.getrate();
                },
                getrate: function () {
                    this.td21 = this.num;
                    var num = this.num * this.arrRate[this.currency2] / this.arrRate[this.currency1];
                    this.td23 = num.toFixed(this.point);
    
                    this.td11 = this.currencies[this.currency1];
                    this.td13 = this.currencies[this.currency2];
    
                    var num = this.arrRate[this.currency2] / this.arrRate[this.currency1];
                    this.td22 = num.toFixed(this.point);
    
                }
    
            },
        })
    script>
    
    body>
    html>
    
6.5.Vue组件
  • Vue: 一个Vue对象, 就是一个组件,一个页面可以拆分成多个组件, 一个页面可以拆分成多个vue对象
  • 好处:
    • 模板不至于过于复杂
    • 组件可以复用, vue代码可以复用

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
    <script src="vue.js">script>
head>
<body>

    <div id="root">
    div>

    <script>
        var son1 = {
            template:"
son1
"
, methods: { f: function () { alert(123) } } } var son2 = { template:"
son2
"
} var son3 = { template:"
son3
"
} new Vue({ el: "#root", data: {}, ///Vue组件 components:{ //son1对象替换x标签 x:son1, //son2对象替换y标签 y:son2, //son3对象替换z标签 z:son3, }, template:"
"
, methods: { f: function () { alert(123) } } })
script> body> html>
6.6.Vue的生命周期(钩子)
  • Vue在实例化的过程中,会调用这些生命周期的钩子,给我们提供了执行自定义逻辑的机会。
  • vue在生命周期中有这些状态:
    • beforeCreate(创建之前):数据还没有监听,没有绑定到vue对象实例,同时也没有挂载对象
    • created(创建,较为常用):数据已经绑定到了对象实例,但是还没有挂载对象
    • beforeMount(挂载之前):模板已经编译好了,根据数据和模板已经生成了对应的元素对象,将数据对象关联到了对象的el属性,el属性是一个HTMLElement对象,也就是这个阶段,vue实例通过原生的createElement等方法来创建这个html片段,准备注入到我们vue实例指明的el属性所对应的挂载点
    • mounted(挂载,较为常用):将el的内容挂载到了el,相当于我们在jquery执行了(el).html(el),生成页面上真正的dom,上面我们就会发现dom的元素和我们el的元素是一致的。在此之后,我们能够用方法来获取到el元素下的dom对象,并进行各种操作
    • beforeUpdate(修改之前):data发生改变时,会调用beforeUpdate和updated钩子,数据更新到dom之前,可以看到$el对象已经修改,但是页面上dom的数据还没有发生改变
    • updated(修改):dom结构会通过虚拟dom的原则,找到需要更新页面dom结构的最小路径,将改变更新到dom上面,完成更新
    • active(存储的时候使用,不做介绍)
    • deactived(存储的时候使用,不做介绍)
    • beforeDestroy(消亡之前)
    • destroyed(消亡):实例的销毁,vue实例还是存在的,只是解绑了事件的监听还有watcher对象数据与view的绑定,即数据驱动
    • errorCaptured(异常捕捉,不做介绍)
    
    <html>
    <head>
        <meta charset="utf-8" />
        <title>生命周期title>
        <script src="js/vuejs-2.5.16.js">script>
    head>
    <body>
        <div id="app">
        	{{message}}
        div>
        <script>
        var vm = new Vue({
            el: "#app",
            data: {
                message: 'hello world'
            },
            beforeCreate: function() {
            	console.log(this);
            	showData('创建vue实例前', this);
            },
            created: function() {
            	showData('创建vue实例后', this);
            },
            beforeMount: function() {
            	showData('挂载到dom前', this);
            },
            mounted: function() {
            	showData('挂载到dom后', this);
            },
            beforeUpdate: function() {
            	showData('数据变化更新前', this);
            },
            updated: function() {
            	showData('数据变化更新后', this);
            },
            beforeDestroy: function() {
            	vm.test = "3333";
            	showData('vue实例销毁前', this);
            },
            destroyed: function() {
            	showData('vue实例销毁后', this);
            }
        });
        function realDom() {
        	console.log('真实dom结构:' + document.getElementById('app').innerHTML);
        }
        function showData(process, obj) {
        	console.log(process);
            console.log('data 数据:' + obj.message)
        	console.log('挂载的对象:')
        	console.log(obj.$el)
        	realDom();
        	console.log('------------------')
        	console.log('------------------')
        }
        vm.message="good...";
        vm.$destroy();
    script>
    body>
    html>
    
6.7.创建Vue项目
  1. http://www.nodejs.cn/ 下载node.js安装包,打开msi安装包,会自动安装node.js和npm,
    • 测试是否安装成功:打开cmd,输入node -vnpm -v。查看是否出现版本号。
  2. 打开cmd,输入 npm install -g cnpm --registry=https://registry.npm.taobao.org ,安装cnpm,
    • 测试是否安装成功:打开cmd,输入 cnpm -v,查看是否出现版本号。
  3. 打开cmd,输入 cnpm install -g @vue/cli ,安装cli脚手架工具,卡住了则按ctrl+c,终止批处理操作,重新键入命令安装。
    • 测试是否安装成功: 打开cmd,输入 vue -V (注意V大写) 出现版本号
  4. 打开cmd,输入 cnpm install -g @vue/cli-init ,安装cli桥接工具,等待即可
  5. 打开cmd,输入 cnpm install -g webpack ,安装webpack,
  6. 创建一个vue项目:
    1. 创建一个vue项目,通过cd命令找到要创建的项目的所在目录,输入命令vue init webpack vuetest ,其中vuetest是项目名称
    2. 回车选择默认项目,然后输入n选择no,最后一项的时候选择稍后处理(即最后一个选项)
    3. 下载Vue项目依赖资源,找到vuetest的目录(第一步以后输入cd vuetest即可),输入命令cnpm install -g
    4. 下载完毕后,使用cmd定位到项目所在目录,输入命令 npm run dev 后,浏览器里键入地址localhost://8080即可
  7. 如果已有一个Vue项目,如何拷贝并运行:
    • 将所有除了.idea文件夹和node_modules文件夹的内容全部拷贝
    • cmd定位到当前文件夹,输入cnpm install,下载node_modules依赖资源。
    • 在idea中打开工程

    也可以使用npm,配置国内镜像源 npm config set registry https://registry.npm.taobao.org

6.8.Vue项目结构
  • .idea文件夹:idea运行环境
  • build:js编译后的文件
  • config:配置文件
    • index.js:项目的整体配置
      • proxyTable{} 语句里可以配置代理
      • 对于linux系统,assetsPublicPath: '/' 语句里的/要修改为./
  • node_modules:Vue项目依赖资源
  • src:代码目录,我们写的代码基本都在这里
    • components文件夹:自己定义组件,在这里添加或修改vue的组件
    • main.js
    • App.vue
    • 其他自建相关文件
  • static:
  • index.html:项目的入口
  • package.json:资源包的配置,启动打包配置,基础配置信息

对于一个新创建的Vue项目,加载顺序为:

  1. 首先加载index.html项目入口文件,主要内容仅有一句代码
  2. 进入src目录下寻找main.js文件,找到了一个vue对象,id是与index.html的div标签绑定的
  3. main.js文件中,vue对象里找到了App标签,替换掉index.html中的div标签
  4. 接下来,继续加载App标签是由自己的子组件定义的,而子组件是路径导入的
  5. 找到App.vue文件及它的默认对象,它的模板继续替换掉main.js中的components: { App }组件,只不过模板是定义在顶部的
  6. 显示的内容就是template中的内容,其中的style标签就是他的css样式(id选择器)
6.8.1.index.html
  • 仅有一行语句,
    ,主要是用于Vue的对象绑定以及模板替换
6.8.2.main.js
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
//在同级目录的某个文件夹下,实际上导出的是App.vue的默认导出的对象
import App from './App'

//项目开发的主配置
Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  //绑定了index.html入口文件的div标签
  el: '#app',
  //App子组件,该语句相当于 components:{App:App}, 前者App是标签,后者App是vue对象(文件),真正加载的实际上就是App.vue文件
  components: { App },
  //替换App标签
  template: ''
})
6.8.3.App.vue



<template>
  <div id="app">
    <img src="./assets/logo.png">
    <HelloWorld/>
  div>
template>

<script>
import HelloWorld from './components/HelloWorld'
//默认导出,App.vue向外界暴露的就是这个默认导出的js对象
export default {
  name: 'App',
  components: {
    HelloWorld
  }
}
script>


<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
style>
6.8.4.vue项目实例
  • 模仿淘宝结构,简单的划分淘宝首页的区域
    • component文件夹下文件结构:
      • body1文件夹
        • BodyLeft.vue
        • BodyCenter.vue
        • BodyRight.vue
      • Body1
      • Body2
      • Top1
      • Top2
      • Top3
    • App.vue

    一定要记得在cmd里运行项目,才能在浏览器里localhost://8080查看到页面样式

对于这个简单的项目,vue组件树有如下的结构

							app.vue
								|
	---------------------------------------------------------------
	|		|		|				  |							  |
  top1    top2    top3    			body1    					body2
									  |
						--------------------------------
						|			  |			       |
					BodyLeft	   BodyCenter      BodyRight



<template>
  <div>top1div>
template>

<script>
    export default {
        created() {
            // TODO: 加载数据: 后端
        }
    }
script>

<style scoped>
style>



<template>
  <div>top2div>
template>

<script>
    export default {
        created() {
            // TODO: 加载数据: 后端
        }
    }
script>

<style scoped>
style>




<template>
  <div>top3div>
template>

<script>
    export default {
        created() {
            // TODO: 加载数据: 后端
        }
    }
script>

<style scoped>
style>




<template>
  <div>
    <body-left class="bodyleft">body-left>
    <body-center class="bodycenter">body-center>
    <body-right class="bodyright">body-right>

  div>
template>

<script>
  import BodyLeft from "./body/BodyLeft";
  import BodyCenter from "./body/BodyCenter";
  import BodyRight from "./body/BodyRight";
    export default {
        components: {
            BodyLeft,
            BodyRight,
            BodyCenter
        },
        created() {
            // TODO: 加载数据: 后端
        }
    }
script>

<style scoped>
    
  .bodyleft{
    width: 200px;
    height: 500px;
    background: #16c050;
    float: left;
  }

  .bodycenter{
    width: 700px;
    height: 500px;
    margin-left: 50px;
    background: #c0b446;
    float: left;
  }
  .bodyright{
    width: 200px;
    height: 500px;
    margin-left: 50px;
    background: #c0323c;
    float: left;
  }

style>




<template>
  <div>BodyLeftdiv>
template>

<script>
    export default {
        name: "BodyLeft"
    }
script>

<style scoped>
style>




<template>
  <div>BodyCenterdiv>
template>

<script>
    export default {
        name: "BodyCenter"
    }
script>

<style scoped>
style>




<template>
  <div>BodyRightdiv>
template>

<script>
    export default {
        name: "BodyRight"
    }
script>

<style scoped>
style>




<template>
  <div>body2div>
template>

<script>
    export default {
        created() {
            // TODO: 加载数据: 后端
        }
    }
script>

<style scoped>
style>




<template>
  <div class="app">
    
    
    <top1 class="top1">top1>
    <top2  class="top2">top2>
    <top3 class="top3">top3>
    <body1 class="body1">body1>
    <body2 class="body2">body2>
  div>
template>

<script>
//导入
import Top1 from './components/Top1'
import Top2 from './components/Top2'
import Top3 from './components/Top3'
import Body1 from './components/Body1'
import Body2 from './components/Body2'


export default {
  name: 'App',
  //注册组件
  components: {
      Top1: Top1,
      Top2,
      Top3,
      Body1,
      Body2
  },
    created() {
      // TODO 请求参数比较合适
    }
}
script>

<style>
.app{
  width: 100%;
  height: 1000px;
  /*background: red;*/
}
  .top1{
    width: 100%;
    height: 45px;
    background: silver;
    border-bottom: 1px  solid;
  }
  .top2{
    width: 100%;
    height: 160px;
    background: #c0323c;
  }
  .top3{
    width: 100%;
    height: 30px;
    background: #16c050;
  }
  .body1{
    width: 1200px;
    height: 500px;
    background: antiquewhite;
    margin: 0 auto;
  }
  .body2{
    width: 1200px;
    height: 300px;
    background: #1735fa;
    margin: 0 auto;
  }
style>
6.9.父子组件传值
  • 父子组件传值的步骤
    • 子组件向上抛出一个方法,通知父组件,接收一个方法,
      • this.$emit("方法名",this.参数名)
    • 另外,这个方法携带一个参数
  • 父组件向子组件传值
    • 父传递:
    • 子接收: props: ['url’]
  • Example:父组件向子组件传值
    • component文件结构
      • Son1.vue
      • Son2.vue
    • App.vue

<template>
    
    <div>{{sonname}}div>
template>

<script>
    export default {
        name: "Son1",
        //接收父组件传来的值
        props: ['sonname']
    }
script>

<style scoped>
style>




<template>
    
    <div>{{sonage}}div>
template>

<script>
    export default {
        name: "Son2",
        //接收父组件传来的值
        props: ['sonage']
    }
script>

<style scoped>
style>



<template>
  <div id="app">
    
    <son1 class="son1"  v-bind:sonname="list[0].name">son1>
    
    <son2 class="son2"  :sonage="list[0].age">son2>
  div>
template>

<script>
import Son1 from "./components/Son1";
import Son2 from "./components/Son2";
export default {
    name: 'App',
    data() {
        return{
            list: [{
                name: "zs",
                age: 18
            },
                {
                    name: "ls",
                    age: 20
                }]
        }
    },
    components: {
        Son1,
        Son2
    }
}
script>

<style>
  .son1{
    width: 400px;
    height: 400px;
    border:  1px solid;
    float: left;
  }
  .son2{
    width: 500px;
    height: 400px;
    margin-left: 100px;
    border:  1px solid;
    float: left;
  }
style>
  • 子组件向父组件传值
    • 父接收:
    • 子抛出: this.$emit(‘changeurl’, url)
  • Example:父组件向子组件传值
    • component文件结构
      • Son1.vue
      • Son2.vue
    • App.vue

    这个例子,Son1抛出了参数给父组件App.vue,父组件App.vue再传值给子组件Son2

    $属性的用途:为了说明这是个方法,而不是属性。目的是为了和data的属性区分开


<template>
  <div>
    
    <input v-model="inputstr"><button @click="add">添加button>
  div>
template>

<script>
    export default {
        name: "Son1",
        data(){
            return{
                //初始状态,inputstr为空
                inputstr: ''
            }
        },
        methods: {
            add: function () {
                // 子组件向上抛出一个方法
                // 通知父组件, 接受一个方法:inputmsg
                // 另外, 这个方法携带一个参数:  this.inputstr
                this.$emit("inputmsg", this.inputstr)
            }
        }
    }
script>

<style scoped>
style>




<template>
    <div>
          <ul>
            <li v-for=" (item, index) in list" :key="index">
              {{item}}
            li>
          ul>
    div>
template>

<script>
    export default {
        name: "Son2",
        //Son2接收父组件传来的msg参数,msg参数是子组件抛出的inputstr字符串,而inputstr字符串是我们所输入的
        props:['msg'],
        data(){
            return{
                list: ["zs", "ls", "wu"]
            }
        },
        //监听msg属性的变化,只要父组件的msg发生变化,就给列表添加值
        watch: {
            msg: function () {
                this.list.push(this.msg)
            }
        }
    }
script>

<style scoped>
style>





<template>
  <div id="app">
    
    
    <son1 class="son1" v-on:inputmsg="appinputmsg">son1>
    <son2 class="son2" v-bind:msg="msg">son2>
  div>
template>

<script>
import Son1 from "./components/Son1";
import Son2 from "./components/Son2";
export default {
    name: 'App',
    data() {
        return{
            msg: ''
        }
    },
    methods: {
        //接收到子组件Son1抛出的方法以后,触发这个方法,parame就是Son1抛出的参数
        appinputmsg: function (parame) {
            // alert("Son1抛出的" + parame)
            
            //把Son1抛出的参数赋值给自己的msg属性,使用data的msg属性做一个中转存储
            this.msg = parame
        }
    },
    components: {
        Son1,
        Son2
    }
}
script>

<style>
    .son1{
        width: 400px;
        height: 400px;
        border:  1px solid;
        float: left;
    }
    .son2{
        width: 500px;
        height: 400px;
        margin-left: 100px;
        border:  1px solid;
        float: left;
    }
style>
6.10.VueBus
  • 中央总线事物,类似计算机组成原理
  • 对于某个复杂的结构,我们想实现子组件之间的传值,只能通过公共的父组件来做中转,而VueBus则像是计算机中的总线一样,开辟了一条通路,所有组件连接至VueBus即可,这样子组件之间的传值只需通过总线即可

    可以用生活中的地铁车站来理解,从某个车站(子组件)到另一个车站(子组件),坐一条线路的地铁即可

  • Example:VueBus通信
    • src文件结构:
      • assets文件夹(项目自带)
      • bus(自建,用于配置总线)
        • index.js
      • components文件夹
        • body1文件夹
          • BodyLeft.vue
          • BodyCenter.vue
          • BodyRight.vue
        • Body1.vue
        • Body2.vue
        • Top1.vue
        • Top2.vue
        • Top3.vue
      • App.vue
      • main.js
    • 一般来说,我们在修改项目的相关配置时,一般都会在main.js中修改
    • 假设此项目,我们要在Top1和BodyCenter之间传值(如果不配置总线,只能Top1传值给App,然后App传值给Body1,Body1再传给BodyCenter)



import Vue from 'vue'  // 导入Vue语法
const  vue = new Vue()  // 创建一个Vue对象
export default vue   // 默认导出这个vue对象






// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'

// 从bus文件夹下的index.js 导过来一个Vue对象, 给这个对象起个名字叫vuebus
import vuebus from './bus/index.js'  //由于index.js是默认代表首页写入底层语法中的,所以也可以不加
// 项目全局配置: $bus,可以是任何名称,但是习惯为$bus,也就是说,在项目里,所有Vue对象都有$bus这个属性
Vue.prototype.$bus = vuebus

//原有的vue配置语句
Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
    el: '#app',
    components: { App },
    template: '<App/>'
})



<template>
    <div>top3div>
template>

<script>
    export default {
        created() {
            // TODO: 加载数据: 后端
        }
    }
script>

<style scoped>
style>





<template>
    <div>top2div>
template>

<script>
    export default {
        created() {
            // TODO: 加载数据: 后端
        }
    }
script>

<style scoped>
style>





<template>
    <div>body2div>
template>

<script>
    export default {
        created() {
            // TODO: 加载数据: 后端
        }
    }
script>

<style scoped>
style>





<template>
    <div>
        <body-left class="bodyleft">body-left>
        <body-center class="bodycenter">body-center>
        <body-right class="bodyright">body-right>
    div>
template>

<script>
  import BodyLeft from "./body/BodyLeft";
  import BodyCenter from "./body/BodyCenter";
  import BodyRight from "./body/BodyRight";
    export default {
        components: {
            BodyLeft,
            BodyRight,
            BodyCenter
        },
        created() {
            // TODO: 加载数据: 后端
        }
    }
script>

<style scoped>
    .bodyleft{
        width: 200px;
        height: 500px;
        background: #16c050;
        float: left;
    }

    .bodycenter{
        width: 700px;
        height: 500px;
        margin-left: 50px;
        background: #c0b446;
        float: left;
    }
    .bodyright{
        width: 200px;
        height: 500px;
        margin-left: 50px;
        background: #c0323c;
        float: left;
    }
style>





<template>
    <div>
        <input v-model="inputstr">
        <button @click="add">添加button>
    div>
template>

<script>
    export default {
        data(){
            return{
                inputstr: ''
            }
        },
        methods: {
            add: function () {
                // 抛出方法addmsg,方法携带参数inputstr
                // this: 值得是本对象
                this.$bus.$emit("addmsg", this.inputstr)
            }
        }
    }
script>

<style scoped>
style>






<template>
    <div>
        <ul>
            <li v-for="(item, index) in list"  :key="index">
                {{item}}
            li>
        ul>
    div>
template>

<script>
    export default {
        name: "BodyCenter",
        data(){
            return {
                list: ["zs", "ls", "wu"]
            }
        },
        //生命周期函数
        created() {
            // 监听一个bus事件: 这个事件的名称为addmsg
            // $on: 监听一个事件
            // res : 监听到的方法携带的参数
            // =>: 箭头函数(ES6): 如下作用 把res当做一个参数传到匿名方法里,类似lambda表达式
            this.$bus.$on("addmsg" , res => {
                this.list.push(res)
            })
        }
    }
script>

<style scoped>
style>
    
    



<template>
  <div>BodyLeftdiv>
template>

<script>
    export default {
        name: "BodyLeft"
    }
script>

<style scoped>
style>





<template>
  <div>BodyRightdiv>
template>

<script>
    export default {
        name: "BodyRight"
    }
script>

<style scoped>
style>

个人理解,如何看待VueBus?

  • $bus这个对象/属性就可以看做一列地铁,因为它被配置为全局对象,每个vue文件都可以使用它,那么就相当于开辟了一个VueBus总线
  • 在这列地铁上,某个vue文件抛出了某个方法并携带某个参数,相当于某位乘客上车了,直到另一个vue文件监听到了前面抛出的方法和参数,相当于这位乘客下车了。
6.11.axios
  • Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中
  • 引入axios
    • 首先就是引入axios,如果你使用es6,只需要安装axios模块之后
    import axios from 'axios';
    //安装方法
    npm install axios
    //或
    bower install axios
    
    • 当然也可以用script引入
    <script src="https://unpkg.com/axios/dist/axios.min.js">script>
    
  • get请求
    //通过给定的ID来发送请求
    axios.get('/user?ID=12345')
    	.then(function(response){
    		console.log(response);
    	})
    	.catch(function(err){
    		console.log(err);
    	});
    //以上请求也可以通过这种方式来发送
    axios.get('/user',{
    	params:{
    		ID:12345
    	}
    })
    	.then(function(response){
    		console.log(response);
    	})
    	.catch(function(err){
    		console.log(err);
    	});
    
  • post请求
    axios.post('/user',{
    	firstName:'Fred',
    	lastName:'Flintstone'
    })
    	.then(function(res){
    		console.log(res);
    	})
    	.catch(function(err){
    		console.log(err);
    	});
    
    • 为方便起见,为所有支持的请求方法提供了别名
      • axios.request(config)
      • axios.get(url[, config])
      • axios.delete(url[, config])
      • axios.head(url[, config])
      • axios.post(url[, data[, config]])
      • axios.put(url[, data[, config]])
      • axios.patch(url[, data[, config]])
  • 关于Vue前端请求后端数据的例子
    <template>
      <div id="app">
        <img :src="imgurl">
      div>
    template>
    
    <script>
    
    export default {
        data(){
            return{
                imgurl: ''
            }
        },
        created() {
            //请求后端数据
            this.$axios.get("http://115.29.141.32:8084/api/mall/getGoodsByType?typeId=1")
                //.then是专门用于处理返回参数的,res就是返回参数
                .then(res => {
                    console.log(res)
                    console.log(res.data)
                    console.log(res.data.data)
                    this.imgurl = res.data.data[0].img
                })
        }
    }
    script>
    
    <style>
    style>
    

你可能感兴趣的:(Java)