Vue知识点-cnblog

Vue知识点

1. vue介绍

核心理念

  • 数据驱动视图:数据发生变化时,用户界面也会发生变化,无需手动修改DOM

mvvm三要素

  • modal:数据
  • viewModal:vue实例
  • view:视图

工作过程简述

  • 数据和视图之间通过vue实例进行通讯,modal发生变化时,vm能够监听到这种变化,并通知给view视图做出页面渲染,页面有事件触发时,vm也能监听到事件,通知modal进行数据响应变化

2. 计算属性

应用场景

  • 解决模板{{}}中放入过多逻辑会让模板难以维护

好处

  • 不是方法,而是存在缓存,当依赖项发生变化才会重新计算

3. 侦听器

  • 监听数据变化时应该做个某些操作
  • 配合防抖,节流

4. 生命周期

  • Vue实例从创建到销毁的过程

挂载阶段

  • beforeCreate:Vue实例初始化之后,事件初始化,组件父子关系确定
  • created:初始化prop,data,computed,watch,methods已经完成
  • beforeMount:渲染template模板,虚拟dom
  • mounted:$el挂载,template模板替换

更新阶段

  • beforeUpdate:获取更新前的各种状态数据
  • updated:所有的状态数据都是最新的

配合keep-alive组件

  • activited:组件激活
  • deactivited:组件失活

销毁阶段

  • beforeDestroy:组件销毁前执行,用于清除一些定时器
  • destoryed
    • this.$destroy()方法,销毁资源

5. 组件

原则

  • 可复用
  • 可维护
  • 单一功能

6. 在单页面中创建和使用组件

全局注册组件

  • 创建

注意data节点为一个函数

Vue.component('componentA',{
    template:"<div>一个A组件</div>",
    data(){
        return {
            msg:'hello'
        }
    },
    
    method:{
        showMsg(){
            console.log('msg')
        }
    }
})

普通页面的vue实例的data节点为一个对象

<script>
	let vm=new Vue({
        el:'#app',
        data:{
            msg:'message'
        }
    })
</script>
  • 使用(vue实例中使用使用短横线)
<component-a></component-a>
  • 在其他组件中使用(使用驼峰命名法)
Vue.component('componentB',{
    template:"<div>新组件:<componentA></componentA> </div>"
})

局部注册组件

const mySon={
    template:'<p>子组件</p>',
    data(){
       return {
           
       } 
    }
}

// 其他组件中局部注册mySon组件(驼峰命名法)
Vue.component('father',{
    template:'<div> 子组件<mySon></mySon> </div>',
    components:{
        mySon:mySon
    }
})

// vue实例中注册(短横线法)
const vm=new Vue({
    el:'#app',
    data:{
        
    },
    
    components:{
        "my-son":mySon
    }
})

// 使用
<my-son></my-son>

7. 组件通讯

父向子通讯

  • props选项
Vue.component('father',{
    // 注意短横线传值
    template:'<div><son :F-text="context"></son> </div>',
    data(){
        return {
            context:'父组件的数据'
        }
    },
    
    // 局部注册子组件
    components:{
        son:{
            props:['Ftext'],
            template:'<p>来自父组件的值{{Ftext}}</p>'
        }
    }
})


子向父通讯

  • 自定义事件
Vue.component('father',{
    // 注意短横线传值
    // 监听子组件触发的事件
    template:'<div><son :F-text="context" @msgToFather="sonMsgHandler"></son> </div>',
    data(){
        return {
            context:'父组件的数据'
        }
    },
    
    methods:{
        sonMsgHandler(val){
            console.log(val)
        }
    }
    
    // 局部注册子组件
    components:{
        son:{
            props:['Ftext'],
            template:'<p>来自父组件的值{{Ftext}}</p>
            // 触发子组件向父组件传输数据的按钮
            	<button @click="msgToFather">向父组件发生数据</button>
            
            ',
            
            methods:{
            	msgToFather(){
					this.$emit('msgToFather','666')        
    			}
        	}
        }
    }
})

兄弟组件通信

  • 通过事件总线

// 事件总线,空的vue实例,监听事件触发变化
const eventBus=new Vue()



// 兄弟组件1
Vue.component('componentA',{
    // 注意短横线传值
    // 监听子组件触发的事件
    template:'<div>兄弟组件1
    	<button @click="sendMsg"></button>
    </div>',
    data(){
        return {
            context:'父组件的数据'
        }
    },
    
    methods:{
        sonMsgHandler(val){
            console.log(val)
        },
            
        // 兄弟发送方,发送数据,通过总线发送    
        sendMsg(){
            eventBus.$emit('sendMsg',context)
        }
    }
    
   
})

// 兄弟组件2
Vue.component('componentB',{
    // 注意短横线传值
    // 监听子组件触发的事件
    template:'<div>兄弟组件1</div>',
    data(){
        return {
            context:'父组件的数据'
        }
    },
    
    methods:{
        sonMsgHandler(val){
            console.log(val)
        },
        
        // 接收兄弟组件发送的数据,eventBus接收
        receiveMsg:{
            eventBus.$on('sendMsg',data=>{
            	console.log('兄弟的信息'+data)
        	})
        }
    }
    
   
})



