Vue3、Vite、Pinia基础学习

news2024/9/22 6:19:48

Vue3

1、创建一个Vue3应用

<script src="vue.global.js"></script>
<body>
    <div id="app">
        {{msg}}
        <h2>{{person.title}}</h2>
        <h2>{{person.name}}</h2>
    </div>
    <script>
        // 采用解构的方式可以省略Vue.createApp和Vue.reactive前的Vue
        const{createApp,reactive}=Vue;

        Vue.createApp({
            // setup选项用于设置响应式数据和方法
            setup(){
                const person=Vue.reactive({
                    title:"Vue学习",
                    name:"sss",
                })
                return{
                    msg:"success",
                    person
                }
            }
        }).mount("#app")    //mount用于挂载到id为app的标签上
    </script>
</body>

2、Vue3模块化开发

<body>
    <div id="app">
        {{msg}}
        <h2>{{person.title}}</h2>
        <h2>{{person.name}}</h2>
    </div>
    <!-- 模块化开发 -->
    <script type="module">
        // 采用解构的方式可以省略Vue.createApp和Vue.reactive前的Vue
        import {createApp,reactive} from './vue.esm-browser.js'

        createApp({
            // setup选项用于设置响应式数据和方法
            setup(){
                const person=reactive({
                    title:"Vue学习",
                    name:"sss",
                })
                return{
                    msg:"success",
                    person
                }
            }
        }).mount("#app")    //mount用于挂载到id为app的标签上
    </script>
</body>

3、ref和reactive的区别

<body>
    <div id="app">
        {{msg}}
        <h2>{{person.title}}</h2>
        <h2>{{person.name}}</h2>
    </div>
    <script type="module">
        import {createApp,reactive} from './vue.esm-browser.js'

        createApp({
            setup(){
                const number=ref(10);//ref用于存储单个基本类型的数据,如:数字、字符串、数组等
                const arr=ref([1,2,3,4]);

                number.value=200;//使用ref创建的响应式对象,需要通过.value属性来访问和修改其值

                // reactive用于存储复杂数据类型,如对象或数组等
                const person=reactive({
                    title:"Vue学习",
                    name:"sss",
                })
                person.name="scu";//使用reactive创建的响应式对象,可以直接通过属性名来访问和修改值

                return{
                    msg:"success",
                    person
                }
            }
        }).mount("#app")    
    </script>
</body>

4、绑定事件v-on

<body>
    <div id="app">
        {{msg}}
        <h2>{{person.title}}</h2>
        <h2>{{person.name}}</h2>

        <!-- 绑定事件 -->
        <button v-on:click="edit">修改</button>
        <br>
        <!-- v-on简写形式 -->
        <button @click="edit">修改(简写形式)</button>
    </div>
    <script type="module">
        import {createApp,reactive} from './vue.esm-browser.js'

        createApp({
            setup(){
                const person=reactive({
                    title:"Vue学习",
                    name:"sss",
                })
                
                //构建函数
                const edit=()=>{
                    person.name="hjklakhs";
                }

                return{
                    msg:"success",
                    person,
                    edit
                }
            }
        }).mount("#app")    
    </script>
</body>

5、按键修饰符

按键修饰符:

  • enter回车
  • space空格
  • tab键
  • keyup是在用户松开按键时才触发
  • keydown是在用户按下按键时立即触发
<body>
    <div id="app">
        {{msg}}
        <h2>{{person.title}}</h2>
        <h2>{{person.name}}</h2>
        <h2>{{person.user}}</h2>

        <!-- 按键修饰符 -->
        回车<input type="text" @keyup.enter="add(40,60)"><br>
        空格<input type="text" @keyup.space="add(20,30)"><br>
        Tab <input type="text" @keydown.tab="add(30,40)"><br>
        w   <input type="text" @keyup.w="add(32,43)"><br>

        <!-- 组合快捷键 -->
        ctrl + Enter <input type="text" @keyup.ctrl.enter="add(34,58)"><br>
        ctrl + A     <input type="text" @keyup.ctrl.a="add(22,30)"><br>

    </div>
    <script type="module">
        import {createApp,reactive} from './vue.esm-browser.js'

        createApp({
            setup(){
                const person=reactive({
                    title:"Vue学习",
                    name:"sss",
                    user:0
                })

                const add=(x,y)=>{
                    person.user+=x+y;
                }

                return{
                    msg:"success",
                    person,
                    add
                }
            }
        }).mount("#app")    
    </script>
</body>

6、显示和隐藏v-show

  • v-show通过css display属性来控制元素的显示或隐藏
  • v-show适用于频繁切换元素的显示状态,因为只改变display属性,不需要重新渲染整个组件
<body>
    <div id="app">
        {{web.show}}
        <hr>
        <!-- 显示和隐藏v-show -->
        <p v-show="web.show">西游记 黑神话悟空</p>

        <button @click="toggle()">切换状态</button>
    </div>
    <script type="module">
        import{createApp,reactive} from './vue.esm-browser.js'
        createApp({
            setup(){
                const web=reactive({
                    show:true
                })
                const toggle=()=>{
                    web.show=!web.show;
                }
                return{
                    web,
                    toggle
                }
            }
        }).mount("#app")
    </script>
</body>

7、条件渲染v-if

  • v-if用于对元素进行条件渲染,当条件为true时,渲染该元素,为false时,则不渲染
  • v-if适用于较少改变的场景,因为频繁从dom中删除或添加元素,会导致性能下降
