daily-share icon indicating copy to clipboard operation
daily-share copied to clipboard

vue2.5基础整理(2020-2-11)

Open yaogengzhu opened this issue 5 years ago • 0 comments

Vue2.5开发基础学习

vue基础

vue官网

  • 注意: vue不支持低版本浏览器内容

使用vue.js 实现hello world

// 如何在页面上实现一个简单的hello world 
// 1. 方式1: 原生的方式
  var app = document.getElementById('app')
	app.innerHTML = 'hello world'

// 2. 方式2: vue的方式
// 引入vue的cdn
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
const app = new Vue({
    el: "#app",
    data: {
      content: 'hello world'
    }
})

使用vuejs实现ToDolist

  • v-for 循环指令
  • v-on 绑定指令 v-on:click
  • v-model input的数据双向绑定

代码演示

<div id="app">
  <input type="text" v-model='inputVal'>
  <button v-on:click="add">添加</button>
  <ul>
    <li v-for=" item in list">{{ item }}</li>
  </ul>
</div>
// 
const vm = new Vue({
  el: '#app',
  data: {
    list: ['a', 'b'],
    inputVal: ''
  },
  methods:{
    add() {
      this.list.push(this.inputVal)
      this.inputVal = ''
    }
  }
})

MVVM 设计模式

MVP模式 --- M-模型层 V-视图 P- 控制器

前端组件化

v-bind: 组件绑定值, 自组件可以用props 接收一个值

Vue.component() 全局组件化创建

  • 也可以在实列上添加组件

vue基础精讲

— vue 的组件是一个实例组成的

基础详细

  • v-on 简写方式@
  • v-bind简写方式:

注意: 凡事$ 的都是vue实例的方法和属性

简单的组件传值

子组件向父组件传值

this.$emit('delete') 使用$emit 方法向外(向上一层)传递一个事件

在父组件中监听delete事件

@delete='change' 在父组件的方法中写change

vue的生命周期的钩子

生命周期就是vue实例在某一个 时间点 会自动执行的函数

 const vm = new Vue({
   el: '#app',
   data: {
     test: 'hello world'
   },
   beforeCreate() {
     console.log(this.$el)
     console.log('beforeCreate')
   },
   created() {
     console.log(this.$el)
     console.log('created')
   },
   beforeMount() {
     console.log(this.$el)
     console.log('beforeMount')
   },
   mounted() {
     console.log(this.$el)
     console.log('mounted')
   },
   beforeUpdate() {
     console.log('beforeUpdated')
   },
   updated() {
     console.log('updated')
   },
   beforeDestroy() {
     console.log('beforeDestroy')
   },
   destroyed() {
     console.log('Destroyed')
   }

 })

vue的模版语法

v- 后接的内容都是js表达式

v-text

插值表达式

v-html 支持html内容

计算属性,和监听器

  • computed 计算属性
    • 内置缓存,提升性能、
  • methods 方法实现
  • watch 监听器

计算属性的setter 和 getter

计算属性中的get, 和set方法一般情况下不使用,如果需要改变计算属性的值,那么必须存在set方法

计算属性默认只有 getter ,不过在需要时你也可以提供一个 setter :

const vm = new Vue({
  el: '#app',
  data: {
    firstName: 'zhu',
    lastName: 'yaogeng'
  },
  computed: {
    fullname: {
      // getters
      get() {
        return this.firstName + this.lastName
      }, 
      // setter 
      set(value) {
        const name = value.split(' ')
        this.firstName = name[0]
        this.lastName = name[1]
      }
    }
  }
})

vue 中如何绑定样式

如何快速的实现样式绑定呢,

  • class 方式
    • :class="{calssname: 变量}" 方式1; class的对象绑定
    • :class="[activeted]", 方式2;数组的方式
  • style 方式
    • :style="{ color: 'red'}" 对象的方式
    • :style="[{ color: red}]" 数组方式

vue 的条件渲染

vue的条件渲染 ,v-if, v-show

V-if和v-show的区别

v-show是display: none,v-if 是dom的删除和添加

在vue项目中,可以使用v-if 和 v-else

v-if="show === a" 方式使用

<input /> // dom 的复用。diff算法 , 需要加一个key值,解决条件该改变,dom没有被更新的问题

vue中的列表渲染

v-for做数组循环.

不建议使用index作为key值

<div v-for='(item, index) in item' :key="index">  
</div>
  • 尝试修改数组的内容时,不能直接给数组赋值

    1.直接更改数组的引用

    2.可以用以下的改变数组,通过视图更改数组(变异方法)

    • push
    • pop
    • shift
    • unshift
    • splice
    • sort
    • reverse

tmplate模版占位符

  • 语法中循环对象
<div v-for="(item, key, index) in obj"></div>
  • 对象更改数据,也需要更改对象的引用方法

Vue的set方法

  • 对象的方法
// 通过Vue.set方法更改值
Vue.set(vm.userInfo, 'address', 'beijing')
vm.$set(vm.userInfo, 'address', 'beijing')
  • 数组的方法
Vue.set(vm.userInfo, 1, 5) // 通过数组下标的方法去使用
vm.$set(vm.userInfo, 2, 10)

