前端知识代码

Vue学习笔记

2019-06-13  本文已影响0人  冬天吃橘子_Autumn

最近在学习Vue,下面是学习过程中总结了一些基本的知识点

Vue

一. 基本知识

1. 实例化

var app = new Vue({

    el: '#app',  //绑定到元素上
    data: {
        message:'hello world'
    },
    filters:{
        filterName1:function(){},
        filterName2:function(){}
    },
    methods:{
        methodName1:function(){},
        methodName2:function(){}
    },
    //生命周期钩子
    created:function(){
        //未挂载到dom之前触发
    },
    mounted:function(){
        //挂载到dom后触发
    },
    beforeDestroy:function(){
        
    }
    
})

2. 过滤器

{{ data中的变量名 | filter中的过滤器名 }}

3. 指令和事件

4. VUE内置指令

5. 计算属性

6. 数组更新、过滤与排序

改变数组的一系列方法:

两个数组变动vue检测不到:

  1. 改变数组的指定项
  2. 改变数组长度
    过滤:filter

解决方法:

改变指定项: Vue.set(app.arr,1,”car”);
app.arr.splice(1): 改变数组长度

二. 组件

组件 (Component) 是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。在较高层面上,组件是自定义元素,Vue.js 的编译器为它添加特殊功能。在有些情况下,组件也可以表现为用 is 特性进行了扩展的原生 HTML 元素。所有的 Vue 组件同时也都是 Vue 的实例,所以可接受相同的选项对象 (除了一些根级特有的选项) 并提供相同的生命周期钩子。

1. 组件用法

2. props父级向子级传递数据

3. 单项数据流

4. 组件命名注意事项

5. 数据类型验证

三. 组件通信

1. 自定义事件

用于:子组件给父级传递数据

子组件用$emit ( '父组件中事件名' , 要传递的数据 ) 来触发事件 ,父组件用@'父组件中事件名'='触发的函数'来 监昕子组件的事件,触发的函数的参数即为子组件传递来的数据

第一步:自定义事件
第二步:在子组件中用$emit触发事件,第一个参数是事件名,后边的参数是要传递的数据
第三步:在自定义事件中用一个参数来接受

<div id="app">
    您的余额是:{{ acount }}<br>
    <my-component :acount="acount" @change-acount='handleAcount'></my-component>
</div>

<script>
    var app = new Vue({
        el: '#app',
        data: {
            acount: 2000
        },
        methods:{
            handleAcount:function(value){
                this.acount = value
            }
        },
        components: {
            'my-component': {
                props:['acount'],
                template: `<div>
                            <button @click="addAcount">+1000</button> 
                            <button @click="reduceAcount">-1000</button>
                         </div>`,
                data: function(){
                    return {
                        count: this.acount
                    }
                },
                methods:{
                    addAcount: function(){
                        this.count += 1000
                        //注意这里$emit的参数
                        this.$emit('change-acount',this.count)
                    },
                    reduceAcount: function(){
                        this.count -= 1000
                        this.$emit('change-acount',this.count)
                    }
                }
            }
        }
    })

2. 在组件中使用v-model

在组件中使用v­-model 其实是一个语法糖,这背后其实做了两个操作

$emit('input',value)的代码,这行代码实际上会触发一个 input事件, ‘input’后的参数就是传递给v­-model绑定
属性的值

<div id="app">
    您的余额是:{{ acount }}<br>
    <!-- <my-component :acount="acount" @change-acount='handleAcount'></my-component> -->
    <!-- 下面使用v-model -->
    <my-component :acount="acount" v-model='acount'></my-component>
</div>

<script>
    var app = new Vue({
        el: '#app',
        data: {
            acount: 2000
        },
        components: {
            'my-component': {
                props:['acount'],
                template: `<div>
                            <button @click="addAcount">+1000</button> 
                            <button @click="reduceAcount">-1000</button>
                          </div>`,
                data: function(){
                    return {
                        count: this.acount
                    }
                },
                methods:{
                    addAcount: function(){
                        this.count += 1000
                        // 这里触发的是input事件
                        this.$emit('input',this.count)
                    },
                    reduceAcount: function(){
                        this.count -= 1000
                        this.$emit('input',this.count)
                    }
                }
            }
        }
    })