<body>
    <div id="app">
        {{web.show}}
        <hr>
        <!-- v-if条件渲染 -->
        <p v-if="web.show">西游记 黑神话悟空</p>

        <button @click="toggle()">切换状态</button>

        <!-- v-if-else -->
        <p v-if="web.user<1000">新网站</p>
        <p v-else-if="web.user>=1000&&web.user<=10000">优秀网站</p>
        <p v-else="web.user">资深网站</p>
    </div>
    <script type="module">
        import{createApp,reactive} from './vue.esm-browser.js'
        createApp({
            setup(){
                const web=reactive({
                    show:true,
                    user:10005
                })
                const toggle=()=>{
                    web.show=!web.show;
                }
                return{
                    web,
                    toggle
                }
            }
        }).mount("#app")
    </script>
</body>

8、动态属性绑定v-bind

  • 单向数据绑定:当数据发生改变时,视图会自动更新,但用户手动更改input的值,数据不会自动更新。
  • 单向数据绑定<input type="text"  :value="data.txt">
    <style>
        .textColor{
            color: rebeccapurple;
        }
    </style>

<body>
    <div id="app">
        <!-- 动态属性绑定v-bind -->
        <!-- :value -->
        <h3>value="www.baidu.com"</h3>
        <!-- <input type="text" value="www.baidu.com"> -->
        <input type="text" v-bind:value="web.url">
        <!-- 简写 -->
        <input type="text" :value="web.url">

        <!-- :src -->
        <h3>src="dhimg1.png"</h3>
        <!-- <img src="../resource/image/dhimg1.png" alt=""> -->
        <img :src="web.img" alt="">

        <!-- :class -->
        <h3>class="textColor"</h3>
        <!-- <b class="textColor">西游记</b> -->
        <b :class="{textColor:web.Status}">西游记</b>
    </div>
    <script type="module">
        import{createApp,reactive} from './vue.esm-browser.js'
        createApp({
            setup(){
                const web=reactive({
                    url:"www.baidu.com",
                    img:"../resource/image/dhimg1.png",
                    Status:true
                })
                return{
                    web
                }
            }
        }).mount("#app")
    </script>
</body>

9、遍历数组或对象v-for

<body>
    <div id="app">
        <!-- 遍历数组或对象v-for -->
        <ul>
            <li v-for="(value,index) in web.number">
                {{index}}:{{value}}
            </li>
        </ul>
        <ul>
            <li v-for="(value,key,index) in web.user">
                {{index}}:{{key}}:{{value}}
            </li>
        </ul>
        <ul>
            <template v-for="(value,key,index) in web.user">
                <li v-if="index==1">
                    {{index}}:{{key}}:{{value}}
                </li>
            </template>
        </ul>
        <ul>
            <li v-for="(value,index) in web.teacher" :title="value.name" :key="value.id">
                {{index}}:{{value.id}}:{{value.name}}:{{value.web}}
            </li>
        </ul>
    </div>
    <script type="module">
        import{createApp,reactive} from './vue.esm-browser.js'
        createApp({
            setup(){
                const web=reactive({
                    number:["十","十一","十二"],//数组
                    user:{
                        name:"sss",
                        age:20
                    },//对象
                    teacher:[
                        {id:100,name:"lucy",web:"baidu.com"},
                        {id:101,name:"jucy",web:"bai.com"}
                    ]//包含两个对象的数组
                })
                return{
                    web
                }
            }
        }).mount("#app")
    </script>
</body>

10、双向数据绑定v-model

  • 双向数据绑定:当数据发生改变时,视图会自动更新,用户手动更改input的值,数据也会自动更新。对于<input type="text">,v-model绑定的是input元素的value属性。
  • 双向数据绑定<input type="text"  v-model=“data.txt">
<body>
    <div id="app">
        <!-- 双向数据绑定v-model -->
        <h3>文本框{{data.text}}</h3>
        <h3>单选框{{data.radio}}</h3>
        <h3>复选框{{data.checkbox}}</h3>
        <h3>记住密码{{data.remember}}</h3>
        <h3>下拉框{{data.select}}</h3>
        <!-- 单向数据绑定 -->
        <input type="text" :value="data.text">
        <br>
        <!-- 双向数据绑定 -->
        <input type="text" v-model="data.text">
        <br>
        <!-- 单选框 -->
        <input type="radio" v-model="data.radio" value="1">写作
        <input type="radio" v-model="data.radio" value="2">画画
        <br>
        <!-- 复选框 -->
        <input type="checkbox" v-model="data.checkbox" value="a">写作
        <input type="checkbox" v-model="data.checkbox" value="b">画画
        <input type="checkbox" v-model="data.checkbox" value="c">运动
        <br>
        <!-- 单个复选框 -->
        <input type="checkbox" v-model="data.remember">记住密码
        <br>
        <!-- 下拉框 -->
        <select v-model="data.select">
            <option value="">请选择</option>
            <option value="A">写作</option>
            <option value="B">画画</option>
            <option value="C">运动</option>
        </select>
    </div>
    <script type="module">
        import{createApp,reactive} from './vue.esm-browser.js'
        createApp({
            setup(){
                const data=reactive({
                    text:"baidu.com",//文本框
                    radio:"",//单选框
                    checkbox:[],//复选框
                    remember:false,//单个复选框 记住密码
                    select:""//下拉框
                })
                return{
                    data
                }
            }
        }).mount("#app")
    </script>
</body>

11、v-model修饰符

  • 在失去焦点或按下回车键之后渲染用 v-model.lazy
  • 输入框的值转换为数字类型用 v-model.number
  • 去除首尾空格 v-model.trim

