Vue2.0 浅学笔记

发布时间 2023-09-27 10:53:16作者: 小辉的

Vue 是框架,也是生态。

1.Vue API风格

选项式(Vue2)

组合式(Vue3)

2.入门

node.js 版本大于15

3.创建项目

创建项目

npm init vue@latest

开发环境

VScode +Volar

4.基本语法

1.文本插值

仅能使用单一表达式

使用JavaScript表达式
每个绑定仅支持单一表达式,也就是一段能够被求值的JavaScript 代码。一个简单的判断方法是是否可以合法地写在秋天后面

<template>
<h3>模板语法</h3>
<p>{{msg}}</p>
<p>{{number+1}}</p>
<p>{{ok ? "yes" :'no'}}</p>
<p>{{messge.split('').reverse().join()}}</p>
</template>
<script>
    
export default {
  data() {
      return {
        'msg':'123木头人',
        'number':10,
        'ok': true,
        'messge':'大家好'
      }
  }
}

</script>



2.渲染原始html

双大括号将会将数据插值为纯文本,而不是 HTML。若想插入 HTML,你需要使用 html 指令

<template>
<h3>模板语法</h3>
<p v-html="rowhtml"></p>
</template>


<script>

export default {
  data() {
      return {
        'rowhtml':'<a href="www.baidu.com">阿辉啊</a>'
      }
  }
}

</script>



3.属性绑定

v-bind 指令指示 Vue 将元素的 d attribute 与组件的 dynamid 属性保持一致。如果绑定的值是 nul 或者undefined ,那么该 attribute 将会从染的元素上移除

<template>
    <div v-bind:id="ids" v-bind:class="msg">test</div>
</template>


<script>
  export default {
    data(){
      return{
        'msg':"active",
        'ids':"appClass"
      }
    }
  }
</script>

<style>
.appClass{
  color: aqua;
}
</style>



简写
因为 v-bind 非常常用,我们提供了特定的简写语法

<div :id="dynamicId”:class="dynamicclass"></div>

布尔

 <button :disabled="a">Button</button>
 
 
 <script>
  export default {
    data(){
      return{
        'msg':"active",
        'ids':"appClass",
        'a':true
      }
    }
  }
</script>

对象

<div :class="obj.name"></div>

<script>
  export default {
    data(){
      return{
        'msg':"active",
        'ids':"appClass",
        'a':true,
        'obj':{
          'name':'xiaohui'
        }
      }
    }
  }
</script>

多值绑定

<div v-bind="obj">9999</div>

<script>
  export default {
    data(){
      return{
        'msg':"active",
        'ids':"appClass",
        'a':true,
        'obj':{
          'name':'xiaohui'
        },
        'url':'www.baidu.com'
      }
    }
  }
</script>

4.条件渲染

v-if

<template>
    <h3>条件渲染</h3>
    <div v-if="flag">你能看见我吗</div>
</template>


<script>
  export default {
    data(){
      return{
        'flag':false
      }
    }
  }
</script>


v-else

<template>
    <h3>条件渲染</h3>
    <div v-if="flag">你能看见我吗</div>
    <div v-else>那你看看我</div>
</template>


<script>
  export default {
    data(){
      return{
        'flag': true
      }
    }
  }
</script>




v-else-if

<template>
    <h3>条件渲染</h3>
    <div v-if="flag">你能看见我吗</div>
    <div v-else>那你看看我</div>
    <div v-if="type=='A'">A</div>
    <div v-else-if="type==B">B</div>
    <div v-else>C</div>

</template>


<script>
  export default {
    data(){
      return{
        'flag': true,
        'type':'A'
      }
    }
  }
</script>




v-show

<template>
    <h3>条件渲染</h3>
    <div v-show="flag">v-show</div>
</template>


<script>
  export default {
    data(){
      return{
        'flag': true,
        'type':'A'
      }
    }
  }
</script>

v-if VS v-show

