Vue进阶

Vue

  • 一、MVVM框架概述
  • 二、Vue
    • 2.1、引入Vue所需的js文件
    • 2.2、创建第一个Vue程序
    • 2.3、Vue实例对象的常用数据属性【七大属性】
    • 2.4、Vue实例对象的常用实例属性
    • 2.5、Vue实例对象的常用实例方法
    • 2.6、Vue常用指令
    • 2.7、Vue条件语句
    • 2.8、Vue循环语句
    • 2.9、Vue绑定事件
    • 210、Vue表单【双向数据绑定】
    • 2.11、Vue组件
      • 2.11.1、父组件向子组件传递数据(props)
      • 2.11.2、子组件向父组件传递数据(自定义事件 - -this.$emit())
    • 2.12、计算属性
    • 2.13、监听属性
    • 2.14、样式绑定
    • 2.14、Vue插槽【重点】
    • 2.16、Vue.js 自定义指令【重点】
  • 三、Vue-cli2【脚手架】
    • 3.1、什么是Vue-cli
    • 3.2、安装Vue-cli需要准备的环境
    • 3.3、创建第一个Vue-cli程序
  • 三、Vue-cli3/4【脚手架】
    • 3.1、项目初始化
    • 3.2、项目结构目录
    • 3.3、启动
    • 3.4、设置配置文件
      • 3.4.1、通过 `vue ui`管理配置文件
      • 3.4.2、通过在根目录创建vue.config.js文件
  • 四、Webpack【模块加载器兼打包工具】
    • 4.1、什么是Webpack
    • 4.2、Webpack的安装
    • 4.3、使用Webpack
  • 五、vue-router路由【更新视图但不重新请求页面】【重点】
    • 5.1、vue-router概念
    • 5.2、使用vue-router
    • 5.3、vue-router嵌套
    • 5.4、参数传递及重定向
    • 5.5、重定向
    • 5.6、路由模式
    • 5.7、404
    • 5.8、路由全局守卫
    • 5.9、理解< router-view/>【超重点】
  • 六、Vue.js Ajax(axios)【重点】
    • 6.1、axios概念
    • 6.2、为什么要用axios
    • 6.3、vue生命周期
    • 6.4、axios的使用

一、MVVM框架概述

Vue进阶_第1张图片
MVVM源自于经典的MVC (ModI-View-Controller) 模式。MVVM的核心是ViewModel层,负责转换Model中的数据对象来让数据变得更容易管理和使用

  • ViewModel层的作用
    1、该层向上与视图层进行双向数据绑定
    2、向下与Model层通过接口请求进行数据交互

Vue进阶_第2张图片

  • 为什么要使用MVVM
    1、MVVM模式和MVC模式一样,主要目的是分离视图(View)和模型(Model),有几大好处
    2、低耦合:视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的View上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
    3、可复用:你可以把一些视图逻辑放在一个ViewModel里面,让很多View重用这段视图逻辑。
    4、独立开发:开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计。
    5、可测试:界面素来是比较难于测试的,而现在测试可以针对ViewModel来写。

二、Vue

2.1、引入Vue所需的js文件

1、国内的镜像
<script src="https://cdn.staticfile.org/vue/3.0.5/vue.global.js">script>
2、国外的镜像
<script src="https://unpkg.com/vue@next">script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.0.5/vue.global.js">script>

2.2、创建第一个Vue程序

DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Vuetitle>
    <script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js">script>
head>
<body>
<div id="vue_det">
    <h1>site : {{site}}h1>
    <h1>url : {{details()}}h1>
    <h1>{{mk()}}h1>
div>
<script type="text/javascript">
    var vm = new Vue({
        el: '#vue_det',
        data: {
            site: "倩倩",
            url: "www.taobao.com",
            alexa: "10000"
        },
        methods: {
            details: function() {
                return  this.site + "第一个Vue程序";
            },
            mk:function (){
                return "www.baidu.com";
            }
        },
    })
script>
body>
html>

2.3、Vue实例对象的常用数据属性【七大属性】

  • 创建实例
    每个 Vue 应用都是通过用 Vue 函数创建一个新的 Vue 实例开始的,虽然没有完全遵循 MVVM 模型,但是 Vue 的设计也受到了它的启发。因此在文档中经常会使用 vm (ViewModel 的缩写) 这个变量名表示 Vue 实例。

var vm = new Vue({})

  1. el 元素节点,为Vue对象绑定了根DOM元素。Vue 构造器中有一个el 参数,它是 DOM 元素中的 id
方式一:new Vue时直接指定el的值

    var vm = new Vue({
        el: '#vue_det',
        data: {
            site: "倩倩",
            url: "www.taobao.com",
            alexa: 1
        }
     )};

方式二:先new Vue,后期通过vm.$mount(el)指定el的值

    var vm = new Vue({
        data: {
            site: "倩倩",
            url: "www.taobao.com",
            alexa: 1
        }
     )};
     vm.$mount('#vue_det')
  1. data 数据集合,data 用于定义属性

当一个 Vue 实例被创建时,它将 data 对象中的所有的属性加入到 Vue的响应式系统中。当这些属性的值发生改变时,视图将会产生“响应”,更新为最新的值。但是要注意的是必须是在实例创建的时候就已经存在于data中的属性才是响应式的,如果是在创建实例后追加的属性值,那么他将得不到响应式的更新。如果你需要在创建实例后才用到某些属性值,那么可以在创建实例的开始就为他赋值为空或者其他的一个初始值。

方式一:data是一个对象
    var vm = new Vue({
        el: '#vue_det',
        data: {
            site: "倩倩",
            url: "www.taobao.com",
            alexa: 1
        }
     )};