8. 插槽

  • 暴露预留位置给父组件,让父组件确定预留位置的模板

默认插槽

// 插槽定义

const son={
    
    template:"
    	<div>
    		Error
    		// 默认插槽
    		<slot>默认内容</slot>
    	</div>
    "
}

Vue.component("alert-box",{
    template:"
    	<div>子组件插槽内容
    		<son>1234<son>
    	</div>
    "
})

具名插槽

// 插槽定义

const son={
    
    template:"
    	<div>
    		Error
    		// 默认插槽
    		<slot>默认内容</slot>
    
    		// 具名插槽,带上名字
    		<slot name="main"></slot>
    		<slot name="footer"></slot>
    	</div>
    "
}

Vue.component("alert-box",{
    template:"
    	<div>子组件插槽内容
    		<son>
    			<template slot="main">main内容</template>
    			<template slot="footer">footer内容</template>
    			// 默认内容
    			1234
    		<son>
    	</div>
    "
})

作用域插槽

  • 子组件的数据可以通过插槽传送给父组件,让父组件确定每一项的特殊显示
// 需求:定义的一个userList组件,渲染父组件传递过来的数组

// 1. 在不更改userList组件逻辑的情况下,实现列表中特定项加粗

Vue.component("userList",{
    template:"
    	<ul>
    		<li :key="item.id" v-for="item in userList">
    			// 使用作用域插槽,将每一项数据传输给父组件,使用者确定是否加粗
    			<slot :info="item">
    				{{item.name}}
    			</slot>
    			
    		</li>
    	</ul>
    ",
    props:['userList']
})


// vue 实例使用

const vm=new Vue({
    el:'#app',
    data:{
        
        userList:[{
            id:1,
            name:'zs'
        },{
            id:2,
            name:'zs'
        },{
            id:3,
            name:'zs'
        }]
    },
    
    components:{
        "user-list":userList
    }
}
})

// 标签使用

<user-list :userList="userList">
    	// 我们通过作用域插槽使第二项加粗
		<template slot-scope="scope">
    		<strong v-if="scope.info.id===2"></strong>
    	</template>    
<user-list>

作用域插槽再一个案例

每次只能生成相同结构的列表,一旦业务需要发生了变化,组件就不再使用了。比如,我现在有了新的需求,在一个列表的每个列表项前面加上一个小的logo,我总不能又写一个新的组件来适应需求的变化吧?

这里就可以使用作用域插槽来解决这个问题。

具体的实现代码如下所示:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>作用域插槽案例</title>
  </head>
  <body>
    <div id="app">
      <!-- 如果没有传递模板,那么子组件的插槽中只会展示用户名 -->
      <my-list title="用户列表" :content="listData"></my-list>
        <!-- 传递模板 -->
        <my-list title="用户列表2" :content="listData">
          <template slot-scope="scope">
            <img src="./one.png" width="20"/>
            <span>{{scope.item.userName}}</span>
          </template>
        </my-list>
    </div>
    <script src="./vue.js"></script>
    <script>
      Vue.component("my-list", {
        props: ["title", "content"],
        template: `
                <div class="list">
                    <div class="list-title">
                        {{title}}
                    </div>
                    <div class="list-content">

                   <ul class="list-content">
                            <li v-for="item in content" :key="item.id">
                           <!--这里将content中的每一项数据绑定到slot的itemb变量上,在父组件中就可以获取到item变量-->     
                        <slot :item="item">{{item.userName}}</slot>
                                
                                </li>
                        </ul> 
                    </div>
                </div>
            `,
      });
      const vm = new Vue({
        el: "#app",
        data: {
          listData: [
            { id: 1, userName: "张三" },
            {
              id: 2,
              userName: "李四",
            },
            {
              id: 3,
              userName: "王五",
            },
          ],
        },
      });
    </script>
  </body>
</html>

在上面的代码中,我们首先在子组件my-list中,添加了作用域的插槽。

 <ul class="list-content">
                            <li v-for="item in content" :key="item.id">
                           <!--这里将content中的每一项数据绑定到slot的itemb变量上,在父组件中就可以获取到item变量-->     
                        <slot :item="item">{{item.userName}}</slot>
                                
                                </li>
                        </ul> 

同时在父组件中,使用对应的插槽

 <div id="app">
      <!-- 如果没有传递模板,那么子组件的插槽中只会展示用户名 -->
      <my-list title="用户列表" :content="listData"></my-list>
        <!-- 传递模板 -->
        <my-list title="用户列表2" :content="listData">
          <template slot-scope="scope">
            <img src="./one.png" width="20"/>
            <span>{{scope.item.userName}}</span>
          </template>
        </my-list>
    </div>

再回到开始的问题,作用域插槽到底是干嘛用的?很显然,它的作用就如官网所说的一样:将组件的数据暴露出去。而这么做,给了组件的使用者根据数据定制模板的机会,组件不再是写死成一种特定的结构。

以上就是作用域插槽的应用,需要你仔细体会。