v 是“真实的“按条件染,因为它确保了在切换时,条件区块内的事件监听器和子组件都会被销毁与重建。
v 也是惰性的: 如果在初次染时条件值为 false,则不会做任何事。条件区块只有当条件首次变为 true 时才被渲染。

相比之下,v-show 简单许多,元素无论初始条件如何,始终会被染,只有 CSS dsplay 属性会被切换,总的来说,v-if有更高的切换开销,而 show 有更高的初始染开销。

因此,如果需要频繁切换,则使用show 较好;如果在运行时绑定条件很少改变,则 v-if会更合适

5.列表渲染

我们可以使用 v-for 指令基于一个数组来染一个列表。v-for 指令的值需要使用 item in items 形式的特殊语法其中 items 是源数据的数组,而 item 是选代项的别名

<template>
    <h3>列表渲染</h3>
    <p v-for="i in names">{{i}}</p>

    <div v-for="i in res">
        <p>{{i.title}}</p>
        <img :src="i.id" alt="1233444">
    </div>
</template>

<script>
    export default {
        data() {
            return {
                'names':[123,456,789],
                'res':[
                    {'id':'https://pic.rmb.bdstatic.com/bjh/down/96114dba7e6715f344fb6d39225d6ad5.jpeg',"title":"title111"},
                    {'id':2,'title':"title22"}
                ]
            }
        }
    }
</script>
    <p  v-for="i of names">{{i}}</p>
<template>
    <h3>列表渲染</h3>
    <p v-for="i in names">{{i}}</p>

    <div v-for="i in res">
        <p>{{i.title}}</p>
        <img :src="i.id" alt="1233444">
    </div>
    <p>index 渲染</p>
    <div v-for="(i,index) in names">
        <p>{{index}}</p>
    </div>
    <p>i of names</p>
    <p  v-for="i of names">{{i}}</p>
    <p>遍历对象所有属性</p>
    <p v-for="(value,key,index) of res">{{ value.title }}--{{key}}--{{index}}</p>
</template>

<script>
    export default {
        data() {
            return {
                'names':[123,456,789],
                'res':[
                    {'id':'https://pic.rmb.bdstatic.com/bjh/down/96114dba7e6715f344fb6d39225d6ad5.jpeg',"title":"title111"},
                    {'id':2,'title':"title22"}
                ]
            }
        }
    }
</script>

6.通过key值管理状态

​ Vue 默认按照“就地更新”的策略来更新通过 4o 染的元素列表当数据项的顺序改变时,Vue 不会随之移动 DOM 元素的顺序,而是就地更新每个元素,确保它们在原本指定的索引位置上渲染。
​ 为了给 Vue 一个提示,以便它可以跟踪每个节点的标识,从而重用和重新排序现有的元素你需要为每个元素对应的块提供一个唯一的 key attribute:

<template>
    <h3>Key 属性</h3>
    <p v-for="(i,index) in names" :key="index">{{i}}</p>
</template>

<script>
    export default{
        data(){
            return {
                names:[12,343454,5464]
            }

        }
    }
</script>

温馨提示
key 在这里是一个通过 v-bind 绑定的特殊 attribute推荐在任何可行的时候为 v-for 提供一个 key attribute绑定的值期望是一个基础类型的值,例如字符串或 number 类型key

7.事件处理

我们可以使用 v-on 指令(简写为 @)来监听 DOM 事件,并在事件触发时执行对应的JavaScript。用法?click"methodName”可 @cick="handler
事件处理器的值可以是
@内联事件处理器:事件被触发时执行的内联JavaScript 语句(与 onick 类似)@方法事件处理器:一个指向组件上定义的方法的属性名或是路径

内连事件处理器

<template>
    <h3>内联事件处理器</h3>
    <button v-on:click="count++">Add</button>
    <button @click="count++">Add</button>
    <h3>{{count}}</h3>
</template>

<script>
    export default{
        data(){
            return {
                count:0
            }
        }
    }
</script>

独立方法