方式二:data是一个函数

    var vm = new Vue({
        el: '#app',
        data() {
            return {
                title:"王倩老师",
                todoItems:['qianqian',"倩倩","王倩倩"]
            };
        }
    });
  1. methods 方法必须定义Vue的Method对象中,用于定义的函数,可以通过 return 来返回函数值
  2. template:用来设置模板,会替换页面元素,包括占位符
  3. conputed:用来计算
  4. vender:创建真正的Virtual Dom
  5. watch:监听data中数据的变化

2.4、Vue实例对象的常用实例属性

  1. vm.$el:该实例属性用于获取Vue实例使用的根DOM元素,即el选项所指的元素DOM
  2. vm.$data:Vue 实例观察的数据对象。Vue 实例代理了对其 data 对象属性的访问,即可以访问data选项中的数据。
  3. vm.$options:用于当前 Vue 实例的初始化选项。需要在选项中包含自定义属性时会有用处。
  4. vm.$refs:返回持有注册过 ref 特性 的所有 DOM 元素和组件实例,该类型为Object,且只读。因为有好多ref,所以通过.名称获得组件实例。
  5. vm.$root:当前组件树的根 Vue 实例。如果当前实例没有父实例,此实例将会是其自己。

2.5、Vue实例对象的常用实例方法

  1. vm.$watch:观察Vue实例变化中的一个表达式或计算属性函数。监视某个属性,如果被更该,将执行回调函数。表达式只接受监督的键路径。对于更复杂的表达式,用一个函数取代。
vm.$watch( expOrFn, callback, [options] )

1、第一个参数为表达式或计算属性函数,也可以是一个属性。
2、第二个参数为,触发的回调函数
3、第三个参数为,可添加的选项

2.6、Vue常用指令

  1. 数据绑定最常见的形式就是使用 {{...}}(双大括号)的文本插值
  2. 使用 v-html 指令用于输出 html 代码
  3. HTML 属性中的值应使用 v-bind 指令
  4. v-text 改变指定元素的文本值
  5. v-show 是否显示该元素(实质改变display)
  6. v-model 指令用来在 input、select、textarea、checkbox、radio 等表单控件元素上创建双向数据绑定,根据表单上的值,自动更新绑定的元素的值。

2.7、Vue条件语句

  1. v-if
  2. v-else
  3. v-else-if
<div id="app">
    <div v-if="type === 'A'">
      A
    div>
    <div v-else-if="type === 'B'">
      B
    div>
    <div v-else-if="type === 'C'">
      C
    div>
    <div v-else>
      Not A/B/C
    div>
div>
    
<script>
new Vue({
  el: '#app',
  data: {
    type: 'C'
  }
})
script>
  1. v-show: v-show 指令来根据条件展示元素

2.8、Vue循环语句

  1. v-for:v-for 指令需要以 site in sites 形式的特殊语法, sites 是源数据数组并且 site 是数组元素迭代的别名。

这里是引用

  • v-for迭代数组
<body>
<div id="for_div">
    <ol>
        <li v-for="s in str">
            {{s.name}}
        li>
    ol>
div>
<script type="text/javascript">
    var vm=new Vue({
        el:'#for_div',
        data:{
            str:[
                {name:'宝宝'},
                {name:'倩倩'},
                {name:'好可爱'}
            ]

        }
    });
script>
body>
  • v-for迭代对象
<body>
<div id="for_div">
    <ol>
        <li v-for="value in object">
            {{value}}
        li>
    ol>
div>
<script type="text/javascript">
    var vm=new Vue({
        el:'#for_div',
        data:{
            object:{
                name:'倩倩',
                age:18,
                sex:"女"

            }

        }
    });
script>
body>
  • v-for可以提供第二个的参数为键名,第三个参数为索引
<body>
<div id="for_div">
    <ol>
        <li v-for="(value,key,index) in object">
            {{index}}---{{key}}---{{value}}
        li>
    ol>
div>
<script type="text/javascript">
    var vm=new Vue({
        el:'#for_div',
        data:{
            object:{
                name:'倩倩',
                age:18,
                sex:"女"
            }
        }
    });
script>
body>
  • v-for可以迭代整数
<div id="for_div">
    <ol>
        <li v-for="num in 50">
            {{num}}
        li>
    ol>
div>

2.9、Vue绑定事件

  • v-on
<body>
<div id="app">
    
    <button v-on:click="greet">Greetbutton>
div>

<script>
    var app = new Vue({
        el: '#app',
        data: {
            name: 'Vue.js'
        },
        // 在 `methods` 对象中定义方法
        methods: {
            greet: function (event) {
                // `this` 在方法里指当前 Vue 实例
                alert('Hello ' + this.name + '!')
                // `event` 是原生 DOM 事件
                if (event) {
                    alert(event.target.tagName)
                }
            }
        }
    })
    
script>
body>
  • 事件修饰符

<a v-on:click.stop="doThis">a>

<form v-on:submit.prevent="onSubmit">form>

<a v-on:click.stop.prevent="doThat">a>

<form v-on:submit.prevent>form>

<div v-on:click.capture="doThis">...div>

<div v-on:click.self="doThat">...div>


<a v-on:click.once="doThis">a>

210、Vue表单【双向数据绑定】

注意:v-model其实是一个语法糖,他的背后本质上包含两个操作,v-model相当于v-bind(语法糖为 :)绑定一个value属性,可以实时获取value属性的值和v-on(语法糖为 @)指令给当前元素绑定input事件的结合
$event获取原生DOM事件的事件对象
Vue进阶_第3张图片

  • 可以用 v-model 指令在表单控件元素上创建双向数据绑定。
  • 输入框
<body>
<div id="app">
    <p>input 元素:p>
    <input v-model="message" placeholder="编辑我……">
    <p>消息是: {{ message }}p>

    <p>textarea 元素:p>
    <p style="white-space: pre">{{ message2 }}p>
    <textarea v-model="message2" placeholder="多行文本输入……">textarea>