<body>
    <div id="app">
        <h3>{{web.url}}</h3>
        <h3>{{web.user}}</h3>
        实时渲染<input type="text" v-model="web.url"><br>
        在失去焦点或按下回车键之后渲染<input type="text" v-model.lazy="web.url"><br>
        输入框的值转换为数字类型<input type="text" v-model.number="web.user"><br>
        去除首尾空格<input type="text" v-model.trim="web.url">
    </div>
    <script type="module">
        import{createApp,reactive} from './vue.esm-browser.js'
        createApp({
            setup(){
                const web=reactive({
                    url:"baidu.com",
                    user:10
                })
                return{
                    web
                }
            }
        }).mount("#app")
    </script>
</body>

12、渲染数据v-text和v-html

  • v-text将数据解析为纯文本格式
  • v-html将数据解析为html格式
<body>
    <div id="app">
        <h3>{{web.title}}</h3>
        <h3 v-text="web.title"></h3>
        <h3 v-html="web.url"></h3>
        <h3 v-text="web.url"></h3>
    </div>
    <script type="module">
        import{createApp,reactive} from './vue.esm-browser.js'
        createApp({
            setup(){
                const web=reactive({
                    url:"<i style='color:blue;'>baidu.com</i>",
                    title:"javascript"
                })
                return{
                    web
                }
            }
        }).mount("#app")
    </script>
</body>

13、计算属性computed

<body>
    <div id="app">
        <h3>{{add()}}</h3>
        <h3>{{add()}}</h3>
        <!-- sub是属性不是方法 -->
        <h3>{{sub}}</h3>
        <h3>{{sub}}</h3>
        x <input type="text" v-model.number="data.x"><br>
        y <input type="text" v-model.number="data.y">
    </div>
    <script type="module">
        // 导入computed
        import{createApp,reactive,computed} from './vue.esm-browser.js'
        createApp({
            setup(){
                const data=reactive({
                    x:10,
                    y:20
                })
                // 方法:无缓存
                const add=()=>{
                    console.log("add");//打印流程
                    return data.x+data.y;
                }
                // 计算属性-有缓存(计算属性根据其依赖的响应式数据变化而重新计算)
                const sub=computed(()=>{
                    console.log("sub");
                    return data.x-data.y;
                })
                return{
                    data,
                    add,
                    sub
                }
            }
        }).mount("#app")
    </script>
</body>

14、侦听器watch

<body>
    <div id="app">
        爱好
        <select v-model="hobby">
            <option value="">请选择</option>
            <option value="1">写作</option>
            <option value="2">画画</option>
            <option value="3">运动</option>
        </select>
        <hr>
        年
        <select v-model="data.year">
            <option value="">请选择</option>
            <option value="2023">2023</option>
            <option value="2024">2024</option>
            <option value="2025">2025</option>
        </select>
        月
        <select v-model="data.month">
            <option value="">请选择</option>
            <option value="10">10</option>
            <option value="11">11</option>
            <option value="12">12</option>
        </select>
    </div>
    <script type="module">
        // 导入watch
        import{createApp,reactive,ref,watch} from './vue.esm-browser.js'
        createApp({
            setup(){
                const hobby=ref("");//爱好
                const data=reactive({
                    year:"2023",
                    month:"10"
                })
                // 侦听对象hobby
                watch(hobby,(newValue,oldValue)=>{
                    console.log(newValue,oldValue);
                    if(newValue=="2"){
                        console.log("画画");
                    }
                })
                // 监听date
                watch(data,(oldValue,newValue)=>{
                    /*
                    JS中对象和数组是通过引用传递的,而不是通过值传递
                    当修改对象或数组的值时,实际上修改的是对对象或数组的引用,而不是创建一个新的对象或数组
                    所以,如果修改了对象或数组的值,那么打印出来的结果则是修改后的值
                    */
                    console.log(oldValue,newValue);
                    if(newValue.year=="2025"){
                        console.log("2025");
                    }
                })
                // 监听date中的某个属性year
                watch(()=>data.year,(newValue,oldValue)=>{
                    console.log(oldValue,newValue);
                    if(data.year=="2024"){
                        console.log("2024");
                    }
                })
                return{
                    hobby,
                    data
                }
            }
        }).mount("#app")
    </script>
</body>

15、自动侦听器watchEffect

<body>
    <div id="app">
        爱好
        <select v-model="hobby">
            <option value="">请选择</option>
            <option value="1">写作</option>
            <option value="2">画画</option>
            <option value="3">运动</option>
        </select>
        <hr>
        年
        <select v-model="data.year">
            <option value="">请选择</option>
            <option value="2023">2023</option>
            <option value="2024">2024</option>
            <option value="2025">2025</option>
        </select>
        月
        <select v-model="data.month">
            <option value="">请选择</option>
            <option value="10">10</option>
            <option value="11">11</option>
            <option value="12">12</option>
        </select>
    </div>
    <script type="module">
        // 导入watchEffect
        import{createApp,reactive,ref,watchEffect} from './vue.esm-browser.js'
        createApp({
            setup(){
                const hobby=ref("");//爱好
                const data=reactive({
                    year:"2023",
                    month:"10"
                })
                // 自动监听
                watchEffect(()=>{
                    console.log("监听开始");
                    if(hobby.value=="2"){
                        console.log("画画");
                    }
                    if(data.year=="2025"){
                        console.log("2025");
                    }
                    if(data.month=="10"){
                        console.log("10");
                    }
                    console.log("监听结束");
                })
                return{
                    hobby,
                    data
                }
            }
        }).mount("#app")
    </script>
</body>

16、图片轮播案例