<template>
    <h3>内联事件处理器</h3>
    <button v-on:click="addCount">Add</button>
    <h3>{{count}}</h3>
</template>

<script>
    export default{
        data(){
            return {
                count:0
            }
        },methods:{
            addCount(){
                console.log('点击了')
                this.count++
            }
        }

    }
</script>

8.事件参数

事件参数可以获取event对象和通过事件传递参数

<template>
    <h3>内联事件处理器,传参</h3>
    <button @click="addCount">Add</button>
    <h3>{{count}}</h3>
</template>

<script>
    export default{
        data(){
            return {
                count:0
            }
        },methods:{
            //event
            addCount(e){
                console.log('点击了')
                // Vue中的Events就是原生js的Event对象
                console.log(e.target.innerHTML="Add"+this.count)

                this.count++
            }
        }

    }
</script>
<template>
    <h3>事件传参</h3>
    <p v-for="(i,index) in names" :key="index" @click="Print(i,$event)">{{i}}</p>
    <div v-html="rowData"></div>
    
</template>

<script>
    export default{
        data(){
            return {
                names:[123,444,555,666]
            }
        },methods:{
            //event
            Print(msg,e){
                console.log(msg,e)
            }
            
        }

    }
</script>

9.事件修饰符

<template>
    <h3>事件修饰符</h3>
    <a @click="Print" href="www.baidu.com">百度一下</a>
    <a @click.prevent="Print" href="www.baidu.com">百度一下1,阻止默2认事件</a>

    <div @click="Print1">
        <p @click="Print2">测试冒泡</p>

        <p @click.stop="Print2">测试冒泡222</p>
    </div>
</template>

<script>
    export default{
        data(){
            return {
                names:[123,444,555,666]
            }
        },methods:{
            //event
            Print(e){
                // 阻止默认事件
                e.preventDefault();
                console.log('点击了')
                
            },
            Print1(e){
                console.log('点击了div')
                
            },
            Print2(e){
                e.stopPropagation();
                console.log('点击了p')
                
            }
            
        }

    }
</script>

10.数组变化的侦测

动态往数组添加数据

变更方法

.pop()

.push()

替换方法

重新赋值

.filter()

.concat()

.slice()

11.计算属性

模板中的表达式虽然方便,但也只能用来做简单的操作。如果在模板中写太多逻辑,会让模板变得臃肿,难以维护。因此我们推荐使用计算属性来描述依赖响应式状态的复杂逻辑

<template>
    <h3>{{ it.name }}</h3>
    <p>{{it.content.length>0 ? 'yes':'no'}}</p>

    <p>{{ itContent }}</p>
</template>

<script>
    export default{
        data(){
            return {
                it:{
                    name:"xiaohui",
                    content:['python','java','js']
                }
            }
        },
        computed:{
            itContent(){
                return this.it.content.length>0 ? "yes":"no"
            }
        }

    }
</script>

12.Class 绑定

<template>
    <h3>Class 绑定</h3>
    <p :class="{'active':isActive,'text-danger':hasError}">Class样式绑定P</p>
    <p :class="classObjb">多属性对象绑定</p>
    <p :class="[arractive,]">Class样式绑定--数组</p>
    <p :class="[isActive ? 'active' :'']">Class 样式绑定--三元表达式</p>
    <p :class="['isActive'? 'active':'',{'text-danger':hasError}]">Class 数组嵌套对象</p>

</template>


<script>
    export default {
        data(){
            return{
                isActive:true,
                hasError:true,
                classObjb:{
                    'active':true,
                    'text-danger':true
                },
                arractive:'active',
                arrHasError:'test-danger'
            }
        }
    }

</script>




<style>

.active{
    color: brown;
}

.text-danger{
    font-size: 30px;
}

</style>

数组对象嵌套,只能数组嵌套对象

13.stype绑定