8.1 vue组件化的理解

  • 定义:可复用的Vue实例,VueComponent组件实例
  • 增加代码的复用性
  • 什么时候使用:
    • 通用组件
    • 业务组件
    • 页面组件
  • 如何使用
    • Vue.component, component节点
    • 通信:props,$emit,$on
    • 内容分发:插槽,template
  • 本质:组件配置–>VueComponent–>render–>vDom—Dom

9. vue常用Api

vue.set

  • 用于设置响应式数据,使视图能够更新
`Vue.set(target,propertyName,value)`
// 设置不是响应式数据的情况,视图不会更新渲染
//批量更新身高,动态的给users中添加身高属性
          batchUpdate() {
            this.users.forEach((c) => {
              c.height = 0;
            });
          },
              
// 动态添加,属性变成响应式,视图会进行渲染              
// 视图不会渲染,怎么办呢
  batchUpdate() {
            this.users.forEach((c) => {
              //   c.height = this.height;
              Vue.set(c, "height", this.height);
            });
          },

vue.delete

  • 用于删除响应式属性时,视图更够更新
`Vue.delete`

vm.$on()

vm.$emit()

  • 用于事件总线事件的事件传递
// 挂载在Vue的原型对象的,Vue.prototype.$bus=new Vue() 
// 实现一个message组件
9.2 vm.$once,vm.$off

vm.$once

  • 监听某个事件触发,触发一次后移除监听
vm.$once('test事件名',function(res){
    
})

vm.$off

  • 移除自定义的事件监听器
vm.$off() // 移除所有的事件监听器 
vm.$off('test') // 移除该事件所有的监听器
vm.$off('test', callback) // 只移除这个回调的监听器

10. 过滤器

基本使用

  • 全局注册
Vue.filter('filterName',function(val){
    // 对原来的值进行处理,返回新的值
    return val
})
  • 使用
<div>{{msg|filterName}}</div>

局部注册

new Vue({
    data:{
        
    },
    
    filters:{
        filterName:function(val){
            
            return newVal
        }
    }
})

带参数的过滤器

Vue.filter("filterName",function(val,arg1,arg2){
    return val+arg1+arg2
})

// 使用
<div>
    {{date|format('yyyy-MM-dd','arg2')}}
</div>

11 自定义指令

基本使用

// 定义
Vue.directive("focus",{
    // 固定写法
    inserted:function(el){
        el.focus()
    }
})

// 使用
<input type="tetx" v-focus/>

带参数的自定义指令

// 定义
Vue.directive("color",{
    // 固定写法
    inserted:function(el,payload){
        // 注意想要获取value
        el.style.color=payload.value.color
    }
})

// 使用
<div type="tetx" v-color="{color:'blue'}"/>

局部使用

directives:{
    color:{
        // 固定写法
        // bind函数只会执行一次
        bind:function(el,payload){
            el.style.color=payload.value.color
        }
    }
}

12. 渲染函数

  • 完全使用JavaScript渲染模板

render函数的基本结构

render:function(createElement){
    return createElement(
    	// 三个参数 {string|object,Array}
        tag, // 标签名称
        data, // 标签属性的数据对象
        children // 子节点数组
    )
}

组件中使用render函数

// 渲染h1-h6的标题
Vue.component("heading",{
    props:{
        lever:{
            
        }
    },
    
    render(h){
        return h(level){
            'h'+level,
            {attrs:{title:this.title}},
            this.$slot.default // 子节点vNode    
        }
    }
})

// 使用
<heading :level="1">{{title}}</heading>

13. mixins(混入)

let myMinxins={
    created:function(){
        
    },
    
    methods:{
        testMethod(){
            
        }
    }
}

Vue.component("minxin名称",{
    mixins:[myMixin]
})

// 局部混入
minxins:{
    'mixins名称':[myMixin]
}

22、插件

前面我们讲解的混入,组件封装等都可以提高组件的复用功能。

但是这种方式不适合分发,也就是不适合将这些内容上传到github上,npm上。而这种情况最适合通过插件来实现。

插件通常用来为Vue添加全局功能。插件的功能范围一般有下面几种:

  • 添加全局方法或者属性。例如:‘element’
  • 添加全局资源
  • 通过全局混入来添加一些组件选项。例如vue-router
  • 添加vue实例方法,通过把它们添加到Vue.prototype上实现
  • 一个库,提供自己的API,同时提供上面提到的一个或多个功能,例如vue-router

插件声明

Vue.js 的插件应该暴露一个 install 方法。这个方法的第一个参数是 Vue 构造器,第二个参数是一个可选的选项对象:

MyPlugin.install = function (Vue, options) {
  // 1. 添加全局方法或 property
  Vue.myGlobalMethod = function () {
    // 逻辑...
  }

  // 2. 添加全局资源
  Vue.directive('my-directive', {
    bind (el, binding, vnode, oldVnode) {
      // 逻辑...
    }
    ...
  })

  // 3. 注入组件选项
  Vue.mixin({
    created: function () {
      // 逻辑...
    }
    ...
  })

  // 4. 添加实例方法
  Vue.prototype.$myMethod = function (methodOptions) {
    // 逻辑...
  }
}

https://www.cnblogs.com/luozhihao/p/7414419.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值