</script>

3. 非父组件之间的通信---bus中介

用于两个组件之间的通信,(非父子关系),可以在根组件中用一个空的Vue对象作为中介,一个组件中监听该中介的自定义事件,另一个组件中触发该自定义事件并传递数据

<div id="app">
    <acomponent></acomponent>
    <bcomponent></bcomponent>
</div>

<script>
    Vue.component('acomponent', {
      template: '<button @click="handle">点击向B组件传递数据</button>',
      data: function () {
        return {
          msg: '我是来自A组件的数据'
        }
      },
      methods: {
        handle: function () {
          // 触发根组件的bus中的method1事件
          this.$root.bus.$emit('method1', this.msg)
        }
      }
    })
    Vue.component('bcomponent', {
      template: '<div>{{ msg }}</div>',
      data: function () {
        return {
          msg: '这是B组件'
        }
      },
      created: function () {
        // 对根组件bus监听method1事件
        this.$root.bus.$on('method1',  (value)=> {
          this.msg = value
        })
      }
    })
    var app = new Vue({
      el: '#app',
      data: {
        bus: new Vue()
      }
    })
</script>

4. 父链和子链

父链:this.$parent

子链:this.$refs.索引
提供了为子组件提供索引的方法,用特殊的属性ref为其增加一个索引

<div id="app">
    <button @click='clickA'>A子组件</button>
    <button @click='clickB'>B子组件</button>
    <son-a ref='a'></son-a>
    <son-b ref='b'></son-b>
</div>

<script>
    var app = new Vue({
        el: '#app',
        data: { msg: '来自父组件的msg' },
        methods: {
            clickA: function(){
                alert(this.$refs.a.name)
            },
            clickB: function(){
                alert(this.$refs.b.name)
            }
        },
        components: {
            'son-a': {
                template: '<div>这是子组件:{{ msg }}</div>',
                data: function () {
                    return {
                        msg: this.$parent.msg,
                        name: 'son-a'
                    }
                }
            },
            'son-b': {
                template: '<div><div>',
                data: function () {
                    return {
                        name: 'son-b'
                    }
                }
            }
        }
    })
</script>

四. 插槽slot标签

1. 单个插槽

用于混合父组件的内容与子组件的模板

在子组件中加入<slot></slot>标签,当父组件中没有传入内容时,默认显示slot标签中的内容,反之,则将传入内容替换掉原来slot标签中的内容

<div id="app">
    <my-component>
        <p>{{ msg }}</p>
    </my-component>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
    Vue.component('my-component', {
        template: `<div>
                        <slot>
                            如果父元素没传内容进来,就默认显示我吧!
                        </slot>
                   </div>`
    })
    var app = new Vue({
        el: '#app',
        data: {msg:'父元素的内容'}
    })
</script>

2. 具名插槽

把父组件要传入的标签命名slot='名称',在子组件的slot标签中添加name属性

<div id="app">
    <my-component>
        <div slot='header'>标题</div>
        <div slot='container'>正文</div>
        <div slot='footer'>底部</div>
    </my-component>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
    Vue.component('my-component', {
      template: `<div>
                  <slot name='header'>
                    如果父元素没传内容进来,就默认显示我吧!
                  </slot>
                 </div>`
    })
    var app = new Vue({
      el: '#app',
      data: {msg:'父元素的内容'}
    })
</script>

3. 作用域插槽

从子组件中获取数据:在父组件中添加<template></template>标签,slot属性的值与子元素<slot>标签的name属性一样,用slot-scope属性获取传来的数据(除了name)