数据绑定的一个常见需求场景是操纵元素的 CSS style列表,因为 se 是attribute,我们可以和其他attribute 一样使用 bind 将它们和动态的字符串绑定。但是,在处理比较复杂的绑定时,通过拼接生成字符串是麻烦且易出错的。因此,Vue 专门为 stye 的 bnd 用法提供了特殊的功能增强。除了字符串外,表达式的值也可以是对象或数组

<template>
    <h3>Style 样式绑定</h3>
    <p :style="{'color':activeColor,'fontSize':Size+'px'}">style样式绑定1</p>
    <p :style="styleObj">style样式绑定2</p>
    <p :style="[styleObj]">stype 绑定数组</p>

</template>

<script>
    export default{
        data(){
            return{
                activeColor:'red',
                Size:20,
                styleObj:{
                    color:'red',
                    fontSize:'20px'
                }

            }
        }
    }
</script>

14.侦听器

<template>
    <h3>侦听器</h3>

    <p>{{ message }}</p>
    <button @click="updateHandle">修改数据</button>
</template>


<script>
export default{
    data(){
        return{
            message:'hello'
        }
    },
    methods:{
        updateHandle(){
            console.log(this.message)
            this.message='word'
        }
    },
    //数据发生变化自动执行的函数
    //函数名与data里面变化的值一致
    watch:{
        message(newValue,oldValue){
            console.log('new',newValue)
            console.log('old',oldValue)
        }
    }
}

</script>

15.表单输入绑定

在前端处理表单时,我们常常需要将表单输入框的内容同步给JavaScript 中相应的变量。手动连接值绑定和更改事件监听器可能会很麻烦,v-model 指令帮我们简化了这一步骤

<template>
    <h3>表单输入绑定</h3>

    <form>
        <input type="text" v-model="message">
        <p>{{ message }}</p>

        <input type="checkbox" id="checkbox" v-model="checked">
        <label for="checkbox">{{ checked }}</label>
        <!-- 失去焦点或者回车 才会显示 -->
        <input type="text" v-model.lazy="test">
        <p>{{ test }}</p>
        <!-- 获取数字 -->
        <input type="text" v-model.number="test">
        <p>{{ test }}</p>
    </form>
</template>

<script>
    export default{
        data(){
            return{
                message:'1578',
                checked:false,
                test:''
            }
        }
    }
</script>

16.模板引用ref

虽然 Vue 的声明性渲染模型为你抽象了大部分对 DOM 的直接操作,但在某些情况下,我们仍然需要直接访问底层 DOM 元素。要实现这一点,我们可以使用特殊的 ref attribute
挂载结束后引用都会被暴露在 this.Srefs 之上

获取DOM操作

<template>
    <h3>Ref Demo</h3>
    <div class="container" ref="container">{{ content }}</div>
    <input type="text" ref="username">
    <button @click="getUser">获取元素</button>
</template>


<script>

    export default {
        data(){
            return {
                content:"内容"
            }
        },
        methods:{
            getUser(){
                console.log(this.$refs.container)
                console.log(this.$refs.username.value)
                // 提取 content  内容
                this.$refs.container.innerHTML='哈哈哈哈'
            }
        }
    }

</script>

5.组件

1.组件组成

组件最大的优势就是可复用性
当使用构建步骤时,我们一般会将 Vue 组件定义在一个单独的 .vue 文件中,这被叫做单文件组件(简称 SFC)

 scoped  style  样式只在当前组件生效
<style scoped>

myDemo.vue

<template>
    <!-- <RefDemo/> -->
    <div class="container">{{ message }}</div>
    
    </template>
    
    <script>
      export default{
        data(){
          return{
            message: '组件的基础组成'
          }
        }
      }
    
    
    </script>
    <!-- 
        scoped  style  样式只在当前组件生效
     -->
    <style scoped>
      .container {
        font-size: 50px;
        color: red;
      }
    
    </style>
    
    
    
    
    
    

app.vue

<template>
  <myDemo/>
  <my-demo/>
</template>

<script>
import myDemo from './components/myDemo.vue'

export default{
  components:{
    myDemo
  }
}

