生活札记

Vue3学习笔记 - 入门(一)

copylian    1 评论    8347 浏览    2022.06.01

Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。

文档:https://cn.vuejs.org/guide/introduction.html

教程:https://www.bilibili.com/video/BV1QA4y1d7xf


1、下载安装Node.js(正常下载LTS版本):

    官网:https://nodejs.org/zh-cn/

    Node.js版本:node -v    =====>  v16.16.0

    npm版本:npm -v   =====>  8.11.0

    问题参考:

        1)、npm出现报错 npm WARN config global `--global`, `--local` are deprecated. Use `--location=global

        2)、npm ERR! Error: EPERM: operation not permitted, mkdir 'D:\Program Files\nodejs\node_cache\_cacache'

    或者更新npm执行:cnpm install -g npm

    或者直接把nodejs安装目录的执行权限调到最高


2、Vue渲染方式:

    1)、js引入:<script type="text/javascript" src="https://unpkg.com/vue@next"></script>

                <div id="counter">

                    <p>{{num}}</p>

                    <p>{{name}}</p>

                </div>

                <script type="text/javascript">

                    const Counter = {

                        data: function(){

                            return {

                                num:1,

                                name:"飓风呀~~~"

                            };

                        }

                    }

                    app = Vue.createApp(Counter).mount("#counter")

                    console.log(app)

                </script>


    2)、Vite安装:npm init vue@latest

微信图片_20220823102818.png

        进入目录:cd 项目目录

        安装:npm install

        运行:npm run dev

                <script>

                // 申明式渲染

                export default {

                  data(){

                    return {

                      num:100,

                      name:"飓风呀~~~"

                    }

                  }

                }

                </script>

                

                <template>

                  <div>

                    {{num}}

                    <p></p>

                    {{name}}

                  </div>

                </template>

                

                <style>

                </style>


3、基础:

    1)、属性、方法绑定:

    <span :[attributeName]="green">green color</span>

    <a @[eventName]="doSomething">ddddd</a>


    2)、计算属性与方法:区别是计算属性 computed 是带缓存的,只要依赖值不变则不会重新计算,方法methods不带缓存会多次执行

            computed: {

                // 简写格式

                reverseHelloWorld:function(){

                      return this.HelloWorld.split('').reverse().join('')

                },

                // 原始格式

                reverseHelloWorld2:{

                  get(){

                    console.log("获取")

                  },

                  // 更改的时候使用,正常计算属性不需要set方法

                  set(){

                    console.log("设置")

                  }

                }

              },


3)、watch监听:数据变化

            data(){

                return {

                  message:"飓风呀888",

                  message1:{

                    name:1,

                    page:2

                  },   

              },

    

            watch:{

                // 监听数据变化

                message: function(newValue, oldValue){

                  console.log(newValue, oldValue)

                },

                message:{

                  immediate:true, // 初始化就监听执行

                  handler:function(newValue, oldValue){

                    console.log(newValue, oldValue)

                  }

                },

                message1: {

                  deep: true, // 深度监听,对象数据可进行深度监听,会一直监听整个对象

                  handler: function (newValue, oldValue) {

                    console.log(newValue, oldValue)

                  }

                },

                "message1.page": { //这种就是只监听对象里的某个元素

                  deep: true, // 深度监听,对象数据可进行深度监听,会一直整个对象

                  handler: function (newValue, oldValue) {

                    console.log(newValue, oldValue)

                  }

                }

              }


4)、class与style:class对象里面格式:类名控制变量数组里的是变量对应的值style里对应的格式:样式属性值变量的值

    <p class="red" :class="{ borderGreen: true, fontSzie: isClass }">我是红色</p>

    <p class="red" :class="styleObj">我是红色</p>

    <p :class="[greenClass, { borderGreen: true}]">我是绿色</p>

    <p :style="{ color: [redClass] }">redClass</p>

    <div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }">display</div>


5)、v-if、v-else-if、v-else与v-show、v-for:条件控制,v-if 不显示的部分不在dom中,v-show隐藏的部分是在dom中相当于display:none

        <div>

              <p>5、v-if、v-show、for</p>

              <p v-if="age > 18">成年了</p>

              <p v-else-if="age == 18">刚成年</p>

              <p v-else>未成年</p>

        

              <!-- template 是不显示的标签 -->

              <template v-if="isShow">

                <div>

                  template 是不显示的标签

                </div>

              </template>

        

              <p v-show="isShow">我显示</p>

              <p v-show="isNoShow">我不显示</p>

        

              <ul>

                <li v-for="(item,index) in forArrData" :key="index">{{ item }} - {{index}}</li>

              </ul>

              <ul>

                <li v-for="(item,key,index) in forObjData" :key="index">{{ item }} - {{key}} - {{index}}</li>

              </ul>

              <ul>

                <!-- key是一个唯一标识符,快速找到节点,提高性能 -->

                <li v-for="(item,index) in forArrData" :key="item">

                  <input type="checkbox" name="a[]" id="a_">{{ item }} {{index}}

                </li>

                <button type="button" @click="changeForData">点击改变Key</button>

              </ul>

            </div>


6)、数组更新检测:数组相关函数:pop()、push()、shift()、unshift()、splice()、sort()、reverse()

            // pop():从后面删除

           this.arrList.pop(10)

    

           // push():从后面添加

           this.arrList.push(10,11)

    

           // shift():从前面删除

           this.arrList.shift()

    

           // unshift():从前面添加

           this.arrList.unshift(1,2,3)

    

           // splice():删除(位置,长度)、添加(位置,0,...数据)、替换(位置,长度,...数据)

           this.arrList.splice(1,2)  // 删除

           this.arrList.splice(1,0,300,400) // 添加

           this.arrList.splice(1, 2, 300, 400) // 替换

    

           // sort():排序

           this.arrList.sort()

    

           // reverse():反向

           this.arrList.reverse()

    

            // 更改某一项

            this.arrList[1] = 100


7)、事件绑定与事件修饰符:

    1)、事件:$event

    2)、事件修饰符:.stop、.prevent、.once、.self、.capture、.passive

    3)、按钮、键盘修饰符:.enter、.tab、.delete、.esc、.space、.up、.down、.left、.right、.ctrl、.alt、.shift、.meta

    <div>

              <p>7、事件绑定与修饰符</p>

              <p><button type="button" @click="counter++">js事件改变{{counter}}</button></p>

              <p><button type="button" @click="changeCounter(5)">函数方法改变{{counter}}</button></p>

              <p><button type="button" @click="changeCounter(5,$event)">函数方法改变,传递事件{{counter}}</button></p>

              <p><button type="button" @click="changeCounter(5,$event),changeAge(10,$event)">多个函数方法改变,传递事件{{counter}} -

                  {{counterAge}}</button></p>

        

              <!-- 阻止冒泡 -->

              <div @click="divClick">

                  <span @click.stop="spanClick">点击冒泡</span>

              </div>

        

              <!-- 禁止事件 -->

              <form action="">

                <button type="submit" @click.prevent="btnSubmit">提交</button>

              </form>

        

              <!-- 按键事件 -->

              <input type="text" name="" value="" @keyup.enter="keyUp">

            </div>


8)、表单输入绑定v-model修饰符:.lazy、.number、.trim

            data(){

                return {

                  // v-model表单控件

                  username:"",

                  fruits:["苹果"],

                  sex:"女",

                  lange:"PHP",

                  job: ["模特"],

                  coute:0

                }

              },

             

            <div>

                  <p>8、v-model表单控件:</p>

                  <p>UserName:{{username}}</p>

                  <p><input type="text" v-model="username" /></p>

                  <p>

                    <span>{{fruits}}</span><br>

                    <input type="checkbox" v-model="fruits" value="苹果">苹果

                    <input type="checkbox" v-model="fruits" value="香梨">香梨

                    <input type="checkbox" v-model="fruits" value="香蕉">香蕉

                    <input type="checkbox" v-model="fruits" value="菠萝">菠萝

                  </p>

                  <p>

                    <span>{{sex}}</span><br>

                    <input type="radio" v-model="sex" value="男">男

                    <input type="radio" v-model="sex" value="女">女

                  </p>

                  <p>

                    <span>{{lange}}</span><br>

                    <select v-model="lange">

                      <option value="PHP">PHP</option>

                      <option value="VueJs">VueJs</option>

                      <option value="GoLang">GoLang</option>

                    </select>

                  </p>

                  <p>

                    <span>{{job}}</span><br>

                    <select v-model="job" multiple="multiple">

                      <option value="模特">模特</option>

                      <option value="歌手">歌手</option>

                      <option value="玩泥巴">玩泥巴</option>

                    </select>

                  </p>

            

                  <!-- 失去焦点更新 -->

                  <p>UserName:{{username}}</p>

                  <p>懒更新:<input type="text" v-model.lazy="username" /></p>


                  <!-- 转数字,字符串原样输出 -->

                  <p>数字{{ coute }}:<input v-model.number="coute" /></p>


                  <!-- 前后去空值 -->

                  <p>去空:<input v-model.trim="username" /></p>

                </div>


9)、component 组件:组件划分为独立的、可重用的部分,组件常常被组织成层层嵌套的树状结构。每个组件都是独立的实例

components.7fbb3771.png


            App.vue:

            

            <script>

            // 每个组件都是独立的实例

            import Header from "./components/Header.vue"

            import Footer from "./components/Footer.vue"

            

            // 申明式渲染

            export default {

              data(){

                return {

                  msg: "Main",

                  copyRight:"飓风呀,版权所有",

                  arrList:[1,2,3,4],

                  objList:{

                    name:"飓风呀",

                    sex:"女",

                    age:100

                  }

                }

              },

              // 加载组件

              components:{

                Header,

                Footer

              }

            }

            </script>

            

            <template>

              <div>

                <Header></Header>

                <Header></Header>

                <Header></Header>

                <p>{{msg}}</p>


                <!--组件属性传递-->

                <Footer :copyright="copyRight" :titleName=200 :arrlist="arrList" :objlist="objList"></Footer>

              </div>

            </template>

            

            Header.vue:

            

            <script>

            // 全局参数

            const obj = {

                title: "Header"

            }

            export default {

                // 组件里面的每个data数据都是独立的,也就是每个组件之间互不影响

                data(){

                    return {

                        title: "Header"

                    }

                },

                // 如果data返回值是同一个则会影响所有

                // data() {

                //     return obj

                // },

                methods: {

                    changeTitle(){

                        this.title = "Header666"

                    }

                }

            }

            </script>

            

            <template>

                <div>

                    <p class="title">{{ title }}</p>

                    <p><button type="button" @click="changeTitle">点击改变</button></p>

                </div>

            </template>

            

            <style>

            .title {

                color: red;

                font-size: 28px;

            }

            </style>

            

            

            Footer.vue:

            

            <script>

            export default {

                data(){

                    return {

                        title: "Footer"

                    }

                },

            

                // 接受父组件传递的参数

                // props: ["copyright", "title"],

                props:{

                    copyright:{

                        type: String,

                        default: "copyright @ 123456",

                        required: true

                    },

                    titleName:{

                        type: Number,

                        default: 1,

                        required: true

                    },

                    arrlist:{

                        type:Array,

                        default(){

                            return [6,7,8]

                        }

                    },

                    objlist: {

                        type: Object,

                        default() {

                            return {}

                        }

                    }

                }

            }

            </script>

            

            <template>

                <div>

                    <p class="title">{{ titleName }}</p>

                    <p>版权:{{ titleName }} - {{ copyright }}</p>

                    <ul>

                        <li v-for="(item, index) in arrlist" :key="item">{{item}} - {{index}}</li>

                    </ul>

                    <ul>

                        <li v-for="(item, index, key) in objlist" :key="item">{{item}} - {{index}} - {{ key }}</li>

                    </ul>

                </div>

            </template>

            

            <style>

            .title {

                color: green;

                font-size: 25px;

            }

            </style>

            

            父子组件访问方式:

            methods: {

                    sendParent() {

                        // 通过$emit触发事件,this.$emit("事件名称","参数数据")

                        this.$emit("headerName", this.headerName)

                    }

                },

                mounted() {

                    // 子组件获取父组件数据

                    console.log(this.$parent)

                    console.log(this.$parent.copyRight)

                    console.log(this.$root)

                },

            

            <div>

                    <!-- 父子组件访问方式 -->

                    <!-- 1、父组件访问子组件:$refs,开发中常用,ref属性用来给子组件或子元素注册引用信息 -->

                    <!-- 2、子组件访问父组件:$parant,在开发中尽量少用,组件复用性高 -->

                    <!-- 3、子组件访问根组件:$root -->

                    <Header @headerName="getHeaderName" ref="header"></Header>

                    {{title}}

                    <p ref="p" id="ps">子组件的headerName:{{ headerName }}</p>

                    <Footer :copyright="copyRight" :titleName=200 :arrlist="arrList" :objlist="objList"></Footer>

                </div>

    

10)、slot 插槽:为子组件传递一些模板片段,让子组件在它们的组件中渲染这些片段。顾名思义就是一个坑,等着被填充。

named-slots.ebb7b207.png

slots.dbdaf1e8.png

            子组件SlotDemo.vue:

            

            <script>

            // 申明式渲染

            export default {

                data(){

                    return {

                        title: "Solt",

                        listArr:[1,2,3,4,5],

                        message:"solt3",

                        message1:"solt4"

                    }

                }

            }

            </script>

            

            <template>

                <div>

                    {{title}}

                    <slot>solt1</slot>

                    <!-- 具名插槽 -->

                    <slot name="slot2"></slot>

            

                    <!-- 作用域插槽:传递变量参数 -->

                    <slot name="slot3" :listArr="listArr" :message="message"></slot>

                    <slot name="slot4" :listArr="listArr" :message="message1">slot4</slot>

                </div>

            </template>


            父组件Content.vue:

            

            <script>

            // 每个组件都是独立的实例

            import SlotDemo from "./SlotDemo.vue"

            

            // 申明式渲染

            export default {

                data(){

                    return {

                        title: "Content"

                    }

                },

                components: {

                    SlotDemo

                }

            }

            </script>

            

            <template>

                <div>

                    <!-- 插槽 -->

                    <SlotDemo>

                        slot1111

            

                        <!-- 具名插槽 -->

                        <template v-slot:slot2>

                            slot2

                        </template>

            

                        <!-- 作用域插槽:获取子组件变量 -->

                        <template #slot3="slotProps">

                            <ul>

                                <li v-for="(item,index) in slotProps.listArr" :key="item">{{ item }} - {{ index }}</li>

                            </ul>

                            {{ slotProps.message }}

                        </template>

                        <!-- 作用域插槽:变量解析出来 -->

                        <template v-slot:slot4="{ listArr, message }">

                            <ul>

                                <li v-for="(item,index) in listArr" :key="item">{{ item }} - {{ index }}</li>

                            </ul>

                            {{ message }}

                        </template>

                    </SlotDemo>

                </div>

            </template>


11)、provide / inject 依赖注入:通过 provide() 提供一个值,可以被后代组件注入,通过 inject() 注入一个由祖先组件或整个应用 (通过 app.provide()) 提供的值。

            祖先组件App.vue:

            <script>

            // 每个组件都是独立的实例

            import Content from "./components/Content.vue"

            

            // 申明式渲染

            export default {

              data(){

                return {

                  msg: "Main",

                  parentData: "parentData6666",

                  obj:{

                    parentData: "parentData6666"

                  }

                }

              },

              // provide/inject不是响应式

              // provide: { parentData: "parentData6666" },

              // 如果想去访问组件实例属性,要使用方法返回对象的形式

              provide(){

                return {

                  // parentData: this.parentData, // 不是想响应式

                  // parentData: this.obj, // 对象方式可以响应式

                  parentData:()=>this.parentData // 方法方式可以响应式

                }

              },

              components:{

                Content

              },

              methods:{

                changeParent(){

                  this.parentData = "祖先数据改变了:aaaa"

                }

              }

            }

            </script>

            

            <template>

              <div>

                <p>祖先数据:{{ parentData }}</p>

                <p><button type="button" @click="changeParent">改变祖先数据</button></p>

                <p>{{msg}}</p>

                <Content></Content>

              </div>

            </template>

            

            孙子组件SlotDemo.vue:

            <script>

            // 申明式渲染

            export default {

                data(){

                    return {

                        title: "Solt",

                        listArr:[1,2,3,4,5],

                        message:"solt3",

                        message1:"solt4"

                    }

                },

                // 接受祖先数据

                inject: ["parentData"],

                computed: { // 计算属性

                    parentDataNew(){

                        return this.parentData()

                    }

                },

            }

            </script>

            

            <template>

                <div>

                    <p>子组件获取祖先数据</p>

                    <p>{{ parentData() }}</p>

                    <p>{{ parentDataNew }}</p>

                </div>

            </template>


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

lifecycle.16e4c08e.png

            组件Life.vue:

            <script>

            export default {

                data(){

                    return {

                        title: "Life",

                        isShow:true

                    }

                },

                beforeCreate() {

                    console.log("Before create")

                },

                created() {

                    console.log("Created")

                },

                beforeMount() {

                    console.log("Before mount")

                },

                mounted() {

                    console.log("mounted")

                },

                beforeUpdate() {

                    console.log("Before update")

                },

                updated() {

                    console.log("Updated")

                },

                beforeUnmount() {

                    console.log("beforeUnmount")

                },

                unmounted() {

                    console.log("unmounted")

                },

                methods:{

                    changeData(){

                        this.title = "改变数据~~~"

                    }

                }

            }

            </script>

            

            <template>

                <div>

                    <p>生命周期:{{title}}</p>

                    <p><button type="button" @click="changeData">改变数据</button></p>

                </div>

            </template>


            组件Content.vue:

            <script>

            // 每个组件都是独立的实例

            import Life from "./Life.vue"

            

            // 申明式渲染

            export default {

                data(){

                    return {

                        isShow:true

                    }

                },

                beforeUnmount() {

                    console.log("beforeUnmount")

                },

                unmounted() {

                    console.log("unmounted")

                },

            }

            </script>

            

            <template>

                <div>

                    <!-- 生命周期 -->

                    <Life v-if="isShow"></Life>

                    {{ isShow }}

                    <p><button type="button" @click="isShow=!isShow">销毁数据</button></p>

                </div>

            </template>


4、Vue3组合式Api:setup():组合式 API (Composition API) 是一系列 API 的集合,使我们可以使用函数而不是声明选项的方式书写 Vue 组件。

            父组件App.vue:

            <script>

            // 每个组件都是独立的实例

            import {provide, ref} from "vue"

            import Setup from "./components/Setup.vue"

            

            // 申明式渲染

            export default {

              data(){

                return {

                  msg: "Main",

                  parentData: "parentData6666",

                  obj:{

                    parentData: "parentData6666"

                  }

                }

              },

              setup(props) {

                // 父组件provide传递数据到子组件

                let provideData = ref("飓风呀999") // 这是一个ref响应式

                provide("provideData", provideData) // 传递的是一个对象

                function changProvide(){

                  provideData.value = "bbb"

                  console.log(provideData.value)

                }

                return { changProvide } // 暴露数据

              },

             

              components:{

                Setup

              },

              mounted() {

                console.log(this.$refs.content) // 通过 $refs 获取组件数据

              },

              methods:{

                changeParent(){

                  this.parentData = "祖先数据改变了:aaaa"

                },

                getSonData(value){

                  alert(value);

                }

              }

            }

            </script>

            

            <template>

              <div>

                <p>{{msg}}</p>

                <p>祖先数据:{{ parentData }}</p>

                <p><button type="button" @click="changeParent">改变祖先数据</button></p>

                <p><button type="button" @click="getSonData">获取子组件数据</button></p>

                <Setup :message="parentData" class="a" data="b" aaa="ccc" :msg="msg" @sendParent="getSonData" ref="content"></Setup>

                <p><button type="button" @click="changProvide">更改setup的provide数据</button></p>

              </div>

            </template>

            

            子组件Setup.vue:   

            <script>

            // 导入引用

            import { ref, reactive, toRefs, watch, watchEffect, computed, onBeforeMount, onMounted, onBeforeUpdate, onUpdated, h, inject } from "vue"

            

            // 申明式渲染

            export default {

                data(){

                    return {

                        title: "Setup"

                    }

                },

                // setup 组合式api:将同一个逻辑关注点相同的代码收集在一起

                setup(props, context) {

                    // 组件在创建之前执行,this无法指向实例

                    console.log("setup")

            

                    // 1、改变setup里的数据

                    let msg = "setup"

                    function changeSetupMsg(){

                        msg += 1 // 这里的数据不是响应式的

                        console.log(msg)

                    }

            

                    // 2、响应式

                    let counter = ref(0) // ref() 返回带有value值的对象

                    function changeSetupCounter(){

                        counter.value++

                        console.log(counter)

                    }

            

                    // reactive() 定义响应式对象

                    let obj = reactive({

                        name: "飓风呀",

                        age:20,

                        child:{

                            sex:"女"

                        }

                    })

                    function changeSetupReactive(){

                        obj.name = "飓风呀呀呀"

                        console.log(obj)

                    }

            

                    // reactive() 定义响应式对象

                    let obj1 = reactive({

                        name: "飓风呀",

                        age: 20,

                        child: {

                            sex: "女"

                        }

                    })

                    function changeSetupReactiveToRefs(){

                        obj1.name = "飓风呀呀呀巴拉巴拉巴拉"

                        console.log(obj1)

                    }

            

                    // 3、watch() 与 watchEffect() 监听

                    // 1、watchEffct() 不需要监听属性,会自动收集依赖,只要在回调函数中引用到了响应式属性,发生变化后回调就会执行

                    //    wathch() 只能监听指定的属性,做出回调函数的执行,可以监听多个

                    // 2、watch() 可以拿到新值newValue、旧值oldValue,watchEffct()拿不到

                    // 3、watchEffct() 在初始化的时候会自动执行一次,用来收集依赖,watch() 不需要,一开始就指定了

                    let watchCouter  = ref(10)

                    let watchObj = reactive({

                        name: "飓风呀",

                        age: 20,

                        child: {

                            sex: "女"

                        }

                    })

            

                    // 监听数据

                    watch(watchCouter, function(newValue, oldValue){

                        console.log(newValue+":"+oldValue)

                    })

                    function changewatchCouter(){

                        watchCouter.value++

                        console.log(watchCouter.value)

                    }

            

                    // 监听对象

                    watch(watchObj, (newValue, oldValue) => {

                        console.log(newValue)

                        console.log(oldValue)

                    })

                    function changewatchWatchObj() {

                        watchObj.age++

                        console.log(watchObj)

                    }

                    // watchEffect(回调函数)不需要指定属性,组件初始化会执行一次回调函数,自动收集依赖

                    watchEffect(()=>{

                        // console.log(watchObj.age)

                    })

            

                    // 4、computed() 计算属性:返回一个带value值得属性对象

                    let computedCouter = ref(10)

                    let computedObj = reactive({

                        name: "飓风呀",

                        age: 20,

                        child: {

                            sex: "女"

                        },

                        computedCouterAge:computed(()=>{

                            return computedObj.age += 5

                        })

                    })

                    let computedCouterNew = computed(()=>{

                        // 返回一个带value值得属性对象

                        return computedCouter.value += 20

                    })

            

                    // 5、生命周期钩子

                    onBeforeMount(() => {

                        // console.log("onBeforeMount")  

                    })

                    onMounted(() => {

                        // console.log("onMounted")

                    })

                    onBeforeUpdate(() => {

                        // console.log("onBeforeUpdate")

                    })

                    onUpdated(() => {

                        // console.log("onUpdated")

                    })

            

                    // 6、props 与 context

                    let { message } = toRefs(props) // 转成响应式

                    onUpdated(() => {

                        console.log(message.value)

                    })

            

                    // 7、context 参数:

                    // 1)、context.attrs(属性:非响应式对象,等同于 $attrs)

                    console.log(context.attrs.class)

            

                    // 2)、context.slots(插槽:非响应式对象,等同于 $slots)

                    console.log(context.slots)

            

                    // 3)、context.emit(触发事件,等同于 $emit)

                    let counterEmit = ref(666)

                    function sendParent() {

                        context.emit("sendParent", counterEmit.value)

                    }

            

                    // 4)、context.expose(暴露公共 property)

                    let counterExpose = ref(888)

                    context.expose({ sendParent, counterExpose }) // 暴露属性、方法,父级组件可通过 $refs 获取到

                    return () => h("div", counterExpose.value) // h() 直接渲染

            

                    // 8、provide() 与 inject() :

                    let provideData = inject("provideData")

            

                    // 通过ES6扩展符号...解构出来的数据不是响应式的,如果需要解构成响应式需要:toRefs() 方法转换

                    // 暴露数据

                    return { 

                        msg, 

                        changeSetupMsg, 

            

                        counter, 

                        changeSetupCounter, 

            

                        changeSetupReactive, 

                        obj, 

            

                        changeSetupReactiveToRefs,

                        ...toRefs(obj1), // 对象解构,通过toRefs输出成响应式

            

                        watchCouter,

                        changewatchCouter,

            

                        watchObj,

                        changewatchWatchObj,

            

                        computedCouterNew,

                        computedObj,

            

                        message,

            

                        sendParent,

            

                        provideData

                    }

                },

            

                // setup() 组合式api也必须有 props

                props:{

                   message:{

                        type:String,

                        default:"飓风呀~~~"

                   } 

                },

                beforeCreate() {

                    // console.log('beforeCreate')

                },

                created() {

                    // console.log('created')

                },

            }

            </script>

            

            <template>

                <div>

                    <p>标题:{{title}}</p>

                    <p>消息不响应:{{ msg }}</p>

                    <p><button type="button" @click="changeSetupMsg">改变msg里的数据</button></p>

            

                    <p>计数器响应:{{ counter }}</p>

                    <p><button type="button" @click="changeSetupCounter">改变couter里的数据</button></p>

            

                    <p>reactive响应式对象:{{ obj.name }} - {{ obj.age }} - {{ obj.child.sex }}</p>

                    <p><button type="button" @click="changeSetupReactive">改变reactive响应式对象里的数据</button></p>

            

                    <p>reactive解构数据:{{ name }} - {{ age }} - {{ child.sex }}</p>

                    <p><button type="button" @click="changeSetupReactiveToRefs">改变reactive响应式对象里的数据</button></p>

            

                    <p>watch数据:{{ watchCouter }}</p>

                    <p><button type="button" @click="changewatchCouter">改变watch数据</button></p>

            

                    <p>watch数据:{{ watchObj.name }} - {{ watchObj.age }} - {{ watchObj.child.sex }}</p>

                    <p><button type="button" @click="changewatchWatchObj">改变watch数据</button></p>

            

                    <p>计算属性:{{ computedCouterNew }}</p>

                    <p>计算对象属性:{{ computedObj.computedCouterAge }}</p>

            

                    <p>父级传递的属性:{{ message }}</p>

            

                    <p>context.emit:<button type="button" @click="sendParent">向父级传递数据</button></p>

            

                    <p>provide/inject:{{ provideData }}</p>

                </div>

            </template>


            组件Setup2.vue:setup语法糖直接暴露所有的属性、方法

            <script setup>

            // 导入引用

            import { ref } from "vue"

            

            // 导入组件

            import Footer from "./Footer.vue"

            

            // 定义变量

            let title = "Setup2"

            let msg = ref("消息内容")

            function changeSetupMsg(){

                msg.value = "消息内容666"

            }

            </script>

            

            <template>

                <div>

                    <p>标题:{{title}}</p>

                    <p>消息不响应:{{ msg }}</p>

                    <p><button type="button" @click="changeSetupMsg">改变msg里的数据</button></p>

                    <!--组件无需通过components加载注册-->

                    <Footer></Footer>

                </div>

            </template>

只袄早~~~
感谢你的支持,我会继续努力!
扫码打赏,感谢您的支持!

文明上网理性发言!