<div id="app">
    <my-component>
        <!-- 这里的prop是变量名,随便取一个名字都可以
             slot的值要跟子组件的name相同
             template标签不会被渲染
             template标签用其他例如<p>、<span>等都可以 -->
        <template slot-scope='prop' slot='abc'>
            <!-- 可以获取除了name以外传来的内容 -->
            {{ prop.text }}
        </template>
    </my-component>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>    
    Vue.component('my-component', {
      template: `<div>
                  <slot name='abc' text='子组件中传来的内容'>
                    如果父元素没传内容进来,就默认显示我吧!
                  </slot>
                 </div>`
    })
    var app = new Vue({
      el: '#app',
      data: {msg:'父元素的内容'}
    })
</script>

4. 访问slot

通过this.$slots.name访问

Vue.component('my-component2', {
      template: `<div>
                  <slot name='header'>
                    如果父元素没传内容进来,就默认显示我吧!
                  </slot>
                  <slot name = 'footer'></slot>
                 </div>`,
      mounted:function(){
        var header = this.$slots.header
        var footer = this.$slots.footer
        console.log(header[0].elm.innerText)
        console.log(footer[0].elm.innerText)
      }
})

五. 动态组件

VUE给我们提供 了一个元素叫component
作用是: 用来动态的挂载不同的组件
实现:使用is特性来进行实现的

<div id="app">
    <!-- 绑定is属性 -->
    <component :is='thisView'></component>
    <button @click="handleView('A')">页面一</button>
    <button @click="handleView('B')">页面二</button>
    <button @click="handleView('C')">页面三</button>
    <button @click="handleView('D')">页面四</button>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
    var app = new Vue({
        el: '#app',
        data: {
            thisView: 'compA'
        },
        methods:{
            'handleView':function(value){
                this.thisView = 'comp' + value
            }
        },
        components:{
            'compA':{template:'<div>页面一</div>'},
            'compB':{template:'<div>页面二</div>'},
            'compC':{template:'<div>页面三</div>'},
            'compD':{template:'<div>页面四</div>'}
        }
    })
</script>

六. 自定义指令

自定义指令的基本用法

和组件类似分全局注册和局部注册,区别就是把component换成了derective

七、render函数

1. 基本用法

在自定义组件时,template属性内容有时会很长,而且,在切换组件内的内容时,不显示的内容可能也会渲染一遍再隐藏,而在组件中用render函数可以解决这个问题

render函数的参数必须是createElement,这是在源码中已经定义好的函数

render函数要记得把createElement函数执行结果返回出去

<div id="app">
    <comp :thisview='thisView'>
        <slot slot='red'>red</slot>
        <slot slot='blue'>blue</slot>
    </comp>
    <button @click='clickRed'>red</button>
    <button @click='clickBlue'>blue</button>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
    Vue.component('comp', {
        props: ['thisview'],
        //这里的参数必须是createElement,是源码中已经定义好的函数
        render: function (createElement) {
            return createElement('div', this.$slots[this.thisview])
        },
        data: function () {
            return {
                view: this.thisview
            }
        }
    })
    var app = new Vue({
        el: '#app',
        data: { thisView: 'red' },
        methods: {
            clickRed: function () {
                this.thisView = 'red'
            },
            clickBlue: function () {
                this.thisView = 'blue'
            }
        }
    })
</script>

2. createElement函数的参数

render函数返回createElement函数的执行结果

3. this.$slots在render函数中的使用

插槽的用法

第三个 参数存的就是VNODE

createElement(‘header’,header), 返回的就是VNODE

var header = this.$slots.header; //这返回的内容就是含有VNODE的数组

<div id="app">
    <child>
        <span slot='header'>我是标题</span>
        <span slot='main'>我是正文</span>
        <span slot='main'>我是正文</span>
        <span slot='footer'>我是结尾</span>
    </child>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
    Vue.component('child', {
        render: function (createElement) {
            var header = this.$slots.header
            var main = this.$slots.main
            var footer = this.$slots.footer
            return createElement('div', {
                'class': {
                    red: true
                }
            }, [
                createElement('header', header),
                createElement('main', main),
                createElement('footer', footer)
            ])
        }
    })
    var app = new Vue({
        el: '#app',
        data: {}
    })

4. 在 render中使用props传递数据

5. 在render函数中使用v-model