<body>
    <div id="app">
        <h3>{{number}}</h3>
        <img :src=`../resource/image/dhimg${number}.png`  style="width: 300px;"><br>
        <button @click="next">下一张</button>
        <button @click="prev">上一张</button>
        <hr>
        <ul>
            <li v-for="value in 4">
                <a href="#" @click="jump(value)">{{value}}</a>
            </li>
        </ul>
    </div>
    <script type="module">
        import{createApp,reactive,ref} from './vue.esm-browser.js'
        createApp({
            setup(){
                const number=ref(2)
                const next=()=>{
                    number.value++;
                    if(number.value=="5"){
                        number.value=1;
                    }
                }
                const prev=()=>{
                    number.value--;
                    if(number.value=="0"){
                        number.value=5;
                    }
                }
                const jump=(value)=>{
                    number.value=value;
                }
                return{
                    number,
                    next,
                    prev,
                    jump
                }
            }
        }).mount("#app")
    </script>
</body>

17、记事本案例

<body>
    <div id="app">
        <input type="text" v-model="data.content">
        <button @click="add">添加</button>
        <ul>
            <li v-for="(value,index) in data.list">
                {{value}}
                <button @click="del(index)">删除</button>
            </li>
        </ul>
        {{data.list.length}}
        <button @click="clear">清空</button>
    </div>
    <script type="module">
        import{createApp,reactive,ref} from './vue.esm-browser.js'
        createApp({
            setup(){
                const data=reactive({
                    content:"baidu.com",
                    list:["sss","yyy"]
                })
                const add=()=>{
                    data.list.push(data.content);
                    console.log(data.list)
                }
                const del=(index)=>{
                    data.list.pop(index);
                }
                const clear=()=>{
                    data.list=[];
                }
                return{
                    data,
                    add,
                    del,
                    clear
                }
            }
        }).mount("#app")
    </script>
</body>

18、购物车案例

<body>
    <div id="app">
        <table>
            <thead>
                <tr>
                    <td><input type="checkbox" v-model="data.selected" @change="selectAll"></td>
                    <td>商品</td>
                    <td>单价</td>
                    <td>库存</td>
                    <td colspan="2">操作</td>
                </tr>
            </thead>
            <tbody>
                <tr v-for="(value,index) in data.list">
                    <td><input type="checkbox" :value="value" v-model="data.checkboxList" @change="changeSelect"></td>
                    <td>{{value.name}}</td>
                    <td>{{value.price}}</td>
                    <td>{{value.stock}}</td>
                    <td>
                        <button @click="sub(value)">-</button>
                        {{value.number}}
                        <button @click="add(value)">+</button>
                    </td>
                    <td><button @click="del(index,value.id)">删除</button></td>
                </tr>
            </tbody>
            <tfoot>
                <tr>
                    <td>总价{{totalPrice()}}</td>
                </tr>
            </tfoot>
        </table>
    </div>
    <script type="module">
        import{createApp,reactive,ref} from './vue.esm-browser.js'
        createApp({
            setup(){
                const data=reactive({
                    selected:false,
                    checkboxList:[],
                    list:[{
                        id:1,
                        name:"铅笔",
                        price:10,
                        number:1,
                        stock:3
                    },
                    {
                        id:2,
                        name:"鼠标",
                        price:20,
                        number:2,
                        stock:5
                    },
                    {
                        id:3,
                        name:"键盘",
                        price:30,
                        number:1,
                        stock:6
                    }],
                })
                const selectAll=()=>{
                    console.log(data.selected);
                    if(data.selected){
                        data.checkboxList=data.list;
                    }else{
                        data.checkboxList=[];
                    }
                }
                const changeSelect=()=>{
                    if(data.checkboxList.length==data.list.length&&data.list.length!=0){
                        data.selected=true;
                    }else{
                        data.selected=false;
                    }
                }
                const totalPrice=()=>{
                    let total=0;
                    for(let i=0;i<data.checkboxList.length;i++){
                        total+=data.checkboxList[i].price*data.checkboxList[i].number;
                    }
                    return total;
                }
                const add=(value)=>{
                    value.number++;
                    if(value.number>=value.stock){
                        value.number=value.stock;
                    }
                }
                const sub=(value)=>{
                    value.number--;
                    if(value.number<=1){
                        value.number=1;
                    }
                }
                const del=(index,id)=>{
                    data.list.splice(index,1);
                    let newArr=data.checkboxList.filter((value,index)=>{
                        return value.id!=id;
                    })
                    data.checkboxList=newArr;
                    changeSelect();
                }
                return{
                    data,
                    selectAll,
                    changeSelect,
                    totalPrice,
                    add,
                    sub,
                    del
                }
            }
        }).mount("#app")
    </script>
</body>

19、购物车案例优化