</script>

2.组件的嵌套关系

组件允许我们将 UI 划分为独立的、可重用的部分,并且可以对每个部分进行单独的思考。在实际应用中,组件常常被组织成层层嵌套的树状结构
这和我们嵌套 HTML 元系的方式类似,Vue 实现了自己的组件模型,使我们可以在每个组件内封装自定义内容与逻辑

1.创建组件以及引用关系
<template>
  <Header />
  <Main />
  <Aside />

</template>

<script>
import Header from './pages/Header.vue'
import Main from './pages/Main.vue'
import Aside from './pages/Aside.vue';

export default{
  components:{
    Header,
    Main,
    Aside
  }
}

</script>

<style>

</style>
2.组件注册方式-全局or 局部

一个Vue 组件在使用前需要先被”注册”,这样 Vue 才能在染模板时找到其对应的实现。组件注册有两种方
式;

全局注册和局部注册

全局注册虽然很方便,但有以下几个问题:

  • 全局注册,但并没有被使用的组件无法在生产打包时被自动移除(也叫“tree-shaking”)。如果你全局注册了一个组件,即使它并没有被实际使用,它仍然会出现在打包后的JS 文件中
  • 全局注册在大型项目中使项目的依赖关系变得不那么明确。在父组件中使用子组件时,不太容易定位子组件的实现。和使用过多的全局变量一样,这可能会影响应用长期的可维护性

全局注册在 main.js引用

// import './assets/main.css'

import { createApp } from 'vue'
import App from './App.vue'
import Header from './pages/Header.vue'

const app=createApp(App)

//在这中间 注册全局组件
app.component("Header",Header)
app.mount('#app')

2.组件传递数据

组件与组件之间不是完全独立的,而是有交集的,那就是组件与组件之间是可以传递数据的
传递数据的解决方案就是 props

parent.vue

<template>
<div>
    <h3>Parent</h3>
    <child title="Parent data" demo="demo"/>
    <child :title="message"/>
</div>
</template>


<script>
import child from './child.vue'
export default{
    data(){
        return{
            message:'ababa'
        }
    },
    components:{
        child
    }
}

</script>

<style scoped>
</style>

child.vue

<template>
<div>
    <h3>Child</h3>
    <p>{{ title }}</p>
    <p>{{ demo }}</p>
</div>
</template>


<script>

export default{

    data(){
        return{

        }
    },
    props:["title","demo"]
}

</script>

只能父传子,不能子传父

3.组件传递多种数据类型

通过 props 传递数据,不仅可以传递字符串类型的数据,还可以是其他类型,例如: 数字、对象、数组等

但实际上任何类型的值都可以作为 props 的值被传递

child.vue

<template>
<div>
    <h3>Child</h3>
    <p>{{ title }}</p>
    <!-- <p>{{ demo }}</p> -->
    <p>age--{{ age }}</p>
    <ul>
        <li v-for="(i,index) in names" :key="index">{{ i }}</li>
    </ul>
    <p>{{ userObj.name }}--{{ userObj.age }}--{{ userObj.sex }}</p>
</div>
</template>


<script>

export default{

    data(){
        return{

        }
    },
    props:["title","demo","age","names","userObj"]
}

</script>

4.组件传递数据的校验

Vue 组件可以更细致地声明对传入的 props 的校验要求

<template>
<div>
    <h3>Child</h3>
    <p>{{ title }}</p>
    <p>{{ test }}</p>
    <p>{{ defaultDate }}</p>
    <p v-for="(i,index) in language" :key="index">{{ i }}</p>
    <li>{{ message }}</li>

</div> 
</template>


<script>

export default{

    data(){
        return{
            message:this.$props.title
        }
    },
    props:{
        title:String,  //单类型校验
        test:[String,Array],  //多类型校验
        defaultDate:{
            type:String,
            default:'默认值'
        },
        language:{
            type:Array,
            default(){
                return ['默认值1','默认值2']
            }
        },
        mustData:{
            type:String,
            required: true //必选项
        }
    }
}