<div id="app">
    <my-component :inputvalue='inputvalue' @change='changevalue'></my-component><br>
    <!-- 这里的v-model是语法糖,绑定input事件,当触发input事件时,把传来的值付给inputvalue -->
    <my-component :inputvalue='inputvalue' v-model='inputvalue'></my-component><br>
    {{ inputvalue }}
</div>

<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
    var app = new Vue({
        el: '#app',
        data: {
            inputvalue: '111'
        },
        methods: {
            changevalue: function (value) {
                this.inputvalue = value
            }
        },
        components: {
            'my-component': {
                props: ['inputvalue'],
                render: function (createElement) {
                    return createElement('input', {
                        attrs: {
                            value: this.inputvalue
                        },
                        on: {
                            input: (event) => {
                                this.$emit('change', event.target.value)
                                this.$emit('input', event.target.value)
                            }
                        }
                    })
                }
            }
        }
    })
</script>

6. 作用域插槽

向组件的插槽中传递数据

$scopedSlots.default

<div id="app">
    <my-component>
        <template scope='abc'>
            {{ abc.text }}<br>
            {{ abc.name }}
        </template>
    </my-component>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
    var app = new Vue({
        el: '#app',
        data: {},
        components: {
            'my-component': {
                render: function (createElement) {
                    return createElement('div', this.$scopedSlots.default({
                        text: '我是子组件传来的数据',
                        name: '陈秋钿'
                    }))
                }
            }
        }
    })
</script>

7. 函数化组件

functional:true //表示当前Vue实例无状态、无实例

无实例:组件内部没有this,可以通过context上下文来解决,render函数的第一个参数是createElement,第二个参数是context,这里this是window

context.parent

context.props

context.props.text ---- this.text

context.children ----- this.$slots.default

八. vue-cli脚手架

1. 安装步骤

首先电脑上要安装最新版的nodeJS.官网下载,安装完之后安装淘宝npm镜像

npm install -g cnpm --registry=https://registry.npm.taobao.org

2. 目录结构

├── build // 项目构建(webpack)相关代码 记忆:(够贱) 9个
│ ├── build.js // 生产环境构建代码
│ ├── check­versions.js // 检查node&npm等版本
│ ├── dev­client.js // 热加载相关
│ ├── dev­server.js // 构建本地服务器
│ ├── utils.js // 构建配置公用工具
│ ├── vue­loader.conf.js // vue加载器
│ ├── webpack.base.conf.js // webpack基础环境配置 //entry程序的入口
│ ├── webpack.dev.conf.js // webpack开发环境配置
│ └── webpack.prod.conf.js // webpack生产环境配置
二、
├── config// 项目开发环境配置相关代码 记忆: (环配) 3个
│ ├── dev.env.js // 开发环境变量(看词明意)
│ ├── index.js //项目一些配置变量
│ └── prod.env.js // 生产环境变量
三、
├──node_modules// 项目依赖的模块 记忆: (依赖) *个
四、
├── src// 源码目录5
1
│ ├── assets// 资源目录
│ │ └── logo.png
2
│ ├── components// vue公共组件
│ │ └── Hello.vue
3
│ ├──router// 前端路由
│ │ └── index.js// 路由配置文件
4
│ ├── App.vue// 页面入口文件(根组件)
5
│ └── main.js// 程序入口文件(入口js文件)
五、
└── static// 静态文件,比如一些图片,json数据等
│ ├── .gitkeep
剩余、
├── .babelrc// ES6语法编译配置
├── .editorconfig// 定义代码格式
├── .gitignore// git上传需要忽略的文件格式
├── index.html// 入口页面
├── package.json// 项目基本信息
├── README.md// 项目说明

3. 其他

以 .vue 结尾的是组件文件,组件文件中的样式只对组件中的标签有用

九. 前端路由和vuex状态管理

访问不同的路由,加载不同的组件(输入不同的网址,显示不同的内容)

watch: {
    // 如果路由有变化,会再次执行该方法
    $route: "getUserData"
}

1. vue­-router路由基本加载

2. 路由的跳转

用router-link

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