<body>
    <div id="app">
        <table>
            <thead>
                <tr>
                    <td><input type="checkbox" v-model="data.selected" ></td>
                    <td>商品</td>
                    <td>单价</td>
                    <td>库存</td>
                    <td colspan="2">操作</td>
                </tr>
            </thead>
            <tbody>
                <tr v-for="(value,index) in data.list">
                    <td><input type="checkbox" :value="value" v-model="data.checkboxList" @change="changeSelect"></td>
                    <td>{{value.name}}</td>
                    <td>{{value.price}}</td>
                    <td>{{value.stock}}</td>
                    <td>
                        <button @click="sub(value)">-</button>
                        {{value.number}}
                        <button @click="add(value)">+</button>
                    </td>
                    <td><button @click="del(index,value.id)">删除</button></td>
                </tr>
            </tbody>
            <tfoot>
                <tr>
                    <td>总价{{totalPrice}}</td>
                </tr>
            </tfoot>
        </table>
    </div>
    <script type="module">
        import{createApp,reactive,watch,computed} from './vue.esm-browser.js'
        createApp({
            setup(){
                const data=reactive({
                    selected:false,
                    checkboxList:[],
                    list:[{
                        id:1,
                        name:"铅笔",
                        price:10,
                        number:1,
                        stock:3
                    },
                    {
                        id:2,
                        name:"鼠标",
                        price:20,
                        number:2,
                        stock:5
                    },
                    {
                        id:3,
                        name:"键盘",
                        price:30,
                        number:1,
                        stock:6
                    }],
                })
                let flag=true;
                watch(()=>data.selected,(newValue,oldValue)=>{
                    if(newValue){
                        data.checkboxList=data.list;
                    }else{
                        if(flag){
                            data.checkboxList=[];
                        }
                    }
                })
                watch(()=>data.checkboxList,(newValue,oldValue)=>{
                    if(newValue.length==data.list.length&&data.list.length!=0){
                        data.selected=true;
                    }else{
                        data.selected=false;
                        flag=false;
                    }
                })
                const totalPrice=computed(()=>{
                    /*
                    reduce定义:用于对数组中所有元素进行迭代操作,并将每次操作的结果累加到一个初始值上
                    reduce接收两个参数:一个是累加器函数,另一个是初始值
                    reduce:将data.checkboxList数组中的每个checkbox对象的price和number属性进行相乘,
                    并将结果累加到初始值0上,最后返回累加的结果

                    total(累加器)用于存储每次计算的结果,初始值为0
                    item(当前元素)在每次迭代过程中,当前元素的值会被传递给回调函数
                    */
                    return data.checkboxList.reduce((total,item)=>total+item.price*item.number,0)
                })
                const add=(value)=>{
                    value.number++;
                    if(value.number>=value.stock){
                        value.number=value.stock;
                    }
                }
                const sub=(value)=>{
                    value.number--;
                    if(value.number<=1){
                        value.number=1;
                    }
                }
                const del=(index,id)=>{
                    data.list.splice(index,1);
                    let newArr=data.checkboxList.filter((value,index)=>{
                        return value.id!=id;
                    })
                    data.checkboxList=newArr;
                }
                return{
                    data,
                    totalPrice,
                    add,
                    sub,
                    del
                }
            }
        }).mount("#app")
    </script>
</body>

Vite

1、基于Vite创建Vue3项目

  • 在指定目录下打开cmd执行命令 npm create vite@latest

  • 打开src文件夹删除style.css文件和HelloWorld.vue文件
  • 打开main.js文件删除  import './style.css'
  • 打开App.vue文件删除 import HelloWorld from './components/HelloWorld.vue' 和 默认样式

2、导入组件

<script setup>
  //导入子组件
  //App.vue是父组件,因为它包含了header.vue和footer.vue两个子组件
  import Header from "./components/header.vue"
  import Footer from "./components/footer.vue"
</script>

<template>
  <Header/>

  
  <Footer/>
</template>

<style scoped>

</style>

3、父传子defineProps

/*App.vue文件*/
<script setup>
    import { reactive } from 'vue';
    //导入子组件
    //App.vue是父组件,因为它包含了header.vue和footer.vue两个子组件
    import Header from './components/header.vue';
    import Footer from './components/footer.vue';
    // const propsweb = {
    //   user:10,
    //   url:"ww.baidu.com"
    // }
    const propsweb = reactive({
      user:10,
      url:"www.baidu.com"
    })
    const userAdd=()=>{
      propsweb.user++;
      console.log(propsweb.user);
    }
</script>

<template>
  <!-- 父传子 - 方式1 -->
  <Header propsname="孙悟空" propsurl="baidu.com" />

  <button @click="userAdd">添加用户</button>

  <!-- 父传子 - 方式2 -->
  <!-- <Footer v-bind="propsweb"/> -->
  <!-- v-bind简写 -->
  <Footer :="propsweb"/>
</template>

<style scoped>

</style>

/*header.vue文件*/
<script setup>
    //接收方式:数组
    const props = defineProps(["propsname","propsurl"])
    console.log(props);
</script>

<template>
    <h3>header</h3>
</template>

<style scoped>

</style>

/*footer.vue文件*/
<script setup>
    //接收方式:对象
    const props=defineProps({
        user:Number,
        url:{
            type:String,
            required:false,//true表示必传属性,若未传则会提示警告信息
            default:"baidu.com"//未传默认值
        }
    })
    console.log(props)
</script>

<template>
    <h3>footer</h3> {{ props.user }}
</template>

<style scoped>

</style>

4、子传父defineEmits

/*App.vue文件*/
<script setup>
    import{reactive,ref} from 'vue'
    import Header from './components/header.vue'

    // 响应式数据
    const web = reactive({
      name:"孙悟空",
      url:"baidu.com"
    })
    const user = ref(0)
    const emitsGetWeb=(data)=>{
      console.log(data)
      web.url=data.url;
    }
    const emitsUserAdd=(data)=>{
      console.log(data);
      user.value+=data;
    }
</script>

<template>
    <Header @getweb="emitsGetWeb" @userAdd="emitsUserAdd"/>
    {{ web.url }} - {{ user }}
</template>

<style scoped>

</style>
/*header.vue文件*/
<script setup>
    const emits = defineEmits(["getweb","userAdd"])
    emits("getweb",{name:"黑神话",url:"www.baidu.com"})
    const add=()=>{
        emits("userAdd",10)
    }
</script>

<template>
    <h3>header</h3>
    <button @click="add">添加用户</button>
</template>

<style scoped>

</style>

5、跨组件通信-依赖注入