</script>

父级传过来的数据,只能读取不能直接修改

5.组件事件--子传父--emit

组件传递数据

组件之间传递数据的方案:

  • 父传子
  • 子传父

Parent.vue

<template>
    <h3>组件事件</h3>
    <childCon @someEvent="getHandle"/>
    <p>来自子组件的数据:{{ message }}--{{ messData }}</p>
</template>

<script>
    import childCon from './childCon.vue';
    export default{
        components:{
            childCon
        },
        methods:{
            getHandle(data,messData){
                console.log("触发了",data)
                this.message=data
                this.messData=messData
            }
        },
        data(){
            return{
                message:"",
                messData:""
            }
        }
    }
</script>

child.vue

<template>
    <h3>child</h3>
    <button @click="clickEvent">传递数据</button>
</template>

<script>
export default{
    methods:{
        clickEvent(){
            console.log("哈哈哈哈")
            //自定义事件
            this.$emit("someEvent",'childData',this.message)
        }
    },
    data(){
        return{
            message:9999
        }
    }
}

</script>

6.组件事件配合v-model使用

Search.vue

<template>
    <h3>搜索</h3>
    搜索:<input type="text" v-model="search">
</template>

<script>
export default{
    data(){
        return{
            search:''
        }
    },
    watch:{
        search(newData,oldData){
            this.$emit("SearchEvent",newData)
        }
    }
}

</script>

Main.vue

<template>
    <h3>Main 主页面--{{ message }}</h3>
    <Search @SearchEvent="getData"/>
</template>

<script>
import Search from './Search.vue';
export default {
    components:{
        Search
    },
    methods:{
        getData(data){
            this.message=data
        }
    },
    data(){
        return{
            message:""
        }
    }
}
</script>

7.组件的生命周期

每个Vue 组件实例在创建时都需要经历一系列的初始化步骤,比如设置好数据侦听,编译模板,挂载实例到DOM,以及在数据改变时更新 DOM。在此过程中,它也会运行被称为生命周期钩子的函数,让开发者有机会在特定阶段运行自己的代码

创建时: beforeCreate 、 created
渲染时: beforeMount 、 mounted
更新时: beforeUpdate 、 updated
卸载时: beforeUnmount 、 unmounted

1.通过ref 获取DOM结构
<template>
    <h3>组件生命周期函数应用</h3>
    <p name="name" ref="name">python</p>
</template>

<script>
export default{
    mounted(){
        console.log(this.$refs.name)
    }
}
</script>
2.模拟网络请求
<template>
    <h3>组件生命周期函数应用</h3>
    <p name="name" ref="name">python</p>
    <ul>
        <li v-for="(i,index) in banner" :key="index">{{ i.name }}-{{ i.content }}</li>
    </ul>
</template>

<script>
export default{
    mounted(){
        console.log(this.$refs.name)
    },
    data(){
        return{
            banner:[]
        }
    },
    mounted(){
        //模拟网络请求
        this.banner=[
            {'name':'xiaohui','content':'123'},
            {'name':'ahui','content':'123木头人'}
        ]
    }
}
</script>

8.动态组件 ---:is

<template>
    <component :is="tabCom"></component>
    <button @click="change">切换组件</button>
</template>

<script>
import ComA from'./components/ComA.vue'
import ComB from './components/ComB.vue'

export default{
  data(){
        return{
            tabCom:"ComA"
        }
    },
    components:{
      ComA,
      ComB
    },
    methods:{
      change(){
        if (this.tabCom=="ComA"){
            this.tabCom="ComB"
        }else{
          this.tabCom='ComA'
        }
      }
    }
}

</script>

<style>

</style>

9.组件保持存活

当使用.来在多个组件间作切换时,被切换掉的组件会被卸载。我们可以通过keep-alive 组件强制被切换掉的组件仍然保持“存活”的状态