深入理解vue组件的细节

is属性, 组件如果不能正常的渲染到指定的位置化,建议是用以下的问题

<tr is="row"></tr>
<body>
    <div id="app">
        <table>
            <tbody>
                <tr is='todo' :title='22'></tr>
                <tr is='todo' title='成功插入'></tr>
            </tbody>
        </table>
    </div>

    <script>
        Vue.component('todo', {
            props: ['title'],
            template: '<tr><td>{{ title }}</td></tr>'
        })
        const vm = new Vue({
            el: '#app',
            methods: {

            }
        })
    
    </script>
</body>

组件中的data 必须是一个函数,函数中需要返回一个对象

data:function() {
  return {
    content: ''
  }
}
// 因为子组件不仅只调用一次,组件会调用多次,为了让每一个字组件的都有一个独立的数据空间,避免数据污染

vue在必要的情况下,操作dom. 通过ref 来操作dom

  • 标签通过ref 是获取一个标签
<div ref='hello'>
  
</div>
this.$refs.hello // 获取dom节点
  • 如果是组件,通过ref,则获取的是组件的实例
this.$emit('change') // 实际上,可以看成是一个发布订阅模式
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <div ref='div'>{{ msg }}</div>
        <do ref='one' @change='change'></do>
        <do ref='two' @change='change'></do>
        total-------<span>{{ total }}</span>
    </div>
    <script>
        
        Vue.component('do', {
            data: function() {
                return {
                    count: 0
                }
            },
            template: '<div v-text="count" @click="change"></div>',
            methods: {
                change() {
                    this.count = ++this.count
                    this.$emit('change')
                }
            }
        })
        const vm = new Vue({
            el: '#app',
            data: {
                msg: 'hello world',
                total: 0
            },
            methods: {
                change() {
                    // console.log('ok')
                    this.total = this.$refs.one.count + this.$refs.two.count
                    
                }
            },
            mounted() {
                console.log(this.$refs.div, 'ok')
            }
        })
    </script>
</body>
</html>

详细介绍父子组件之间的传值

父组件如何向子组件传值

  • 通过属性的方式传递
<counter :count="0"></counter>
props: ['count'],
template: '<div>{{ count }}</div>'
// 单向数据流---- , 可以改变自身的data, 如果直接改变props,vue会报警告

单向数据流 可以通过拷贝副本,进行

子组件向父组件传值,通过事件的$emit()方式

$emit('change', 参数)

vue组件参数校验 与非 Props特性

props 参数校验, props 特性,

props 特点:不会在dom标签上显示,父给子传,子能拿到

// 方式1
props: {
  content: Number
}
// 方式2 多种类型
props: {
  content: [Number, String]
}
// 方式3 
props: {
  content: {
    type: String,
    required: false, // 可以不传
    default: '默认值',
    validator: function(value) {  // 对值进行校验
				return (vlaue.length > 5)  // 自定义校验器
    }
  }
}

非props 特性

  • 特性:
    • 外层传递,不接受的话,不能使用
    • 非props 属性会展示在子组件最外层标签上

给组件绑定原生事件

给子组件绑定一个事件的话,绑定的是一个自定义的事件,

  • 方式1
    • 自定义事件如何触发:this.$emit('click')
  • 方式2
    • @click.native 变成原生的点击事件,不是内部组件向外触发的自定义事件

非父子组件的传值

  • 方式: 组件中逐层传递

  • 两个组件传值,但不具备父子组件的关系

    • vuex
    • 总线机制(bus/总线/发布订阅/观察者模式)
Vue.prototype.bus = new Vue()
// 每个vue的实例都有一个bus的属性

Vue.component('child', {
  data: function() {
    return {
      selfContent: this.content
    }
  },
  props: {
    content: String
  },
  template: '<div></div>',
  methods: {
    handleClick: function() {
      this.bus.$emit('change', this.content)
    }
	},
  mounted: function() {
    // this
    var that = this
    this.bus.$on('change', funciton(msg) {
    		this.selfContent = msg
    })
  }
})

Vue 中使用插槽

插槽

  • 方式1: 使用v-html

    <com content='<p>hello</p>'></com>
    
  • 方式2: 使用slot语法

    • <slot>默认值</slot> 可以存在默认值

    • 具名插槽:同样具名插槽也有默认值

      • 父组件
      <div slot='header'></div> 
      
      • 子组件
      <slot name='header'></slot>
      

demo

<body>
    <div id="app">
        <do content='<p>您好,世界</p>'>
            <p slot='header'>我用自己的插槽, 可以滚蛋了</p>
            <p slot='footer'>我用自己的插槽, 可以滚蛋了</p>
        </do>
    </div>
    <script>
        Vue.component('do', {
            props: ['content'],
            template: `<div>
                         <slot name='header'>这是插槽</slot>
                         <h1> hello world </h1>
                         <p v-html='content'></p>
                         <slot name='footer'>这是插槽</slot>
                       </div>`
        })
        const vm = new Vue({
            el: '#app',
            data: {

            }
        })
    </script>
</body>

. vue 的作用域插槽