/*App.vue文件*/
<script setup>
    import{ref,provide,reactive} from 'vue'
    // 导入子组件
    import Header from './components/header.vue'

    // 响应式数据
    const web = reactive({
      name:"孙悟空",
      url:"baidu.com"
    })
    //provide用于父组件将数据提供给所有子组件
    /*
      若使用了provide和inject来进行数据传递,
      则一般不需要再使用defineProps
    */
    provide("provideWeb",web)

    const user = ref(0)
    provide("provideUser",user)

    const userAdd=()=>{
      user.value++;
    }
    //用于父组件将函数提供给所有子组件
    provide("provideFuncUserAdd",userAdd)
</script>

<template>
    <h3>App.vue-Top组件</h3>
    user:{{ user }}
    <!-- 子组件 -->
    <Header/>
</template>

<style scoped>

</style>

/*header.vue文件*/
<script setup>
    // 导入子组件
    import Footer from "./footer.vue"
    import {inject} from 'vue'
    //子组件通过inject注入父组件提供的响应式数据
    const user = inject("provideUser")
    console.log("provideUser",user)
</script>

<template>
    <h3>header.vue-Middle组件</h3>
    <!-- 子组件 -->
    <Footer/>
</template>

<style scoped>

</style>

/*footer.vue文件*/
<script setup>
    import { inject } from 'vue';
    //子组件通过inject注入父组件提供的响应式数据
    const web=inject("provideWeb");
    console.log("provideWeb",web);
    //子组件通过inject注入父组件提供的响应式数据
    const FuncUserAdd = inject("provideFuncUserAdd")
    console.log(FuncUserAdd)
</script>

<template>
    <h3>footer.vue-Bottom组件</h3> 
    <button @click="FuncUserAdd">添加用户</button>
</template>

<style scoped>

</style>

6、匿名插槽和具体插槽v-slot

  • 插槽是指可以在父组件内自定义模板片段,在子组件中可以将定义的模板片段插入到子组件的特定位置。

/*App.vue文件*/
<script setup>
    // 导入子组件
    import Header from './components/header.vue';
    import Footer from './components/footer.vue';
</script>

<template>
    <h3>App.vue</h3>
    <Header>
        <a href="baidu.com">百度</a>
    </Header>
    <Footer>
          <!-- <template v-slot:url> -->
          <!-- v-slot简写形式 -->
          <template #url>
            <a href="www.baidu.com">网址</a>
          </template>
    </Footer>
</template>

<style scoped>

</style>



/*header.vue文件*/
<script setup>
    
</script>

<template>
    <h3>header.vue子组件</h3>
    <!-- 匿名插槽 -->
    <slot/>
</template>

<style scoped>

</style>


/*footer.vue文件*/
<script setup>
    
</script>

<template>
    <h3>footer.vue子组件</h3> 
    <!-- 具名插槽 -->
    <slot name="url"/>
</template>

<style scoped>

</style>

7、作用域插槽

  • 作用域插槽:子组件向父组件传递数据,并在父组件定义的模板中渲染

/*App.vue文件*/
<script setup>
    // 导入子组件
    import Header from './components/header.vue';
    import Footer from './components/footer.vue';
</script>

<template>
    <h3>App.vue</h3>
    <Header>
        <a href="baidu.com">百度</a>
    </Header>
    <Footer>
          <!-- <template v-slot:url> -->
          <!-- 作用域插槽 -->
          <template #url="data">

            <!-- 解构形式 -->
            <!-- <template #url="{title,user}"> -->

            <!-- data用于接收数据 -->
            {{ data.title }}
            {{ data.user }}
            <a href="www.baidu.com">网址</a>
          </template>
    </Footer>
</template>

<style scoped>

</style>


/*footer.vue文件*/
<script setup>
    
</script>

<template>
    <h3>footer.vue子组件</h3> 
    <!-- 具名插槽 -->
    <slot name="url" title="摆渡" user="1000"/>
</template>

<style scoped>

</style>

8、生命周期函数

生命周期函数是组件实例从创建到销毁过程中不同时间点自动调用的函数。

1、挂载阶段:

  •  onBeforeMount:在组件实例即将被挂载到DOM之前调用,此时模板还未编译或渲染到DOM,通常用于执行初始化操作,如:获取异步数据、设置初始属性值等。
  • onMounted:在组件成功挂载到DOM并完成首次渲染后调用,此时可以访问和操作DOM元素,并执行与页面交互相关的逻辑。

2、更新阶段:

  • onBeforeUpdate (由于响应式数据变化):在组件更新之前在重新渲染时之前调用,可以根据新的参数判断是否需要进行特殊处理,甚至可以选择阻止此次更新过程。
  • onUpdated:在组件完成更新并重新渲染后调用,可以基于新的渲染结果处理更新后的数据。

3、卸载阶段:

  • onBeforeUnmount:在组件从DOM中销毁之前调用,用于释放资源,如:清理计时器、解绑事件监听器等。
  • onUnmounted:在组件已经从DOM中移除并销毁后调用,确保组件所占用的所有资源都被正确释放。

4、错误处理:

  • onErrorCaptured:在捕获到组件中的错误时调用,用于处理错误,如:记录错误日志等。
<script setup>
    import { onMounted,onUpdated,ref} from 'vue';
    // 在组件成功挂载到DOM并完成首次渲染后调用
    onMounted(()=>{
      console.log("onMounted")
    })
    // 组件更新后调用
    onUpdated(()=>{
      console.log("onUpdated")
    })
    const user = ref(0)
    console.log(user.value)
</script>

<template>
    {{ user }}
    <button @click="user++">添加用户</button>
</template>

<style scoped>

</style>