<template>
    <KeepAlive>
      <component :is="tabCom"></component>
    </KeepAlive>
    <button @click="change">切换组件</button>
</template>

<script>
import ComA from'./components/ComA.vue'
import ComB from './components/ComB.vue'

export default{
  data(){
        return{
            tabCom:"ComA"
        }
    },
    components:{
      ComA,
      ComB
    },
    methods:{
      change(){
        if (this.tabCom=="ComA"){
            this.tabCom="ComB"
        }else{
          this.tabCom='ComA'
        }
      }
    }
}

</script>

<style>

</style>

child.vue

	<template>
    <h3>ComA</h3>
    <p>{{ msg }}</p>
    <button @click="update">更新数据</button>
</template>

<script>
export default{
    beforeUnmount(){
        console.log("组件卸载之前")
    },
    mounted(){
        console.log("组件卸载之后")
    },
    data(){
        return{
            msg:"老数据"
        }
    },
    methods:{
        update(){
           this.msg='now data'
    }
    }
}
</script>

10.异步组件

在大型项目中,我们可能需要拆分应用为更小的块,并仅在需要时再从服务器加载相关组件。Vue 提供了defineAsyncComponent 方法来实现此功能

<template>
    <KeepAlive>
      <component :is="tabCom"></component>
    </KeepAlive>
    <button @click="change">切换组件</button>
</template>

<script>
import { defineAsyncComponent } from 'vue'
import ComA from'./components/ComA.vue'
// import ComB from './components/ComB.vue'

//异步加载组件
const ComB = defineAsyncComponent(()=>
    import("./components/ComB.vue")
)
export default{
  data(){
        return{
            tabCom:"ComA"
        }
    },
    components:{
      ComA,
      ComB
    },
    methods:{
      change(){
        if (this.tabCom=="ComA"){
            this.tabCom="ComB"
        }else{
          this.tabCom='ComA'
        }
      }
    }
}

</script>

<style>

</style>

6.attribute 透传属性

1.属性继承

<template>
  <!-- <componentsEvent/> -->
  <attComponents class="attr"/>
  <Main/>
</template>

<script>
import componentsEvent from './components/componentsEvent.vue';
import Main from './components/Main.vue';
import attComponents from './components/attComponents.vue';

export default{
  components:{
    // componentsEvent
    // Main
    attComponents

  }
}

</script>

<style>

</style>
<template>
    <h3>attribute test</h3>
</template>


<style>
.attr{
    color: red;
}
</style>

2.禁用属性继承

<template>
    <h3>attribute test</h3>
</template>

<script>
    export default{
        inheritAttrs:false
    }
</script>

<style>
.attr{
    color: red;
}
</style>

7.插槽Slots

我们已经了解到组件能够接收任意类型的JavaScript 值作为 props,但组件要如何接收模板内容呢? 在某些场景中,我们可能想要为子组件传递一些模板片段,让子组件在它们的组件中渲染这些片段

1.基础

<template>
  <SoltBase>
    <div>
      <h3>插槽标题</h3>
      <p>插槽内容</p>
    </div>
  </SoltBase>
</template>

<script>
import SoltBase from './components/Slots/slotBase.vue'
export default{
  components:{
    SoltBase

  }
}

</script>

<style>

</style>
<template>
    <h3>插槽基础知识</h3>
    <slot></slot>
</template>

<script>

</script>

slot

续集

2.渲染作用域

<template>
  <slot2>
    <h3>插槽内容</h3>
    <h4>{{ message }}</h4>
    <h3 v-html="URL"></h3>
    
  </slot2>

</template>

<script>
import SoltBase from './components/Slots/slotBase.vue'
import slot2 from './components/Slots/slot2.vue';
export default{
  components:{
    slot2

  },
  data(){
        return{
            message:'插槽内容7777',
            URL:'<a href="www.baidu.com">百度一下</a>'
        }
    }
}

</script>

<style>

</style>

3.具名插槽

parent.vue