子组件负责数据,父组件负责显示内容, 当组件做循环,

  • 作用域插槽必须是template 开始和结尾, 同时使用slot-scope=''接收
<child>
  <template slot-scope='props'>
    <h1>{{ props.item }}</h1>
  </template>
</child>
Vue.component("child", {
  data: funciton() {
    return {
      list: [1, 2, 3, 4]
 	 	}
},
  template: `<div>
								<slot 
									v-for="item of list"
									:item=item
								></slot>
						 </div>`
})

动态组件和v-once

有一个属性 :is='组件名'


组件创建,和销毁浪费性能。 使用v-once 能提高性能效率


  • 方式1
<body>
    <div id="app">
        <child-one v-if='type === "child-one"'></child-one>
        <child-two v-if='type === "child-two"'></child-two>
        <button @click='change'>改变</button>
    </div>
    <script>
        Vue.component('child-one', {
            template: '<div>子组件一</div>'
        })

        Vue.component('child-two', {
            template: '<div>子组件二</div>'
        })
        const vm = new Vue({
            el: '#app',
            data: {
                type: 'child-one'
            },
            methods: {
                change() {
                    this.type = this.type === 'child-one' ? 'child-two' : 'child-one'
                }
            }
        })
    </script>
</body>
  • 方式2
<body>
    <div id="app">
        <component :is='type'></component>
        <button @click='change'>改变</button>
    </div>
    <script>
        Vue.component('child-one', {
            template: '<div v-once>子组件一</div>'
        })

        Vue.component('child-two', {
            template: '<div v-once>子组件二</div>'
        })
        const vm = new Vue({
            el: '#app',
            data: {
                type: 'child-one'
            },
            methods: {
                change() {
                    this.type = this.type === 'child-one' ? 'child-two' : 'child-one'
                }
            }
        })
    </script>
</body>

Vue Css的动画原理

当vue中,被transition 标签的元素添加动画class ,默认前缀v-

  • fade-enter 进入 第一帧
  • fade-enter-active 进入第二帧
  • fade-leave 离开第一帧
  • fade-leave-activ 离开第二帧
 .fade-enter {
        opacity: 0;
    }

    .fade-enter-active {
        transition: opacity 2s;
    }

    .fade-leave-to {
        opacity: 0;
    }

    .fade-leave-active {
        transition: opacity 2s;
        color: red;
    }

在vue中使用animate.css库

借用keyframes

@keyframes bounce-in {
  0% {
    transform: scale(0);
  }
  50% {
    transform: scale(1.5);
  }
  100% {
    transform: scale(1)
  }
}

.fade-enter-active {
  transform-origin: left center;
  animaition: bounce-in 1s;
}
.fade-leave-active {
  transform-origin: left center;
  animaition: bounce-in 1s reverse;
}

自定义命名规范

<transition 
   name='fade'
   enter-active-class='active'
   leave-active-class='leave'
></transition>

Animatie.css 库

class 类名必须加animated 动画

<transition 
   name='fade'
   enter-active-class='animated 类名'
   leave-active-class='animated 类名'
></transition>
  • 必须使用自定class
  • 必须有aninated 这个类名
<div id="app">
  <transition name='fade'
              enter-active-class='animated flash red'
              leave-active-class='animated shake blue'
              >
    <h1 v-show='show'>hello, world!</h1>
  </transition>
  <button @click='change'>改变</button>
</div>

vue 中如何使用过渡和动画

appear

appear-active-class='animated swing'

<transitiion
   appear
   appear-active-class='animated swing'
></transitiion>

手动结束时常

type='transition'

或者 :duration='10000' 自定义播放时长

或者:duration="{enter: 3000, leave: 1000}" 入场动画和出场动画时常

vue中的js动画和velocity.js的结合

  • @before-enter='handleBeforeEnter' 入场动画
  • @enter='handleEnter'
  • @after-enter='handleAfterEnter'
  • @before-leave …. 出场动画
methods: {
  	handleBeforeEnter: function(el) {
      el.style.color='red'
    },
    handleEnter: function(el, done) {
      setTimeout(() => {
        el.style.color ='green'
        done() // 告诉vue回调函数被执行完了
      }, 2000)
    },
     handleAfterEnter: function(el) {
        el.style.color = '#0000'
     }
}
js常用的动画库 velocity.js

多个元素和组件之的过渡动画

  • 元素关键点位置: key值设置
  • transition: 上的mode设置
<style>
    .fade-enter, .fade-leave-to {
        opacity: 0;
    }
    .fade-enter-active, .fade-leave-active {
        transition: opacity 1s;
    }
</style>
<body>
    <div id="app">
        <transition name='fade' mode='out-in'>
            <div v-if='show' key='1'>hello, world!</div>
            <div v-else key='2'>您好,世界!</div>
        </transition>
        <button @click='change'>改变</button>
    </div>
    <script>

        const vm = new Vue({
            el: '#app',
            data: {
                show: true
            },
            methods: {
                change() {
                    this.show = !this.show
                }
            }
        })
    </script>
</body>

yaogengzhu avatar Feb 11 '20 04:02 yaogengzhu