<template>
    <ul>
        <li>
            <router-link to="/helloworld">HELLO WORLD</router-link>
        </li>
        <li>
            <router-link to="/helloearth">HELLO EARTH</router-link>
        </li>
    </ul>
</template>

3. 通过路由传递参数

<!-- list.vue -->
<template>
    <ul>
        <li>
            <router-link :to="{name: 'helloworld',params:{worldmsg: '你好世界'}}">
                HELLO WORLD
            </router-link>
        </li>
        <li>
            <router-link :to="{name:'helloearth',params:{earthmsg:'你好地球'}}">
                HELLO EARTH
            </router-link>
        </li>
    </ul>
</template>

<!-- HelloEarth.vue -->
<template>
    <div class="hello">
        <h1>{{ msg }}</h1>
        <h2>Essential Links</h2>
        <h3>{{ $route.params.earthmsg }}</h3>
    </div>
</template>

<script>
    export default {
        name: 'HelloEarth',
        data () {
            return {
                msg: 'HELLO EARTH'
            }
        }
    }
</script>
// index.js(router)
export default new router({
  routes: [{
    name: 'helloworld',
    path: '/helloworld/:worldmsg',
    component: HelloWorld
  },{
    name: 'helloearth',
    path: '/helloearth/:earthmsg',
    component: HelloEarth
  }]
})

4. Axios —— get请求

this.$http.get( 'url ', {params:{}})

axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,它本身具有以下特征:

  • 从浏览器中创建 XMLHttpRequest
  • 从 node.js 发出 http 请求
  • 支持 Promise API
  • 拦截请求和响应
  • 转换请求和响应数据
  • 取消请求
  • 自动转换JSON数据
  • 客户端支持防止 CSRF/XSRF

5. Axios —— post请求

import qs from'qs'
postData() {
    this.$http.post(url, qs.stringify({
        params: {
            page: 1,
            limit: 10
        }
    }))
    .then(res => {
        this.items = res.data.data;
        console.log(res.data.data);
    })
    .catch(function(err) {
        console.log(err);
    });
}

6.vuex的store用法

子组件和父组件之间的通信可以通过props以及$emit来完成,非父组件之间的通信需要通过他们之间的共同父组件来完成,当文件较多时,就会很乱很麻烦,所以就用到了Vuex的store

简而言之,vuex可以用来管理状态,共享数据,在各个组件之间管理外部状态

应用场景:多个页面间共享的登录状态

  1. 安装vuex,引入并通过use方法使用它

    npm i vuex

    import Vuex from 'vuex'

    Vue.use(Vuex)

  2. 创建状态仓库

    //这里的Store和state是不能改的!
    var store = new Vuex.Store({
      //state 状态
      state: {
        num: 100
      }
    })
    //在入口文件中引入store,跟引入router一样
    new Vue({
      el: '#app',
      router,    
      store, //就是这一句
      components: { App },
      template: '<App/>'
    })
    
    
  1. 在任意组件中,都可以通过 this.$store.state.XXX 直接拿到共享的数据

    computed:{
        getNum:function(){
            return this.$store.state.num
        }
    }
    
    

7. vuex的相关操作及核心用法

vuex状态管理的流程

view———­>actions———–>mutations—–>state————­>view

十. 过渡

<div id="demo">
  <button v-on:click="show = !show">
    Toggle
  </button>
  <transition name="fade">
    <p v-if="show">hello</p>
  </transition>
</div>
new Vue({
  el: '#demo',
  data: {
    show: true
  }
})
.fade-enter-active, .fade-leave-active {
  transition: opacity .5s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
  opacity: 0;
}

在进入/离开的过渡中,会有 6 个 class 切换。

  1. v-enter:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。
  2. v-enter-active:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。
  3. v-enter-to: 2.1.8版及以上 定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时 v-enter 被移除),在过渡/动画完成之后移除。
  4. v-leave: 定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。
  5. v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。
  6. v-leave-to: 2.1.8版及以上 定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 v-leave 被删除),在过渡/动画完成之后移除。

上一篇 下一篇

猜你喜欢

热点阅读