9、toRef和toRefs

  • toRefs将一个响应式对象的所有属性转换为ref对象
  • toRef将一个响应式对象的某个属性转换为ref变量
<script setup>
    import {reactive,toRefs,toRef} from 'vue';
    let web=reactive({
      name:"黑神话",
      url:"baidu.com"
    })
    // let{name,url}=toRefs(web);
    let url=toRef(web,"url")
    console.log(url)
</script>

<template>
    {{ url }}
</template>

<style scoped>

</style>

Pinia

1、Pinia简介

  • Pinia是一个轻量级的状态管理库,状态管理库是用于管理应用程序全局状态的工具。
  • Pinia可以处理大型项目中复杂的状态管理需求,而父传子、子传父以及跨组件通信,可以解决一些简单的状态传递问题,更适合小型项目。
  • 对于复杂的状态管理需求,使用Pinia是更好的选择,而对于简单的状态管理需求,使用localStorage是更简单的解决方案。

  • 以登录为例:使用Pinia创建一个userStore来集中管理用户的登录状态和过期时间。
    • 当用户登录成功时:设置userStore中用户的登录状态为已登录,并设置过期时间。
    • 当用户退出登录时:修改userStore中用户的登录状态为未登录,并删除过期时间。

2、安装Pinia以及定义和使用Store

  • 在终端中输入命令安装npm install pinia
//main.js文件

import { createApp } from 'vue'
//导入Pinia的createPinia方法,用于创建Pinia实例(状态管理库)
import {createPinia} from 'pinia'
import App from './App.vue'
//创建一个Pinia实例,用于在应用中集中管理状态(store)
const pinia = createPinia()
// createApp(App).mount('#app')
const app = createApp(App)
app.use(pinia)//将Pinia实例注册到Vue应用中
app.mount("#app")

//web.js文件

// 定义仓库
import { defineStore } from "pinia";
import { reactive,ref } from "vue";
//定义一个基于Pinia的Store
 export const useWebStore = defineStore('web',()=>{
    const web=reactive({
        title:"仓库管理",
        url:"baidu.com"
    })
    const users=ref(1000)
    const userAdd=()=>{
        users.value++;
    }
    return{
        web,
        users,
        userAdd
    }
})

//App.vue文件
<script setup>
    import {useWebStore} from './stores/web.js'
    const webStore =useWebStore()
    console.log(webStore.web)
    console.log(webStore.users)
</script>

<template>
    {{ webStore.web.url }}
    {{ webStore.users }}
    <button @click="webStore.userAdd">添加用户</button>
</template>

<style scoped>

</style>

3、Pinia持久化存储插件

1、安装npm i pinia-plugin-persistedstate

2、将插件添加到 pinia 实例上

import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'

const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)

3、创建 Store 时,将 persist 选项设置为 true

//组合式语法
import { defineStore } from 'pinia'
import { ref } from 'vue'

export const useStore = defineStore(
  'main',
  () => {
    const someState = ref('你好 pinia')
    return { someState }
  },
  {
    persist: true,
  },
)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2081604.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【使用 Python 进行图像裁剪的多种方法】

以下为您介绍使用 Python 进行图像裁剪的多种方法及代码示例&#xff1a; 使用 PIL 库&#xff08;Pillow&#xff09;&#xff1a; Pillow 是 Python 中一个强大的图像处理库&#xff0c;其截图功能不仅可以获取屏幕截图&#xff0c;还能对截图进行丰富的图像处理操作。例如&…

PD取电协议芯片 XSP08Q集成全协议芯片

1&#xff1a;Type-C接口应用很广泛&#xff0c;几乎可以覆盖各行各业&#xff0c;例如快充领域&#xff0c;多种快充协议都可以在Type-C接口上实现&#xff0c;在用电端&#xff0c;只需要使用XSP08取电协议控制芯片&#xff0c;即可获取各种快充电压&#xff0c;例如&#xf…

以某团为案例,30分钟讲清商业模式画布该如何做!

在进行商业模式分析时&#xff0c;即时白板内置的商业模式画布模板显然是一种极其有效的工具。该模板将复杂的商业逻辑分解为明确的要素&#xff0c;使得分析过程更具条理性和方向性&#xff0c;便于深刻理解和呈现商业模式。 以下以某团为例&#xff0c;详细解析其商业逻辑&a…

Django REST Framework(十九)权限

Django REST framework (DRF) 的权限认证涉及以下几个方面&#xff1a;全局权限配置、局部权限配置、自定义权限类、以及自定义认证类。以下是关于这些方面的详细说明&#xff1a; 1. 全局权限配置 在 Django 项目的配置文件 settings.py 中&#xff0c;可以全局配置 DRF 的权…

警惕!血脂偏高,这些身体信号你不可不知!

在快节奏的现代生活中&#xff0c;高血脂&#xff0c;这个看似“沉默的杀手”&#xff0c;正悄然威胁着越来越多人的健康。它不像感冒发烧那样有明显的症状&#xff0c;却能在不知不觉中侵蚀血管&#xff0c;增加心血管疾病的风险。今天&#xff0c;我们就来揭开高血脂的神秘面…

第四届中国RPA+AI开发者大赛火热报名中!

创新未来 第四届中国RPAAI开发者大赛 报名正式启动 数字化转型的加速推进为RPA技术带来了前所未有的发展机遇。AI技术的飞速进步&#xff0c;特别是在机器学习、自然语言处理和计算机视觉等领域的显著进展&#xff0c;已经大幅度扩展了RPA的应用范围。 据IDC研究报告预测&am…

windows共享文件给单个用户方法操作说明