div>
<script>
    new Vue({
        el: '#app',
        data: {
            message: '你好呀!倩倩',
            message2: '两个人相互辉映,光芒胜过夜晚繁星'
        }
    })
script>
body>
  • 单选框和复选框
    注意:label的作用:在有选择框时,如果没有label必须选择选择框才能进行选择,而直接选择文字不可以,反之,label的作用就是在点击文字的同时可以选中选择框,但是要注意的是一般情况下一个label绑定一个input

Vue进阶_第4张图片
注意:单选框对应的是一个布尔值,多选框对应的是一个数组

<body>
<div id="app">
    <p>单选框p>

    <input type="radio" id="boy" name="sex" value="" v-model="message">
    <label for="boy">label>
    <input type="radio" id="girl" name="sex" value="" v-model="message">
    <label for="girl">label><br>
    <span>您当前选中的内容为:{{message}}span>

    <p>复选框p>
    <p>单个复选框:p>
    <input type="checkbox" id="checkbox" v-model="checked">
    <label for="checkbox">{{ checked }}label>

    <p>多个复选框:p>
    <input type="checkbox" id="baidu" value="baidu" v-model="checkedNames">
    <label for="baidu">baidulabel>
    <input type="checkbox" id="google" value="Google" v-model="checkedNames">
    <label for="google">Googlelabel>
    <input type="checkbox" id="taobao" value="Taobao" v-model="checkedNames">
    <label for="taobao">taobaolabel>
    <br>
    <span>选择的值为: {{ checkedNames }}span>

div>
<script>
    new Vue({
        el: '#app',
        data: {
            message: '',
            checked:'',
            checkedNames:[]
        }
    })
script>
body>
  • 下拉菜单
<body>
<div id="app">
    <select v-model="selected" name="fruit">
        <option value="">选择一个网站option>
        <option value="www.baidu.com">Baiduoption>
        <option value="www.google.com">Googleoption>
    select>
    <div id="output">
        选择的网站是: {{selected}}
    div>
div>
<script>
    new Vue({
        el: '#app',
        data: {
            selected: ''
        }
    })
script>
body>
  • 值绑定:value
    Vue进阶_第5张图片

  • v-model修饰符
    Vue进阶_第6张图片
    Vue进阶_第7张图片

2.11、Vue组件

组件可以扩展 HTML 元素,封装可重用的代码,
组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树

Vue进阶_第8张图片

  • 语法糖
    Vue进阶_第9张图片

  • 全局组件

Vue.component(tagName, options)

tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件:

<body>
<div id="app">

    <box>box>

div>
<script>
    Vue.component("box",{
        template:"

自定义组件

"
}); new Vue({ el: '#app', data: { message:["qianqian","xiangni","xixi"] } })
script> body>
  • 局部组件
<body>
<div id="app">
    <box>box>只可以在父模块中使用
div>

<box>box>这个标签则不可以使用

<script>
    var Child = {
        template: '

自定义组件!

'
} // 创建根实例 new Vue({ el: '#app', components: { // 将只在父模板可用,只能在他对应的el中使用 'box': Child } })
script> body>

注意:可以看出来app是我们顶级父级组件,俗称root
Vue进阶_第10张图片

  • 组件数据的存放
    Vue进阶_第11张图片
  • 为什么组件中的data的属性必须是一个函数呢
    1、如果组件中的data不是函数的话,那么多个组件将会共享同一个数据,其中一个组件上对数据做出的改变,也会影响另一个组件上的数据 。
    2、组件上的data是函数的情况下,组件每次调用data里面的数据,都是由data这个独有的函数返回过来的数据,所以不会造成这个组件更改data的数据,另一个在使用这个数据的组件也会更改这个数据

2.11.1、父组件向子组件传递数据(props)

  • Props
    prop 是子组件用来接受父组件传递过来的数据的一个自定义属性。
    父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 “prop”:
<body>
<div id="app">
    <child message="hello!">child>
div>

<script>
    // 注册
    Vue.component('child', {
        // 声明 props
        props: ['message'],
        // 同样也可以在 vm 实例中像 “this.message” 这样使用
        template: '{{ message }}'
    })
    // 创建根实例
    new Vue({
        el: '#app'
    })
script>
body>
  • 动态 Prop
<body>
<div id="app">
    <div>
        <input v-model="parentMsg">
        <br>
        <child v-bind:message="parentMsg">child>
    div>
div>

<script>
    // 注册
    Vue.component('child', {
        // 声明 props
        props: ['message'],
        // 同样也可以在 vm 实例中像 “this.message” 这样使用
        template: '{{ message }}'
    })
    // 创建根实例
    new Vue({
        el: '#app',
        data: {
            parentMsg: '父组件内容'
        }
    })
script>
body>
<body>
<div id="app">
    <box v-for="person in qianqian " v-bind:str="person">box>
div>