<template>
  <slot2>
    <template v-slot:header>
        <h3>插槽内容--header</h3>
    </template>

    <template v-slot:main>
        <h3>插槽内容main</h3>
    </template>
    
  </slot2>


</template>

child.vue

<template>
    <h1>slot 续集</h1>
    <slot name="header">
        <!-- <h1>插槽默认值main</h1> -->
    </slot>

    <a href="wwwwww">Zhogn</a>
    <slot name="main">
        <!-- <h1>插槽默认值main</h1> -->
    </slot>
</template>

v-slot 可以简写为#

4.插槽中的数据传递

在某些场景下插槽的内容可能想要同时使用父组件域内和子组件域内的数据。要做到这一点,我们需要一种方法来让子组件在渲染时将一部分数据提供给插槽
我们也确实有办法这么做!可以像对组件传递 props 那样,向一个插槽的出口上传递 attributes

1.基础数据传输
<template>
  <slot3 v-slot="slotProps">
        <h3>{{ currentTest }}--{{ slotProps.msg }}</h3>
  </slot3>


</template>

<script>
import SoltBase from './components/Slots/slotBase.vue'
import slot2 from './components/Slots/slot2.vue';
import slot3 from './components/Slots/slot3.vue'

export default{
  components:{
    slot3
  },
  data(){
        return{
            currentTest:"test content"
        }
    }
}

</script>

<style>

</style>

child.vue

<template>
    <h3>slot  再续集</h3>
    <slot :msg="childData" name="header">  </slot>
</template>

<script>
export default{
    data(){
        return{
            childData:'子组件数据'
        }
    },

}
</script>
2.具名插槽数据传输

patent.vue

<template>
  <slot3>
        <template #header="slotProps">
          <h3>{{ currentTest }}--{{ slotProps.msg }}</h3>
        </template>

        <template #main="slotProps">
          <p>{{ slotProps.demo }}</p>
        </template>
  </slot3>


</template>

<script>
import SoltBase from './components/Slots/slotBase.vue'
import slot2 from './components/Slots/slot2.vue';
import slot3 from './components/Slots/slot3.vue'

export default{
  components:{
    slot3
  },
  data(){
        return{
            currentTest:"test content"
        }
    }
}

</script>

<style>

</style>

child.vue

	<template>
    <h3>slot  再续集</h3>
    <slot :msg="childData" name="header">  </slot>
    <slot name="main" :demo="demo">  </slot>
</template>

<script>
export default{
    data(){
        return{
            childData:'子组件数据',
            demo:'demo'
        }
    },

}
</script>

8.依赖注入-跨组件透传

通常情况下,当我们需要从父组件向子组件传递数据时,会使用 props 。想象一下这样的结构: 有一些多层级嵌套的组件,形成了一颗巨大的组件树,而某个深层的子组件需要一个较远的祖先组件中的部分数据。在这种情况下,如果仅使用 props 则必须将其沿着组件链逐级传递下去,这会非常麻烦

孙子.vue

<template>
    <h3>comChild</h3>
    <p>{{ msg }}</p>
    <p>{{ fullmsg }}</p>
</template>

<script>
export default{
inject:["msg"],
data(){
    return{
        fullmsg:this.msg
    }
}

}


</script>

祖宗 vue

<template>
    <h3>祖宗</h3>
    <comParent/>
</template>

<script>
import comParent from './components/comParent.vue'
export default{
    data(){
        return{
            msg:"from 祖宗的财产"
        }
    },
    components:{
        comParent
    },
    // provide:{
    //      msg:"from 祖宗的财产"
    // },
    provide(){
        return{
            msg:this.msg
        }
    }

}


</script>

provide jnject 只能由上到下的传递 ,不能反向传递

定义全局数据,可在任意位置读取

main.js中

// import './assets/main.css'

import { createApp } from 'vue'
import App from './App.vue'

const app=createApp(App)

app.provide('msg','我是全局数据')

//在这中间 注册全局组件
// app.component("Header",Header)
app.mount('#app')