如下图&#xff0c;我们想给学习视频这个文件夹共享出去&#xff0c;但是不想每个用户&#xff08;Everyone&#xff09;都可以访问&#xff0c;只允许本地账户ZZ可以访问&#xff0c;该如何操作呢&#xff1f;请见下面的内容。 右键这个文件夹&#xff0c;点击属性 点击图下所…

本地运行 AI 有多慢 ? 大模型推理测速 (llama.cpp, Intel GPU A770)

上文说到, 天下苦 N 卡久矣, 直接使用 CPU 推理又太慢. 那么, 在没有 N 卡的情况下, 本地运行 AI (神经网络) 大模型, 能够达到怎样的速度 ? 同志们好, 欢迎来到 胖喵穷人实验室 ! 这里专注于 低成本, 低难度, 低风险 的 “三低” 小实验. 胖喵穷人实验室 (PM-PLab-E)正式名称…

如何在算家云搭建模型Linly-Dubbing(语音识别)

一、模型介绍 Linly-Dubbing 是一个智能视频多语言 AI 配音和翻译工具&#xff0c;它融合了 YouDub-webui 的灵感&#xff0c;并在此基础上进行了拓展和优化。 该模型致力于提供更加多样化和高质量的配音选择&#xff0c;通过集成Linly-Talker的数字人对口型技术&#xff0c;…

零基础入门转录组数据分析——预后模型之多因素cox模型

零基础入门转录组数据分析——预后模型之多因素cox模型 目录 零基础入门转录组数据分析——预后模型之多因素cox模型1. 预后模型和多因素cox模型基础知识2. 多因素cox预后模型&#xff08;Rstudio&#xff09;——代码实操2. 1 数据处理2. 2 构建多因素cox模型&#xff08;用输…

有色冶炼行业中的智能电动机保护器

低压电动机作为有色冶炼企业底层大量使用的设备&#xff0c;其异常运行不仅影响冶炼厂的正常生产&#xff0c;还会 威胁到人的生命安全&#xff0c;因此为电动机设置合适而又全面的保护至关重要。智能电动机保护器集保护、 遥测、通信、遥控、显示等功能于一体&#xff0c;是目…

基于大数据的水资源管理与调度优化研究【Web可视化、灰色预测、大屏设计】

需要本项目的私信博主 目录 1 引言 1.1 研究背景 1.2 国内外研究现状 1.3 研究目的 1.4 研究意义 2 关键技术理论介绍 2.1 Python语言 2.2 pandas 2.3 pyecharts 2.4 灰色预测 3 数据来源及处理 3.1 数据来源 3.2 数据处理 4 数据可视化分析及大屏设计 4.1 年度…

Windows下安装Kafka3

参考文章&#xff1a;Windows下安装Kafka3_kafka3 window-CSDN博客 安装配置Kafka 首先在官网 Apache Kafka 下载Kafka二进制压缩包。无论是在CentOS还是在Windows下都是下载该压缩包&#xff0c;里面已经包含了Kafka Linux和windows平台下的可执行文件了。选择目前比较新的3…

解决 JS WebSocket 心跳检测 重连

解决 JS WebSocket 心跳检测 重连 文章目录 解决 JS WebSocket 心跳检测 重连一、WebSocket 心跳检测的作用二、心跳检测的处理方案1. 创建 WebSocket 连接2. 心跳参数设置3. 心跳检测逻辑4. 心跳包响应处理5. 断线重连机制 三、总结 一、WebSocket 心跳检测的作用 WebSocket 是…

计量校准企业的生产制造,具备什么实际的作用?

计量校准行业已经发展了几十年&#xff0c;从建国后成立的计量所&#xff0c;建立了计量规范&#xff0c;到如今百花齐放&#xff0c;各类机构不断涌出&#xff0c;可供企业选择的计量机构可谓是越来越多&#xff0c;那么实际意义上&#xff0c;计量校准企业的生产制造&#xf…

草莓成熟度检测检测系统源码分享 # [一条龙教学YOLOV8标注好的数据集一键训练_70+全套改进创新点发刊_Web前端展示]

草莓成熟度检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer V…

【ragflow】安装2:源码安装依赖

中文文档【ragflow】安装1: docker:失败官方说的成功 docker 安装的启动失败 重新来一遍,不会重新拉取: root@k8s-master-pfsrv:/home/zhangbin/perfwork/rag# cd ragflow/ root@k8s-master-pfsrv:/home/

基于数字孪生智慧机场建设方案(53页PPT)

方案介绍&#xff1a; 数字孪生技术是一种通过数字化方式创建物理实体的虚拟模型&#xff0c;并借助历史数据、实时数据以及算法模型&#xff0c;模拟、验证、预测、控制物理实体过程的技术手段。在智慧机场建设中&#xff0c;该技术通过构建机场的虚拟镜像&#xff0c;实现机…

软件设计师全套备考系列文章15 -- 数据库:规范化、控制功能、大数据

软考-- 软件设计师&#xff08;15&#xff09;-- 数据库&#xff1a;规范化、控制功能、大数据 文章目录 软考-- 软件设计师&#xff08;15&#xff09;-- 数据库&#xff1a;规范化、控制功能、大数据前言一、章节考点二、规范化三、数据库的控制功能四、大数据、数据仓库 前言…

深度解析HarmonyOS SDK实况窗服务源码,Get不同场景下的多种模板

HarmonyOS SDK实况窗服务&#xff08;Live View Kit&#xff09;作为一个实时呈现应用服务信息变化的小窗口&#xff0c;遍布于设备的各个使用界面&#xff0c;它的魅力在于将复杂的应用场景信息简洁提炼并实时刷新&#xff0c;在不影响当前其他应用操作的情况下&#xff0c;时…