<script>
    Vue.component("box",{
        props:["str"],
        template:"
  • {{str}}
  • "
    }); new Vue({ el:"#app", data:{ qianqian:{ name:"倩倩", age:18, sex:"仙女" } } });
    script> body>

    2.11.2、子组件向父组件传递数据(自定义事件 - -this.$emit())

    注意:父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!

    • 使用 v-on 绑定自定义事件
      1、使用 $on(eventName) 监听事件,监听当前实例上的自定义事件。事件可以由 vm.$ emit触发。回调函数会接收所有传入事件触发函数的额外参数
      2、使用 $emit(eventName) 触发事件,Vue子组件向父组件传值
    <body>
    <div id="app">
        <div id="counter-event-example">
            <p>{{ total }}</p>
            <button-counter v-on:increment="incrementTotal"></button-counter>
            <button-counter v-on:increment="incrementTotal"></button-counter>
        </div>
    </div>
    
    <script>
        Vue.component('button-counter', {
            template: '',
            data: function () {
                return {
                    counter: 0
                }
            },
            methods: {
                incrementHandler: function () {
                    this.counter += 1
                    this.$emit('increment')
                }
            },
        })
        new Vue({
            el: '#counter-event-example',
            data: {
                total: 0
            },
            methods: {
                incrementTotal: function () {
                    this.total += 1
                }
            }
        })
    </script>
    </body>
    
    • 上述执行流程的理解

    Vue进阶_第12张图片

    • 案例分析
     <body>
    
    <div id="app">
      
      <cpn @item-click="cpnClick">cpn>
    div>
      
    <template id="cpn">
      <div>
        <button v-for="item in categories" @click="btnClick(item)">{{item.name}}button><br/>
      div>
    template>
    
    <script type="text/javascript">
    //创建子组件
    const sonCpn={
      //关联字符串模板
      template:'#cpn',
      //子组件的data必须是函数function而不能是对象
      data(){
        return {
          categories:[
            {id:'aa',name:'热门推荐'},
            {id:'bb',name:'手机数码'},
            {id:'cc',name:'家用电器'},
            {id:'dd',name:'电脑显卡'},
          ]
        }
      },
      
      methods:{
        //创建子组件向父组件传值的事件响应函数
        btnClick(item){
          //向父组件传值,定义一个子组件发出的自定义事件(itemClick)
          //第一个参数是自定义事件名
          //第二个参数是发射出去的信息,传给父组件的监听函数
          this.$emit('item-click',item)
    
        }
      }
    
    }
    var app=new Vue({
      el:"#app",
      
      data:{
        
      },
      methods:{
        //创建父组件的监听函数,item是子组件$emit()传递过来的值
        cpnClick(item){
          console.log(item.name);
        }
      },
      components:{
        'cpn':sonCpn//这里也可以直接按es6的写法,写为cpn
      }
    }
      
    );
    
    script>
    body>
    
    

    第一步:子组件通过自定义事件获取到要传递给父组件的数据
    第二步:子组件通过this.$emit(‘item-click’,item)将数据发出
    第三步:父组件通过@item-click="cpnClick"接收数据
    第四步:父组件使用自己的方法cpnClick进行数据处理

    2.12、计算属性

    • computed计算属性
      计算属性的重点突出在属性两个字上(属性是名词),首先它是个属性,其次这个属性有计算的能力(计算是动词),这里的计算就是个函数,简单的说,他就是一个能够将计算结果缓冲起来的属性(将行为转化成了静态的属性)。
    <body>
    <div id="app">
        <p>原始字符串: {{ message }}p>
        <p>计算后反转字符串: {{ reversedMessage }}p>
    div>
    
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                message: '123456789'
            },
            computed: {
                // 计算属性的 getter
                reversedMessage: function () {
                    // `this` 指向 vm 实例
                    return this.message.split('').reverse().join('')
                }
            }
        });
    script>
    body>
    
    • computed vs methods
      我们可以使用 methods 来替代 computed,效果上两个都是一样的,但是 computed 是基于它的依赖缓存,只有相关依赖发生改变时才会重新取值。而使用 methods ,在重新渲染的时候,函数总会重新调用执行
    computed属性:
    
    computed: {
       // 计算属性的 getter
       reversedMessage: function () {
       // `this` 指向 vm 实例
       return this.message.split('').reverse().join('')
        }
    }
    methods属性:
    
    methods: {
      reversedMessage2: function () {
        return this.message.split('').reverse().join('')
      }
    }
    

    2.13、监听属性

    vm.$watch( expOrFn, callback, [options] )
    
    1、第一个参数为表达式或计算属性函数,也可以是一个属性。
    2、第二个参数为,触发的回调函数
    3、第三个参数为,可添加的选项
    
    <body>
    <div id="app">
        <p>原始字符串: {{ message }}p>
        <p>计算后反转字符串: {{ reversedMessage }}p>
    div>
    
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                message: '123456789'
            },
            computed: {
                // 计算属性的 getter
                reversedMessage: function () {
                    // `this` 指向 vm 实例
                    return this.message.split('').reverse().join('')
                }
            },
        });
        vm.$watch("message",function (newVal,oldVal) {
            alert("message的值由"+oldVal+"变为"+newVal);
        });
    script>
    body>
    
    • 通过watch属性也可以实现监听
    <body>
    <div id="app">
        <p>原始字符串: {{ message }}p>
        <p>计算后反转字符串: {{ reversedMessage }}p>
    div>
    
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                message: '123456789'
            },
            computed: {
                // 计算属性的 getter
                reversedMessage: function () {
                    // `this` 指向 vm 实例
                    return this.message.split('').reverse().join('')
                }
            },
            watch:{
                message:{
                    handler:function (newVal,oldVal) {
                        alert("message的值由"+oldVal+"变为"+newVal);
                    }
                }
            }
        });
    script>
    body>
    
    • watch和vm.$watch的区别
    <body>
    <div id = "computed_props">
        千米 : <input type = "text" v-model = "kilometers">
        米 : <input type = "text" v-model = "meters">
    div>
    <p id="info">p>
    <script type = "text/javascript">
        var vm = new Vue({
            el: '#computed_props',
            data: {
                kilometers : 0,
                meters:0
            },
            methods: {
            },
            computed :{
            },
            watch : {
                kilometers:function(val) {
                    this.kilometers = val;
                    this.meters = this.kilometers * 1000
                },
                meters : function (val) {
                    this.kilometers = val/ 1000;
                    this.meters = val;
                }
            }
        });
        // $watch 是一个实例方法
        vm.$watch('kilometers', function (newValue, oldValue) {
            // 这个回调将在 vm.kilometers 改变后调用
            document.getElementById ("info").innerHTML = "修改前值为: " + oldValue + ",修改后值为: " + newValue;
        })
    script>
    body>
    

    2.14、样式绑定

    class 与 style 是 HTML 元素的属性,用于设置元素的样式,我们可以用 v-bind 来设置样式属性。

    Vue.js v-bind 在处理 class 和 style 时, 专门增强了它。表达式的结果类型除了字符串之外,还可以是对象或数组。

    • class属性绑定

    我们可以为 v-bind:class 设置一个对象,从而动态的切换 class:

    <style>
    .active {
    	width: 100px;
    	height: 100px;
    	background: green;
    }
    style>
    <body>
    <div id="app">
      <div v-bind:class="{ 'active': isActive }">div>
    div>
    
    <script>
    new Vue({
      el: '#app',
      data: {
        isActive: true
      }
    })
    script>
    body>
    
    <style>
    .active {
    	width: 100px;
    	height: 100px;
    	background: green;
    }
    .text-danger {
    	background: red;
    }
    style>
    head>
    <body>
    <div id="app">
      <div class="static"
         v-bind:class="{ 'active': isActive, 'text-danger': hasError }">
      div>
    div>
    
    <script>
    new Vue({
      el: '#app',
      data: {
        isActive: true,
    	hasError: true
      }
    })
    script>
    body>
    

    我们也可以在这里绑定返回对象的计算属性。这是一个常用且强大的模式
    我们可以把一个数组传给 v-bind:class

    • Vue.js style(内联样式)
    <body>
    <div id="app">
    	<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }">菜鸟教程div>
    div>
    
    <script>
    new Vue({
      el: '#app',
      data: {
        activeColor: 'green',
    	fontSize: 30
      }
    })
    script>
    body>
    

    2.14、Vue插槽【重点】

    插槽就是子组件中的提供给父组件使用的一个占位符,用 表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的标签。

    2.16、Vue.js 自定义指令【重点】

    • 方式一:通过Vue.directive注册【可以在全局中使用】
    <body>
        <div id="app">
            <input v-size>
        </div>
    <script type="text/javascript">
        //注册一个全局指令
        Vue.directive('size',{
            // 当绑定元素插入到 DOM 中。
            inserted:function (el) {
                el.focus()
            }
        });
        new Vue({
            el:'#app'
        });
    </script>
    </body>
    
    • 方式二:实例使用 directives 选项来注册局部指令,【指令只能在这个实例中使用】
    <body>
    <div id="app">
      <p>页面载入时,input 元素自动获取焦点:</p>
    
    </div>
    <input v-focus>此时这里不可以使用指令
    <script>
    // 创建根实例
    new Vue({
      el: '#app',
      directives: {
        // 注册一个局部的自定义指令 v-focus
        focus: {
          // 指令的定义
          inserted: function (el) {
            // 聚焦元素
            el.focus()
          }
        }
      }
    })
    </script>
    </body>
    
    • 钩子
    • 1、钩子函数
    bind: 只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。
    
    inserted: 被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document 中)。
    
    update: 被绑定元素所在的模板更新时调用,而不论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新(详细的钩子函数参数见下)。
    
    componentUpdated: 被绑定元素所在模板完成一次更新周期时调用。
    
    unbind: 只调用一次, 指令与元素解绑时调用。
    
    • 2、钩子函数参数
    1、el: 指令所绑定的元素,可以用来直接操作 DOM2、binding: 一个对象,包含以下属性:
    	name: 指令名,不包括 v- 前缀。
    	value: 指令的绑定值, 例如: v-my-directive="1 + 1", value 的值是 2。
    	oldValue: 指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
    	expression: 绑定值的表达式或变量名。 例如 v-my-directive="1 + 1" , expression 的值是 "1 + 1"。
    	arg: 传给指令的参数。例如 v-my-directive:foo, arg 的值是 "foo"。
    	modifiers: 一个包含修饰符的对象。 例如: v-my-directive.foo.bar, 修饰符对象 modifiers 的值是 { foo: true, bar: true }3、vnode: Vue 编译生成的虚拟节点。
    4、oldVnode: 上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
    
    <div id="app"  v-runoob:hello.a.b="message">
    </div>
     
    <script>
    Vue.directive('runoob', {
      bind: function (el, binding, vnode) {
        var s = JSON.stringify
        el.innerHTML =
          'name: '       + s(binding.name) + '
    '
    + 'value: ' + s(binding.value) + '
    '
    + 'expression: ' + s(binding.expression) + '
    '
    + 'argument: ' + s(binding.arg) + '
    '
    + 'modifiers: ' + s(binding.modifiers) + '
    '
    + 'vnode keys: ' + Object.keys(vnode).join(', ') } }) new Vue({ el: '#app', data: { message: '菜鸟教程!' } }) </script>

    三、Vue-cli2【脚手架】

    3.1、什么是Vue-cli

    1、vue-cli 官方提供的一个脚手架,用于快速生成一个 vue 的项目模板;
    2、预先定义好的目录结构及基础代码,就好比咱们在创建 Maven 项目时可以选择创建一个骨架项目,这个骨架项目就是脚手架,我们的开发更加的快速;

    • 主要功能
       统一的目录结构
       本地调试
       热部署
       单元测试
       集成打包上线

    3.2、安装Vue-cli需要准备的环境

    • 1、安装Node.jsNode.js : http://nodejs.cn/download/
      Vue进阶_第13张图片

    • 2、安装淘宝镜像:npm install cnpm -g

    • 3、安装Vue-cli:cnpm install vue-cli -g
      Vue进阶_第14张图片

    3.3、创建第一个Vue-cli程序

    • Vue-cli项目结构目录

    Vue进阶_第15张图片

    • 1、切换到需要创建的目录中

    • 2、执行vue init webpack myvue:myvue 是项目名称

    • 3、初始化
      Vue进阶_第16张图片

    • 4、创建完毕的目录
      Vue进阶_第17张图片

    • 5、进入当前目录并初始化项目

    cd myvue
    npm install 初始化项目
    

    Vue进阶_第18张图片

    • 6、运行项目npm run dev

    Vue进阶_第19张图片
    运行成功
    Vue进阶_第20张图片

    三、Vue-cli3/4【脚手架】

    3.1、项目初始化

    • 检查自己的vue-cli版本,如果是2,升级到3或4
    npm install -g @vue/cli
    
    • 创建项目
      在这里插入图片描述
    • 选择配置,会询问是否使用taobao镜像,vue-cli4已经默认支持vue3
      Vue进阶_第21张图片
    • 选择手动配置,空格键可以选中或者取消选中Vue进阶_第22张图片
    • 选择vue的版本
      Vue进阶_第23张图片
    • 是否采用history模式
      在这里插入图片描述
    • 选择css的处理模式
      Vue进阶_第24张图片
    • 是否将添加的配置抽取成一个独立的json文件
      在这里插入图片描述
    • 是否要保存这次创建方式,方便下次可以直接创建
      Vue进阶_第25张图片

    在这里插入图片描述

    • 创建成功
      Vue进阶_第26张图片

    3.2、项目结构目录

    Vue进阶_第27张图片

    3.3、启动

    npm run serve
    

    Vue进阶_第28张图片
    Vue进阶_第29张图片

    3.4、设置配置文件

    3.4.1、通过 vue ui管理配置文件

    Vue进阶_第30张图片

    Vue进阶_第31张图片

    3.4.2、通过在根目录创建vue.config.js文件

    注意:文件名不能随意修改
    Vue进阶_第32张图片

    四、Webpack【模块加载器兼打包工具】

    4.1、什么是Webpack

    1、本质上,webpack是一个现代JavaScript应用程序的静态模块打包器(module bundler)。当webpack处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个bundle.
    2、Webpack是当下最热门的前端资源模块化管理和打包工具,它可以将许多松散耦合的模块按照依赖和规则打包成符合生产环境部署的前端资源。还可以将按需加载的模块进行代码分离,等到实际需要时再异步加载。通过loader转换,任何形式的资源都可以当做模块,比如CommonsJS、AMD、ES6、 CSS、JSON、CoffeeScript、LESS等;
    3、伴随着移动互联网的大潮,当今越来越多的网站已经从网页模式进化到了WebApp模式。它们运行在现代浏览器里,使用HTML5、CSS3、ES6 等新的技术来开发丰富的功能,网页已经不仅仅是完成浏览器的基本需求; WebApp通常是一个SPA (单页面应用) ,每一个视图通过异步的方式加载,这导致页面初始化和使用过程中会加载越来越多的JS代码,这给前端的开发流程和资源组织带来了巨大挑战。
    4、前端开发和其他开发工作的主要区别,首先是前端基于多语言、多层次的编码和组织工作,其次前端产品的交付是基于浏览器的,这些资源是通过增量加载的方式运行到浏览器端,如何在开发环境组织好这些碎片化的代码和资源,并且保证他们在浏览器端快速、优雅的加载和更新,就需要一个模块化系统,这个理想中的模块化系统是前端工程师多年来一直探索的难题。

    4.2、Webpack的安装

    npm install webpack -g
    npm install webpack-cli -g
    

    安装成功
    Vue进阶_第33张图片

    4.3、使用Webpack

    • 1、创建一个空的idea项目
    • 2、在idea中创建modules包,再创建hello.js。hello.js 暴露接口 相当于Java中的类
    //暴露模块
    exports.sayHi=function () {
        document.write("

    王倩倩

    "
    ) }
    • 3、创建main.js 当作是js主入口,main.js 请求hello.js 调用sayHi()方法
    //引入模块
    var hello=require("./hello");
    hello.sayHi();
    
    • 4、在主目录创建webpack.config.js
      webpack.config.js 这个相当于webpack的配置文件 enrty请求main.js的文件 output是输出的位置和名字
    module.exports={
        entry:'./modules/main.js',
        output:{
            filename:"./js/bundle.js"
        }
    };
    

    注意
    1、如果是 v4.0.0 以上版本的 webpack,可以不使用配置文件配置 webpack ,使用官网推荐的使用 ./src/index.js 作为入口点
    2、官方中明确说明,如果使用配置文件使用 webpack 打包项目,则文件名是 webpack.config.js 。
    3、检查 webpack.config.js 的路径是否出错,webpack.config.js 必须是放在根目录下

    • 5、使用webpack打包
      打包成功后显示
      在这里插入图片描述

    • 6、在主目录创建index.html 导入bundle.js

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

    运行成功
    Vue进阶_第34张图片

    • 模块化开发
      1、将一个复杂的程序依据一定的规则(规范)封装成几个块(文件), 并进行组合在一起
      2、块的内部数据与实现是私有的, 只是向外部暴露一些接口(方法)与外部其它模块通信
    • 基本语法
      1、暴露模块:module.exports = value或exports.xxx = value/
      2、引入模块:require(xxx),如果是第三方模块,xxx为模块名;如果是自定义模块,xxx为模块文件路径

    五、vue-router路由【更新视图但不重新请求页面】【重点】

    5.1、vue-router概念

    Vue.js 路由允许我们通过不同的 URL 访问不同的内容。

    • 包含的功能
      1、嵌套的路由/视图表/
      2、模块化的、基于组件的路由配置
      3、路由参数、查询、通配符
      4、基于 Vue.js 过渡系统的视图过渡效果
      5、细粒度的导航控制
      6、带有自动激活的 CSS class 的链接
      7、HTML5 历史模式或 hash 模式,在 IE9 中自动降级
      8、自定义的滚动条行为

    < router-link> 是一个组件,该组件用于设置一个导航链接,切换不同 HTML 内容。 to 属性为目标地址, 即要显示的内容,< router-link> 默认会被渲染成一个 标签

    < router-view>路由匹配到的组件将渲染在这里

    Vue进阶_第35张图片

    5.2、使用vue-router

    • 1、安装vue-router
    npm install vue-router --save-dev
    
    • 2、安装路由,在src目录下,新建一个文件夹 : router,专门存放路由、index.js(默认配置文件都是这个名字)
    import Vue from 'vue'
    import VueRouter from 'vue-router'
    
    //导入自己所需的组件
    import Content from "../components/Content";
    import Main from "../components/Main";
    
    //安装路由
    Vue.use(VueRouter);
    
    //配置导出路由
    
    export default new VueRouter({
      routes:[{
        //路由的路径
        path:'/content',
        name:'content',
        //跳转的组件
        component:Content
      },
        {
          path:'/main',
          name:'content',
          //跳转的组件
          component:Main
        }
      ]
    });
    
    
    • 3、在main.js中配置路由

    注意:router必须放到components: { App },的前边

    import Vue from 'vue'
    import App from './App'
    import router from './router'//自动扫描里面的路由配置
    Vue.config.productionTip = false
    
    /* eslint-disable no-new */
    new Vue({
      el: '#app',
      //配置路由
      router,
      components: { App },
      template: ''
    })
    
    • 4、测试

    Vue进阶_第36张图片

    5.3、vue-router嵌套

    < template>:所有的元素必须在根节点下
    实际应用界面,通常由多层嵌套的组件组合而成。children属性
    比如,我们 “首页”组件中,还嵌套着 “登录”和 “注册”组件,那么URL对应就是/home/login和/home/reg。

    • 创建用户信息组件,在 views/user 目录下创建一个名为 Profile.vue 的视图组件
    <template>
      <h1>个人信息</h1>
    </template>
    <script>
      export default {
        name: "UserProfile"
      }
    </script>
    <style scoped>
    </style>
    
    
    • 在用户列表组件在 views/user 目录下创建一个名为 List.vue 的视图组件
    <template>
      <h1>用户列表</h1>
    </template>
    <script>
      export default {
        name: "UserList"
      }
    </script>
    <style scoped>
    </style>
    
    • 修改首页视图,我们修改 Main.vue 视图组件,此处使用了 ElementUI 布局容器组件,代码如下
    <template>
        <div>
          <el-container>
            <el-aside width="200px">
              <el-menu :default-openeds="['1']">
                <el-submenu index="1">
                  <template slot="title"><i class="el-icon-caret-right"></i>用户管理</template>
                  <el-menu-item-group>
                    <el-menu-item index="1-1">
                    <!--插入的地方-->
                      <router-link to="/user/profile">个人信息</router-link>
                    </el-menu-item>
                    <el-menu-item index="1-2">
                    <!--插入的地方-->
                      <router-link to="/user/list">用户列表</router-link>
                    </el-menu-item>
                  </el-menu-item-group>
                </el-submenu>
                <el-submenu index="2">
                  <template slot="title"><i class="el-icon-caret-right"></i>内容管理</template>
                  <el-menu-item-group>
                    <el-menu-item index="2-1">分类管理</el-menu-item>
                    <el-menu-item index="2-2">内容列表</el-menu-item>
                  </el-menu-item-group>
                </el-submenu>
              </el-menu>
            </el-aside>
    
            <el-container>
              <el-header style="text-align: right; font-size: 12px">
                <el-dropdown>
                  <i class="el-icon-setting" style="margin-right: 15px"></i>
                  <el-dropdown-menu slot="dropdown">
                    <el-dropdown-item>个人信息</el-dropdown-item>
                    <el-dropdown-item>退出登录</el-dropdown-item>
                  </el-dropdown-menu>
                </el-dropdown>
              </el-header>
              <el-main>
              <!--在这里展示视图-->
                <router-view />
              </el-main>
            </el-container>
          </el-container>
        </div>
    </template>
    <script>
        export default {
            name: "Main"
        }
    </script>
    <style scoped lang="scss">
      .el-header {
        background-color: #B3C0D1;
        color: #333;
        line-height: 60px;
      }
      .el-aside {
        color: #333;
      }
    </style>
    
    
    • 配置嵌套路由修改 router 目录下的 index.js 路由配置文件,使用children放入main中写入子模块
    //导入vue
    import Vue from 'vue';
    import VueRouter from 'vue-router';
    //导入组件
    import Main from "../views/Main";
    import Login from "../views/Login";
    //导入子模块
    import UserList from "../views/user/List";
    import UserProfile from "../views/user/Profile";
    
    //使用
    Vue.use(VueRouter);
    //导出
    export default new VueRouter({
      routes: [
        {
          //登录页
          path: '/main',
          component: Main,
          //  写入子模块
          children: [
            {
              path: '/user/profile',
              component: UserProfile,
            }, {
              path: '/user/list',
              component: UserList,
            },
          ]
        },
        //首页
        {
          path: '/login',
          component: Login
    
        },
      ]
    })
    

    Vue进阶_第37张图片

    5.4、参数传递及重定向

    < template>:所有的元素必须在根节点下

    • 1、 修改路由配置, 主要是router下的index.js中的 path 属性中增加了 :id 这样的占位符
    {
    	path: '/user/profile/:id', 
    	name:'UserProfile', 
    	component: UserProfile
    }
    
    
    • 传递参数
      此时我们在Main.vue中的route-link位置处 to 改为了 :to,是为了将这一属性当成对象使用,注意 router-link 中的 name 属性名称 一定要和 路由中的 name 属性名称 匹配,因为这样 Vue 才能找到对应的路由路径;
    <!--name是组件的名字 params是传的参数 如果要传参数的话就需要用v:bind:来绑定-->
    <router-link :to="{name:'UserProfile',params:{id:1}}">个人信息</router-link>
    
    
    • 3、在要展示的组件Profile.vue中接收参数 使用 {{$route.params.id}}来接收
    <template>
      <!--  所有的元素必须在根节点下-->
      <div>
        <h1>个人信息</h1>
        {{$route.params.id}}
      </div>
    </template>
    
    

    Vue进阶_第38张图片
    第二种取值方式 使用props 减少耦合

    • 1、修改路由配置 , 主要在router下的index.js中的路由属性中增加了 props: true 属性
    {
    	path: '/user/profile/:id', 
    	name:'UserProfile', 
    	component: UserProfile, 
    	props: true
    }
    
    
    • 传递参数和之前一样 在Main.vue中修改route-link地址
    <!--name是组件的名字 params是传的参数 如果要传参数的话就需要用v:bind:来绑定-->
    <router-link :to="{name:'UserProfile',params:{id:1}}">个人信息</router-link>
    
    
    • 在Profile.vue接收参数为目标组件增加 props 属性
    <template>
      <div>
        个人信息
        {{ id }}
      </div>
    </template>
    <script>
        export default {
          props: ['id'],
          name: "UserProfile"
        }
    </script>
    <style scoped>
    </style>
    
    

    5.5、重定向

    重定向的意思大家都明白,但 Vue 中的重定向是作用在路径不同但组件相同的情况下

    {
      path: '/main',
      name: 'Main',
      component: Main
    },
    {
      path: '/goHome',
      redirect: '/main'
    }
    
    

    说明:这里定义了两个路径,一个是 /main ,一个是 /goHome,其中 /goHome 重定向到了 /main 路径,由此可以看出重定向不需要定义组件;

    <el-menu-item index="1-3">
        <router-link to="/goHome">回到首页</router-link>
    </el-menu-item>
    
    

    5.6、路由模式

    路由模式有两种

    • hash:路径带 # 符号,如 http://localhost/#/login
    • history:路径不带 # 符号,如http://localhost/login

    注意:默认为hash,若是要使用history需要mode: 'history'

    5.7、404

    • 1.创建一个NotFound.vue视图组件
    <template>
        <div>
          <h1>404,你的页面走丢了</h1>
        </div>
    </template>
    <script>
        export default {
            name: "NotFound"
        }
    </script>
    <style scoped>
    </style>
    
    
    • 2.修改路由配置index.js
    import NotFound from '../views/NotFound'
    {
       path: '*',
       component: NotFound
    }
    
    

    在这里插入图片描述

    5.8、路由全局守卫

    beforeRouteEnter:在进入路由前执行
    beforeRouteLeave:在离开路由前执行

      export default {
        name: "UserProfile",
        beforeRouteEnter: (to, from, next) => {
          console.log("准备进入个人信息页");
          next();
        },
        beforeRouteLeave: (to, from, next) => {
          console.log("准备离开个人信息页");
          next();
        }
      }
    
    

    参数说明:
    to:路由将要跳转的路径信息
    from:路径跳转前的路径信息
    next:路由的控制参数
    next() 跳入下一个页面
    next(’/path’) 改变路由的跳转方向,使其跳到另一个路由
    next(false) 返回原来的页面
    next((vm)=>{}) 仅在 beforeRouteEnter 中可用,vm 是组件实例

    5.9、理解< router-view/>【超重点】

    • 通过脚手架创建的项目默认都是放入App.vue
      Vue进阶_第39张图片
    • 在不使用路由嵌套的时候,不需要显示的指定component组件,这时路径匹配成功时会默认跳转到App.vue中的< router-view/>进行展示,但是在重定向时一定要确保该路由已经routers中注册
      Vue进阶_第40张图片
    • 但是在路由嵌套中,或者在多个组件中都存在< router-view/>时,一定要显示的定义出组件,告给vue-router路径匹配成功时应该跳转到哪个组件中的< router-view/>

    Vue进阶_第41张图片
    Vue进阶_第42张图片

    • 在指定的< router-view/>中展示

    Vue进阶_第43张图片

    Vue进阶_第44张图片

    六、Vue.js Ajax(axios)【重点】

    6.1、axios概念

    Axios是一个开源的可以用在浏览器端和NodeJS 的异步通信框架,她的主要作用就是实现AJAX异步通信

    • 特点
      ●从浏览器中创建XMLHttpRequests
      ●从node.js创建http请求
      ●支持Promise API [JS中链式编程]
      ●拦截请求和响应
      ●转换请求数据和响应数据
      ●取消请求
      ●自动转换JSON数据
      ●客户端支持防御XSRF (跨站请求伪造)

    6.2、为什么要用axios

    由于Vue.js是一个视图层框架且作者(尤雨溪) 严格准守SoC (关注度分离原则),所以Vue.js并不包含AJAX的通信功能,为了解决通信问题,作者单独开发了一个名为vue-resource的插件,不过在进入2.0 版本以后停止
    了对该插件的维护并推荐了Axios 框架。少用jQuery,因为它操作Dom太频繁!

    6.3、vue生命周期

    Vue进阶_第45张图片

    6.4、axios的使用

    DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Titletitle>
        <script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js">script>
        <script src="node_modules/axios/dist/axios.js">script>
    head>
    <body>
        <div id="app">
            {{info.name}}
        div>
    <script type="text/javascript">
        var vm=new Vue({
            el:'#app',
            data(){
                //请求的返回参数必须和json字符串一样
                return {
                    info:{
                        name:null,
                        url:null,
                        address:{
                            street:null,
                            city:null
                        }
                    }
                }
            },
            mounted(){
                axios.get('/myWebpack/modules/data.json').then(response=>(this.info=response.data))
            }
        });
    script>
    body>
    html>
    
    • 固定格式

    Vue进阶_第46张图片

    你可能感兴趣的:(Vue,vue)