尚硅谷vue全家桶(上)

news2024/10/6 6:02:28

vue2

  • 简介
    • 第一天
      • 第二天
  • 第三天
    • 第四天
      • 第五天
  • 第六天
    • 第七天
      • 第八天
  • 第九天

网课链接(半个月拿下)

简介

在这里插入图片描述
需要提前会的东西
在这里插入图片描述
中文文档链接点下面
vue.js
要会查文档用API

第一天

清除提示1
再文档中下载开发版本+浏览器安装vue devtools插件
打开允许访问URL

在这里插入图片描述
在这里插入图片描述
浏览器链接位置

……///……
这个直接在浏览器中安装的拓展在后续学习中时不时出现问题,建议直接从网盘下载工具
网盘链接如下

链接: https://pan.baidu.com/s/1ev2zbUIghU_Eo264_ArPWw?pwd=4dzp 提取码: 4dzp 复制这段内容后打开百度网盘手机App,操作更方便哦

……///……

清除提示2
直接写入下面代码,如果没有清除直接回vue.js文档改为txt格式用快捷键ctrl f 查找productionTip,把true改为false,再把文件后缀改回去

<script type="text/javascript">
        Vue.config.productionTip = false //以阻止 vue 在启动时生成生产提示。
    </script>

hello小案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script type="text/javascript" src="vue.js"></script>
</head>
<body>
    <!-- 准备好一个容器 -->
    <div id="root">
        <h1>hello,{{name}}</h1>
    </div>

    <script type="text/javascript">
        Vue.config.productionTip = false //以阻止 vue 在启动时生成生产提示。

        //创建vue实例
        const x = new Vue({
            el:'#root',  //el用于指定当前vue实例为哪个容器服务
            data:{       //data用于存储数据数据供el所指定容器使用
                name:'你好'
            }
        })
    </script>
</body>
</html>

分析

<body>
    <!-- 准备好一个容器 -->
    <div id="root">
        <h1>hello,{{name.toUpperCase()}},{{address}}</h1>
    </div>

    <script type="text/javascript">
        Vue.config.productionTip = false //以阻止 vue 在启动时生成生产提示。

        //创建vue实例
        const x = new Vue({
            el:'#root',  //el用于指定当前vue实例为哪个容器服务
            data:{       //data用于存储数据数据供el所指定容器使用
                name:'你好',
                address:'长沙'
            }
        })
    </script>
</body>

在这里插入图片描述

第二天

模板语法
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script type="text/javascript" src="vue.js"></script>
</head>
<body>
    <!-- 准备好一个容器 -->
    <div id="root">
        <h1>插值语法</h1>
        <h3>你好,{{name}}</h3>
        <hr/>
        <h1>指令语法</h1>
        <a v-bind:href="school.url.toUpperCase()" x="hello">点我学习vue{{school.name}}</a>
        <a :href="school.url" x="hello">快去学习{{school.name}}</a>
    </div>
</body>

    <script type="text/javascript">
        Vue.config.productionTip = false //以阻止 vue 在启动时生成生产提示。

        new Vue({
            el:'#root',
            data:{
                name:'jack',
                school:{
                    name:'哈哈',
                    url:'http://www.atguigu.com'
                }
          }
        })
        
    </script>

</html>

数据绑定
在这里插入图片描述

<body>
    <!-- 准备好一个容器 -->
    <div id="root">
    <!-- 简写 -->
    单向数据绑定:<input type="text" :value="name"><br/>
    双向数据绑定:<input type="text" v-model="name"><br/>
    </div>
</body>
    <script type="text/javascript">
        Vue.config.productionTip = false //以阻止 vue 在启动时生成生产提示。

        new Vue({
            el:'#root',  //el用于指定当前vue实例为哪个容器服务
            data:{       //data用于存储数据数据供el所指定容器使用
                name:'你好'
            }
        })
    </script>

el与data的两种写法
学到组件data必须使用函数式
在这里插入图片描述

<body>
  
    <div id="root">
        <h1>你好,{{name}}</h1>
    </div>
</body>
    <script type="text/javascript">
        Vue.config.productionTip = false //以阻止 vue 在启动时生成生产提示。

        //el两种写法
        /* 第一种
         new Vue({
            el:'#root',  //el用于指定当前vue实例为哪个容器服务
            data:{       //data用于存储数据数据供el所指定容器使用
                name:'你好'
            }
        }) */
        /* 第二种
        const v = new Vue({
            data:{
                name:'哈哈'
            }
        })
        console.log(v)
        v.$mount('#root') //挂载 */


        //data两种写法
        new Vue({
            el:'#root',
            //第一种写法,对象式
            /* data:{       //data用于存储数据数据供el所指定容器使用
                name:'你好'
            } */

            //第二种,函数式
            data:function(){
                return{
                    name:'哈哈'
                }
            }
        })
    </script>

第三天

object.defineProperty方法

    <script type="text/javascript">
        let number = 18
        let person = {
            name:'张三',
            sex:'男',

        }
        Object.defineProperty(person,'age',{
          /*   value:18,
            enumerable:true, //控制属性是否可以枚举
            writable:true,  //控制属性是否可以被修改
            configurable:true  //控制属性是否可以被删除
     */    
            get(){
                console.log('有人读取了age属性了')
                return number
            },
            set(value){
                console.log('有人修改了age属性,且值是',value)
                number = value
            }
    })
    </script>

数据代理


    <script type="text/javascript">
        let obj = {x:100}
        let obj2 = {y:200}

        Object.defineProperty(obj2,'x',{
            get(){
                return obj.x
            },
            set(value){
                obj.x = value
            }
        })
    </script>

vue中的数据代理


<div id="root">
    <h2>学校名称:{{name}}</h2>
    <h2>学校地址:{{address}}</h2>
</div>
</body>

<script type="text/javascript">
Vue.config.productionTip = false
const vm = new Vue({
    el:'#root',
    data:{
        name:'尚硅谷',
        address:'长沙',
    }
})
</script>

事件处理


<div id="root">
    <h2>欢迎来到{{name}}学习</h2>
    <button v-on:click="showInfo">点我提示信息</button>
</div>
</body>

<script type="text/javascript">
    Vue.config.productionTip = false

    const vm = new Vue({
        el:'#root',
        data:{
            name:'尚硅谷'
        },
        methods: {
            showInfo(event){
                // console.log(this)//此处this是vm
                alert('同学你好')
            }
        },
    })
</script>
<div id="root">
    <h2>欢迎来到{{name}}学习</h2>
    <!-- <button v-on:click="showInfo">点我提示信息</button> -->
    <button @click="showInfo1">点我提示信息1</button>
    <button @click="showInfo2(66,$event)">点我提示信息2(传参)</button>
</div>
</body>

<script type="text/javascript">
    Vue.config.productionTip = false

    const vm = new Vue({
        el:'#root',
        data:{
            name:'尚硅谷'
        },
        methods: {
            showInfo1(event){
                // console.log(this)//此处this是vm
                alert('同学你好')
            },
            showInfo2(number,a){
                console.log(number,a)
            }
        }
    })
</script>

事件修饰符
在这里插入图片描述


<div id="root">
    <h2>欢迎来到{{name}}学习</h2>
    <a href="http://www/atguigu.com" @click.prevent="shoowInfo">点我提示信息</a>
    <!-- 阻止事件冒泡 -->
    <div class="demo1" @click="showInfo">
        <button @click.stop="showInfo">点我提示信息</button>
    </div>
</div>
</body>

<script type="text/javascript">
    new Vue({
        el:'#root',
        data:{
            name:'尚硅谷'
        },
        methods: {
            showInfo(e){
                e.stopPropagation()
                alert('同学你好!')
            }
        },
    })
</script>

键盘事件
在这里插入图片描述

<div id="root">
        <h2>欢迎来到{{name}}学习</h2>
        <input type="text" placeholder="按下回车提示输入" @keyup.caps-lock="showInfo">
    </div>
</body>

<script type="text/javascript">
    Vue.config.productionTip = false

    new Vue({
        el:'#root',
        data:{
            name:'尚硅谷'
        },
        methods: {
            showInfo(e){
                console.log(e.target.value)
            }
        },
    })
</script>

计算属性

<!-- 准备好一个容器 -->
<div id="root">
    : <input type="text" v-model="firstName"><br><br>
    : <input type="text" v-model="lastName"><br><br>
    <!-- 拼接姓名实现"张-三"联动 -->
    <!-- 第一种实现:使用插值语法(字符串的slice方法,左闭右开截取字符串) ,麻烦-->
    姓名: <span>{{firstName.slice(0,3)}}-{{lastName}}</span><br><br>


    <!-- 第二种实现:使用methods,每次用到都会调用一次,而计算属性只调用第一次就欧了-->
    姓名: <span>{{fullName()}}</span><br><br>
    姓名: <span>{{fullName()}}</span><br><br>
    姓名: <span>{{fullName()}}</span><br><br>
    姓名: <span>{{fullName()}}</span><br><br>
    姓名: <span>{{fullName()}}</span>
</div>

<script>
    const vm = new Vue({
        el: '#root',
        data: {
            firstName: '张',
            lastName: '三'
        },
        methods: {
            fullName() {
                console.log('调用')
                return this.firstName + '-' + this.lastName;
            }
        }
    })
</script>

<!-- 准备好一个容器 -->
<div id="root">
    : <input type="text" v-model="firstName"><br><br>
    : <input type="text" v-model="lastName"><br><br>
    <!-- 拼接姓名实现"张-三"联动 -->

    <!-- 使用计算属性,只调用一次,非常奈斯,节省内存 -->
    姓名: <span>{{fullName}}</span><br><br>
    姓名: <span>{{fullName}}</span><br><br>
    姓名: <span>{{fullName}}</span><br><br>
    姓名: <span>{{fullName}}</span><br><br>
    姓名: <span>{{fullName}}</span><br><br>
    姓名: <span>{{fullName}}</span>
</div>

<script>
    const vm = new Vue({
        el: '#root',
        data: {
            firstName: '张',
            lastName: '三'
        },
        computed: {
            //计算属性里面的属性要写成对象的形式,每个对象里面都有getter和setter
            //这个fullName实际上就是firstName和lastName经过一番计算得到的玩意儿,直接给到vm身上
            fullName: {
                //get有什么用?当有人读取fullName时,get调用,返回值作为fullName的值
                //get什么时候调用? 1.初次读取fullName  2.get里用到的数据发生了改变
                get() {
                    console.log('fullName被读了');
                    // console.log(this);//此处的this是vm
                    return this.firstName + '-' + this.lastName;
                },

                //set什么时候调用? fullName被手动修改时调用
                //这里边呢有个连锁反应,我手动修改vm.fullName导致firstName和lastName被修改,Vue模板重新解析
                //页面刷新,firstName和lastName的修改又导致get被重新执行(依赖的数据变了),返回新的fullName
                //计算属性计算属性,就是一直在计算,所以要想改fullName,必须改它依赖的值
                set(val) {
                    let arr = val.split('-');
                    this.firstName = arr[0]; 
                    this.lastName = arr[1];
                }
            }
        }
    })
</script>

简写
只考虑读取不考虑修改时可使用

<!-- 准备好一个容器 -->
<div id="root">
    : <input type="text" v-model="firstName"><br><br>
    : <input type="text" v-model="lastName"><br><br>
    <!-- 拼接姓名实现"张-三"联动 -->

    <!-- 使用计算属性,只调用一次,非常奈斯,节省内存 -->
    姓名: <span>{{fullName}}</span>
</div>

<script>
    const vm = new Vue({
        el: '#root',
        data: {
            firstName: '张',
            lastName: '三'
        },
        computed: {
            fullName() {
                console.log('fullName被读了');
                return this.firstName + '-' + this.lastName;
            }

        }
    })
</script>

天气案例

<div id="root">
    <!-- 实现点击按钮切换天气 -->
    <!-- 写法1:利用插值语法和三元表达式 -->
    <h2>今天天气很{{isHot ? '炎热': '寒冷'}}</h2>

    <!-- 写法2:利用计算属性 -->
    <h2>今天天气很{{info}}</h2>
    <!--    绑定事件的时候:@xxx="yyy" yyy可以写一些简单的语句,但是最好别这么干-->
    <!--    <button @click="isHot = !isHot">切换天气</button>-->
    <button @click='change'>点击切换天气</button>
</div>
<script>
    new Vue({
        el: '#root',
        data: {
            isHot: true
        },
        methods: {
            change() {
                this.isHot = !this.isHot;
            }
        },
        computed: {
            info() {
                //注意这里的isHot要加this
                return this.isHot ? '炎热' : '寒冷';
            }
        },
    })  
</script>

监视属性

<div id="root">
    <!-- 实现点击按钮切换天气 -->
    <!-- 写法1:利用插值语法和三元表达式 -->
    <h2>今天天气很{{isHot ? '炎热': '寒冷'}}</h2>

    <!-- 写法2:利用计算属性 -->
    <h2>今天天气很{{info}}</h2>
    <!--    绑定事件的时候:@xxx="yyy" yyy可以写一些简单的语句,但是最好别这么干-->
    <!--    <button @click="isHot = !isHot">切换天气</button>-->
    <button @click='change'>点击切换天气</button>
</div>
<script>
    new Vue({
        el: '#root',
        data: {
            isHot: true
        },
        methods: {
            change() {
                this.isHot = !this.isHot;
            }
        },
        computed: {
            info() {
                //注意这里的isHot要加this
                return this.isHot ? '炎热' : '寒冷';
            }
        },
        watch: {
            isHot: {
                immediate: true,   //初始化时先调用一次handler 
                //当isHot被修改时调用handler函数
                handler(newVal, oldVal) {
                    console.log('isHot被修改了', '改之前是' + oldVal, '改之后是' + newVal);
                }
            },
            //watch不只可以监视data中的属性,还可以监视计算属性
            info: {
                immediate: true,   //初始化时先调用一次handler 
                //当isHot被修改时调用handler函数
                handler(newVal, oldVal) {
                    console.log('info被修改了', '改之前是' + oldVal, '改之后是' + newVal);
                }
            }
        }
    })  
</script>

通过vm.$watch监视

const vm = new Vue({
    el: '#root',
    data: {
        isHot: true
    },
    methods: {
        change() {
            this.isHot = !this.isHot;
        }
    },
    computed: {
        info() {
            //注意这里的isHot要加this
            return this.isHot ? '炎热' : '寒冷';
        }
    }
})

	vm.$watch('isHot', {
	    immediate: true,   //初始化时先调用一次handler 
	    //当isHot被修改时调用handler函数
	    handler(newVal, oldVal) {
	        console.log('isHot被修改了', '改之前是' + oldVal, '改之后是' + newVal);
	    }
	})
	
	vm.$watch('info', {
	    immediate: true,   //初始化时先调用一次handler 
	    //当isHot被修改时调用handler函数
	    handler(newVal, oldVal) {
	        console.log('info被修改了', '改之前是' + oldVal, '改之后是' + newVal);
	    }
	})

深度监视

   <!-- 准备一个容器 -->
    <div id="root">
        <h3>a的值是:{{numbers.a}}</h3>
        <button @click="numbers.a++">点我实现a+1</button>
        <h3>b的值是:{{numbers.b}}</h3>
        <button @click="numbers.b++">点我实现b+1</button>
        <h3>我tm就非要强制让number变</h3>
        <button @click="numbers = {a:666, b:999}">点我改变numbers</button>
    </div>
    <script>
        const vm = new Vue({
            el: '#root',
            data: {
                isHot: true,
                numbers: {
                    a: 1,
                    b: 2
                }
            },
            watch: {
                //监视多级结构中某个属性的变化,使用引号包起来(之前不加引号都是简写形式)
                'numbers.a': {
                    handler() {
                        console.log('a被改变了');
                    }
                },
                //如果下面这么写,即使ab变了也不会执行handler,因为这么写意思是监视numbers这个属性
                //而这个属性值是一个对象,只要numbers对象的地址不变就不变,除非像上面div写的暴力方法
                 numbers: {
                     handler() {
                         console.log('numbers改变了');
                     }
                 },

                //但是如果加个deep,就可以监视多级结构中某个属性的变化,ab变了numbers也变
                numbers: {
                    deep: true,
                    handler() {
                        console.log('numbers改变了');
                    }
                },
            }
        })
    </script>

简写

	//复杂形式
	vm.$watch('isHot', {
	    //当isHot被修改时调用handler函数
	    handler(newVal, oldVal) {
	        console.log('isHot被修改了', '改之前是' + oldVal, '改之后是' + newVal);
	    }
	})
	//简写形式
	vm.$watch('isHot',function (newVaule,oldVaule) {
	        console.log(newVaule,oldVaule);
	    })

计算属性对比监视属性
计算

const vm = new Vue({
    el: '#root',
    data: {
        firstName: '张',
        lastName: '三'
    },
    computed: {
        fullName() {
            console.log('fullName被读了');
            return this.firstName + '-' + this.lastName;
        }

    }
})

监视

   const vm = new Vue({
        el: '#root',
        data: {
            firstName: '张',
            lastName: '三',
            fullName: '张-三'
        },
        watch: {
            firstName: {
                handler(newVal, oldVal) {
                    this.fullName = newVal + '-' + this.lastName;
                }
            },
            lastName: {
                handler(newVal, oldVal) {
                    this.fullName = this.firstName + '-' + newVal;
                }
            },
        }
    })

computed能完成的功能,watch都可以完成

第四天

绑定class样式

<div id="root">
    <!--   1. 绑定class样式--字符串写法,适用于样式的类名不确定,需要动态指定-->
    <div class="basic" :class="mood" @click="changeMood">{{name}}</div>

    <!--   2. 绑定class样式--数组写法,适用于要绑定的样式个数不确定,名字也不确定-->
    <div class="basic" :class="classArr" @click="removeStyle3">{{name}}</div><br>

    <!--   3. 绑定class样式--对象写法,适用于要绑定的样式个数确定,名字也确定,要动态决定用不用-->
    <div class="basic" :class="classObj">{{name}}</div><br>
    <button @click="useStyle1">点击添加样式1</button>
    <button @click="useStyle2">点击添加样式2</button>

</div>
<script>
    const vm = new Vue({
        el: '#root',
        data: {
            name: 'zzy',
            mood: 'normal',
            classArr: ['style1', 'style2', 'style3'],
            classObj: {
                style1: false,
                style2: false
            }
        },
        methods: {
            changeMood() {
                // this.mood = 'happy';
                //点击实现随机切换样式
                const arr = ['happy', 'sad', 'normal'];
                const index = Math.floor(Math.random() * 3);  //获取0-3之间的整数不包括3
                this.mood = arr[index];
            },
            //点击去掉style3样式
            removeStyle3() {
                this.classArr.pop();
            },
            //点击添加样式1
            useStyle1() {
                this.classObj.style1 = true;
                // this.classObj.style2 = true;
            },
            //点击添加样式2
            useStyle2() {
                // this.classObj.style1 = true;
                this.classObj.style2 = true;
            }
        }
    })
</script>

绑定style样式

<!--    绑定style样式--对象写法-->
<div class="basic" :class="classArr" :style="styleObj" >{{name}}</div><br>
<!--    绑定style样式--数组写法(非常不常用)-->
<div class="basic" :class="classArr" :style="[styleObj,styleObj2]" >{{name}}</div>
<script>
new Vue({
    el:'#root',
    data: {
        name: 'zzy',
        styleObj:{
        	//驼峰命名法
            fontSize:'50px',
            color:'red'
        },
        styleObj2:{
     	   //驼峰命名法
            backgroundColor:'green'
        }
   }
})
</script>

条件渲染

<body>
    <!-- 准备好一个容器 -->
<div id="root">

    <!-- 1.v-show="false" => 相当于display:none -->
    <h2 v-show="false">我的名字叫{{name}}</h2>
    <h2 v-show="1 === 3">我的名字叫{{name}}</h2>
    <!-- 等价于<h2 style="display: none;">我的名字叫{{name}}</h2> -->

    <!-- 2.v-if="false" => 彻底删除标签了 -->
    <h2 v-if="false">我的名字叫{{name}}</h2>
    <h2 v-if="1 === 3">我的名字叫{{name}}</h2>


    <!-- 实现功能:随着n递增展示不同的div -->
    <h2>当前n的值是:{{n}}</h2>
    <button v-on:click="n++">点击n+1</button>

    <!-- 这里的v-if,v-else-if,v-else和基础js里的一样儿 -->
    <div v-if="n === 1">Angular</div>
    <div v-else-if="n === 2">React</div>
    <div v-else-if="n === 3">Vue</div>
    <div v-else>哈哈</div>

    <!-- v-if和template的配合使用(v-show不行)
    template不会影响页面结构,页面运行后会自动去掉,但是可以配合v-if控制多个元素整体显示
    而且不会影响css拿节点-->
    <template v-if="n === 1">
        <div>哈哈1</div>
        <div>哈哈2</div>
        <div>哈哈3</div>
    </template>

</div>

<script>
    const vm = new Vue({
        el: '#root',
        data: {
            name: 'zzy',
            n: 0
        }
    })
</script>

列表渲染

    <!-- 准备好一个容器 -->
      <div id="root">
        <ul>
            <li v-for="(p,index) in persons" :key="p.id">
                <!-- 遍历数组的话,index是索引值,p是数组每个元素 -->
                {{p.name}}----{{p.age}}----{{index}}
            </li>

            <li v-for="(p,index) of games" :key="index">
                <!-- 遍历对象的话,index就是属性名,p是属性值 -->
                {{p}}---{{index}}
            </li>

            <li v-for="(p,index) of str" :key="index">
                <!-- 遍历字符串的话,index就是索引值,p是每个字符 -->
                {{p}}---{{index}}
            </li>

            <li v-for="(p,index) of 5" :key="index">
                <!-- 遍历指定次数的话,index就是索引值,p是从1开始数 -->
                {{p}}---{{index}}
            </li>
        </ul>
    </div>
//下面同上
  

key作用和原理

   <!-- 准备好一个容器 -->
    <div id="root">
        <h1>人员列表</h1>
        <button @click="add">点击添加老刘</button>
        <ul>
            <li v-for="(p,index) in persons" :key="p.id">
                <!-- 遍历数组的话,index是索引值,p是数组每个元素 -->
                {{p.name}}----{{p.age}}----{{index}}
                <input type="text">
            </li>
        </ul>
    </div>

    <script>
        const vm = new Vue({
            el: '#root',
            data: {
                persons: [
                    { id: '001', name: '张三', age: 23 },
                    { id: '002', name: '李四', age: 18 },
                    { id: '003', name: '王五', age: 10 }
                ]
            },
            methods: {
                add() {
                    const p = { id: 004, name: '老刘', age: 90 };
                    this.persons.unshift(p);
                }
            },
        })
    </script>

在这里插入图片描述
列表过滤

<!-- 准备好一个容器 -->
<div id="root">
    <h1>人员列表</h1>
     <input type="text" placeholder="请输入关键字" v-model="keyword" @keyup.enter="search"> 
    <ul>
        <li v-for="(p,index) in newPersons" :key="p.id">
            {{p.name}}----{{p.age}}----{{p.sex}}
        </li>
    </ul>
</div>

<script>
        const vm = new Vue({
            el: '#root',
            data: {
                keyword: '',
                persons: [
                    { id: '001', name: '冯万宁儿', age: 23, sex: '男' },
                    { id: '002', name: '屁及万儿', age: 18, sex: '男' },
                    { id: '003', name: '及丽热巴', age: 10, sex: '女' },
                    { id: '004', name: '冯小刚儿', age: 60, sex: '男' }
                ],
                 newPersons: []
            },
            methods: {
                search() {
                    this.newPersons = this.persons.filter((ele, index) => {
                        const arr = ele.name.split('');    //先把每个对象的name分割为数组
                        //数组里是不包含空字符串的,所以这样如果keyword=''是筛不出来东西的
                        const flag = arr.includes(this.keyword);   //判断数组中是否包含当前vue中的keyword
                        return flag;   //筛选出来包含keyword的对象,组成一个新数组
                    })
                }
            },

        })
</script>

用watch瑕疵实现

    <!-- 准备好一个容器 -->
<div id="root">
    <h1>人员列表</h1>
       <!-- <input type="text" placeholder="请输入关键字" v-model="keyword" @keyup.enter="search"> -->
       <input type="text" placeholder="请输入关键字" v-model="keyword">
    <ul>
        <li v-for="(p,index) in newPersons" :key="p.id">
            {{p.name}}----{{p.age}}----{{p.sex}}
        </li>
    </ul>
</div>

<script>
        const vm = new Vue({
            el: '#root',
            data: {
                keyword: '',
                persons: [
                    { id: '001', name: '冯万宁儿', age: 23, sex: '男' },
                    { id: '002', name: '屁及万儿', age: 18, sex: '男' },
                    { id: '003', name: '及丽热巴', age: 10, sex: '女' },
                    { id: '004', name: '冯小刚儿', age: 60, sex: '男' }
                ],
                 newPersons: []
            },
            watch: {
                keyword: {
                    //页面上来由于newPersons是空,不会显示数据,想要让页面初始化就显示所有人,就要加个immediate: true
                    //这样就可以让handler函数初始化时先调用一次,由于开始keyword=''
                    // 而字符串里都包含空字符串,就可以先筛选出来,初始化所有人物信息
                    immediate: true,
                    handler(newVal, oldVal) {
                        this.newPersons = this.persons.filter((ele) => {
                            //判断keyword变化后的新值在不在每个对象的name中,并返回一个新的数组
                            return ele.name.includes(newVal);
                            //有个点要注意,字符串里面是有空字符串的
                        });
                    }
                }
            }
        })
</script>

用computed完美实现

<!-- 准备好一个容器 -->
<div id="root">
    <h1>人员列表</h1>
    <!-- <input type="text" placeholder="请输入关键字" v-model="keyword" @keyup.enter="search"> -->
    <input type="text" placeholder="请输入关键字" v-model="keyword">
    <ul>
        <li v-for="(p,index) in newPersons" :key="p.id">
            {{p.name}}----{{p.age}}----{{p.sex}}
        </li>
    </ul>
</div>

<script>
    const vm = new Vue({
        el: '#root',
        data: {
            keyword: '',
            persons: [
                { id: '001', name: '冯万宁儿', age: 23, sex: '男' },
                { id: '002', name: '屁及万儿', age: 18, sex: '男' },
                { id: '003', name: '及丽热巴', age: 10, sex: '女' },
                { id: '004', name: '冯小刚儿', age: 60, sex: '男' }
            ],
            //newPersons: []
        },
        computed: {
            newPersons: {
                get() {
                    return this.persons.filter((ele) => {
                        return ele.name.includes(this.keyword);
                    })
                }
            }
        }
    })
</script>

列表排序

<!-- 准备好一个容器 -->
<div id="root">
    <h1>人员列表</h1>
    <input type="text" placeholder="请输入关键字" v-model="keyword">
    <button @click="sortType = 0">原顺序</button>
    <button @click="sortType = 1">年龄降序</button>
    <button @click="sortType = 2">年龄升序</button>
    <ul>
        <li v-for="(p,index) in newPersons" :key="p.id">
            {{p.name}}----{{p.age}}----{{p.sex}}
        </li>
    </ul>
</div>

<script>
    const vm = new Vue({
        el: '#root',
        data: {
            sortType: 0,   //0原顺序,1年龄降序,2年龄升序
            keyword: '',
            persons: [
                { id: '001', name: '冯万宁儿', age: 23, sex: '男' },
                { id: '002', name: '屁及万儿', age: 18, sex: '男' },
                { id: '003', name: '及丽热巴', age: 10, sex: '女' },
                { id: '004', name: '冯小刚儿', age: 60, sex: '男' }
            ],
        },
        computed: {
            newPersons() {
                //先过滤,再排序
                const arr = this.persons.filter((p) => {
                    return p.name.indexOf(this.keyword) !== -1
                })

                // 或者if(this.sortType)
                if (this.sortType !== 0) {
                    arr.sort((a, b) => this.sortType === 1 ? b.age - a.age : a.age - b.age)
                }
            
                return arr
            }
        }
    })
</script>

更新时的问题

<!-- 准备好一个容器 -->
<div id="root">
    <h1>人员列表</h1>
    <button @click="updateNing">更新冯万宁儿</button>
    <ul>
        <li v-for="(p,index) in persons" :key="p.id">
            {{p.name}}----{{p.age}}----{{p.sex}}
        </li>
    </ul>
</div>

<script>
    const vm = new Vue({
        el: '#root',
        data: {
            persons: [
                { id: '001', name: '冯万宁儿', age: 23, sex: '男' },
                { id: '002', name: '屁及万儿', age: 18, sex: '男' },
                { id: '003', name: '及丽热巴', age: 10, sex: '女' },
                { id: '004', name: '冯小刚儿', age: 60, sex: '男' }
            ],
        },
        methods: {
            updateNing() {
                // this.persons[0].name = '冯千宁儿';     //奏效
                // this.persons[0].age = 66;        //奏效
                // this.persons[0].sex = '女';      //奏效

                this.persons[0] = { id: '001', name: '冯千宁儿', age: 66, sex: '女' };
                //上面这么写,也奏效,数据实际上已经改了,但是Vue监测不到所以没更新到页面,为啥捏?
            }
        }
    })
</script>

在这里插入图片描述
监测数据的原理

	let data = {
	    name: 'zzy',
	    age: 18
	}
	
	//创建一个监视的实例对象,用来监视data中数据的变化
	const obs = new Observer(data);
	const vm = {};
	vm._data = obs;
	
	//创建一个类似vm._data的构造函数
	function Observer(obj) {
	    //1.创建一个数组接收传入对象的属性名
	    let arr = Object.keys(obj);  //['name','age']
	    //2.遍历属性名,让Observer实例对data中的每个数据进行数据代理
	    arr.forEach((k) => {
	        Object.defineProperty(this, k, {
	            get() {
	                //有人想读实例中的属性值,我就把data中对应的属性值拿过来
	                return obj[k];
	            },
	            set(val) {
	                //有人想改实例中的属性值,我就把data中对应的属性值更改(数据代理)
	                console.log(`${k}被改了,我要重新解析模板,生成虚拟DOM,开始diff算法`);
	                obj[k] = val;
	            }
	        })
	    })
	}

案例Vue.set()使用

<div id="root">
    <h2>我的名字:{{name}}</h2>
    <h2>我的年龄:{{age}}</h2>
    <h3 v-if="sex">我的性别:{{sex}}</h3>
    <button @click="addmySex">点击添加我的性别</button>
    <hr>
    <h2>她的名字:{{girlfriend.name}}</h2>
    <button @click="addherSex">点击添加性别,属性值为女</button>
    <h2 v-if="girlfriend.sex">她的性别:{{girlfriend.sex}}</h2> <!-- undefined不显示,也不报错 -->
    <h2>她的年龄:对外{{girlfriend.age.fakeAge}},真实{{girlfriend.age.realAge}}</h2>
    <h2>朋友们</h2>
    <ul>
        <li v-for="p in girlfriend.friends" :key="p.id">
            {{p.name}}----{{p.age}}
        </li>
    </ul>
</div>
<script>
    const vm = new Vue({
        el: '#root',
        data: {
            name: 'zzy',
            age: 18,
            girlfriend: {
                name: 'ht',
                // sex: '女',
                age: {
                    realAge: 23,
                    fakeAge: 18
                }
            }
        },
        methods: {
            addherSex() {
                // Vue.set(this.girlfriend, 'sex', '女');
                this.$set(this.girlfriend, 'sex', '女');  //vm.$set(vm.girlfriend, 'sex', '女');
            },
            addmySex() {
                Vue.set(this, 'sex', '男');
            }
        },
    })
</script>

(说实话,我没听懂……)所以我又听了一遍

Vue监测数组

<div id="root">
    <h2>我的名字:{{name}}</h2>
    <h2>我的年龄:{{age}}</h2>
    <hr>

    <h2>她的名字:{{girlfriend.name}}</h2>

    <button @click="addHobby">点击替换'跳'的爱好</button>
    <h2>爱好</h2>
    <ul>
        <li v-for="(h,index) in girlfriend.hobby" :key="index">
            {{h}}
        </li>
    </ul>
</div>
<script>
    const vm = new Vue({
        el: '#root',
        data: {
            name: 'zzy',
            age: 18,
            girlfriend: {
                name: 'ht',
                hobby: ['唱', '跳', 'rap']
            }
        },
        methods: {
            addHobby() {
                //除了那7个方法外,set方法也可以改变数组实现响应式
                Vue.set(this.girlfriend.hobby, 1, '打游戏');
            }
        },
    })  
</script>

案例

<div id="root">
    <button @click="addSex">添加一个性别属性,默认为女</button>
    <button @click="addHeight">添加一个身高属性,默认为170</button><br>
    <button @click="girlfriend.age.realAge--">年龄-1</button>
    <button @click="addFriend">在列表前加一个朋友</button><br>
    <button @click="updateFriend">修改第一个朋友的名字为张三</button>
    <button @click="addHobby">添加一个爱好</button><br>
    <button @click="updateHobby">修改第一个爱好为散步</button>
    <button @click="removeHobby">过滤掉爱好中的跳</button>

    <h2>名字:{{girlfriend.name}}</h2>
    <h2>年龄:对外{{girlfriend.age.fakeAge}},真实{{girlfriend.age.realAge}}</h2>
    <h2 v-if="girlfriend.sex">性别:{{girlfriend.sex}}</h2>
    <h2 v-if="girlfriend.height">身高:{{girlfriend.height}}</h2>

    <h2>朋友们</h2>
    <ul>
        <li v-for="p in girlfriend.friends" :key="p.id">
            {{p.name}}----{{p.age}}
        </li>
    </ul>

    <h2>爱好</h2>
    <ul>
        <li v-for="(h,index) in girlfriend.hobby" :key="index">
            {{h}}
        </li>
    </ul>
</div>
<script>
    const vm = new Vue({
        el: '#root',
        data: {
            name: 'zzy',
            age: 18,
            girlfriend: {
                name: 'ht',
                // sex: '女',
                age: {
                    realAge: 23,
                    fakeAge: 18
                },
                friends: [
                    { id: 001, name: 'jack', age: 10 },
                    { id: 002, name: 'rose', age: 8 },
                ],
                hobby: ['唱', '跳', 'rap']
            }
        },
        methods: {
            addSex() {
                Vue.set(this.girlfriend, 'sex', '女');
            },
            addHeight() {
                this.$set(this.girlfriend, 'height', 170);
            },
            addFriend() {
                this.girlfriend.friends.unshift({ id: '003', name: 'alice', age: 5 });  //有效写法
            },
            updateFriend() {
                this.girlfriend.friends[0].name = '张三';
            },
            addHobby() {
                this.girlfriend.hobby.push('打游戏');
            },
            updateHobby() {
                // this.girlfriend.hobby[0] = '散步';  //无效写法
                // this.girlfriend.hobby.splice(0, 1, '散步');   //有效写法
                Vue.set(this.girlfriend.hobby, 0, '散步');   //有效写法
            },
            removeHobby() {
                // 变更方法,顾名思义,会变更调用了这些方法的原始数组。相比之下,也有非变更方法
                // 例如 filter()、concat() 和 slice()。它们不会变更原始数组,而总是返回一个新数组。
                // 当使用非变更方法时,可以用新数组替换旧数组:
                this.girlfriend.hobby = this.girlfriend.hobby.filter((ele) => {
                    return ele !== '跳';
                })
            }
        },
    })
</script>

**代码参考与——DantinZhang
**

第五天

收集表单数据

   <!-- 准备好一个容器 -->
    <div id="root">
        <form v-on:submit.prevent="demo">
            <!-- v-model.trim去掉收集的首尾空格 -->
            账号:<input type="text" v-model.trim="userInfo.account"> <br><br>
            密码:<input type="password" v-model="userInfo.password"><br><br>
            <!--下面是 双向绑定修饰符:收集到的必须是数字类型(Vue内部做了数据转换) -->
            年龄:<input type="number" v-model.number="userInfo.age"><!-- v-model.number经常和type="number"一起用 --><br><br>

            性别:
            男<input type="radio" name="sex" value="male" v-model="userInfo.sex"><input type="radio" name="sex" value="female" v-model="userInfo.sex"><br><br>
            爱好:
            抽烟<input type="checkbox" value="smoke" v-model="userInfo.hobby">
            喝酒<input type="checkbox" value="drink" v-model="userInfo.hobby">
            跳舞<input type="checkbox" value="dance" v-model="userInfo.hobby"><br><br>
            玩哪个游戏?
            <select v-model="userInfo.game">
                <option value="saibo">赛博朋克2077</option>
                <option value="ditie">地铁:离去</option>
                <option value="dipingxian">地平线4</option>
                <option value="nfsmw">极品飞车21:热度</option>
                <option value="dabiaoge">荒野大镖客2</option>
            </select><br><br>

            <!-- v-model.lazy可以实现不用实时收集,输入框焦点离开了再收集 -->
            其他信息: <textarea v-model.lazy="userInfo.other"></textarea><br><br>
            <input type="checkbox" v-model="userInfo.agree">阅读并接受<a href="http://www.baidu.com">用户协议</a>
            <button>提交</button>
        </form>
    </div>

    <script>
        const vm = new Vue({
            el: '#root',
            data: {
                userInfo: {
                    account: '',
                    password: '',
                    age: '',
                    sex: 'female',
                    //hobby的数据类型影响着多选框收集到的数据类型
                    hobby: [],
                    game: 'nf smw',
                    other: '',
                    agree: '',
                },
            },
            methods: {
                demo() {
                    // console.log(JSON.stringify(this._data));  //一般不建议直接访问_data,建议用个对象包住数据
                    console.log(JSON.stringify(this.userInfo));  //只是这么写的话,所有双向绑定都要加userInfo前缀
                }
            },
        })
    </script>

v-model的三个修饰符
v-model.lazy:实现不用实时收集,输入框失去焦点再收集
v-model.number:输入的字符串收集为数字(Vue内部做了数据转换),经常和type="number"一起用
v-model.trim:收集时去掉输入的首尾空格

过滤器格式化时间戳
dayjs

   <!-- 准备一个容器 -->
    <div id="hello">
        <h1>当前时间是:{{time}}</h1>
        
        <!-- 计算属性实现 -->
        <h1>当前时间是:{{formatTime}}</h1>
        <!-- 方法实现 -->
        <h1>当前时间是:{{getformatTime()}}</h1>
        <!-- 过滤器实现 time传给timeFormater,然后返回值替换整个部分-->
        <h1>当前时间是:{{time | timeFormater}}</h1>
        <!-- 过滤器实现(传参)-->
        <h1>当前时间是:{{time | timeFormater('YYYY——MM——DD')}}</h1>
        <!-- 过滤器的串联,一层一层往后传,后面的接受的是前面的返回值-->
        <h1>当前时间是:{{time | timeFormater('YYYY——MM——DD') | mySlice}}</h1>
		<!-- 下面这个打开控制台看元素节点就明白了 -->
        <h3 :x="name | mySlice">DJ</h3> 
    </div>

    <script>
        // 全局过滤器
        Vue.filter('mySlice', function (val) {
            return val.slice(0, 4);
        })

        const vm = new Vue({
            el: '#hello',
            data: {
                time: 1660472948789,
                name: 'zhangziying'
            },
            computed: {
                formatTime: {
                    get() {
                        return dayjs(this.time).format('YYYY年MM月DD日 HH:mm:ss');
                    }
                }
            },
            methods: {
                getformatTime() {
                    return dayjs(this.time).format('YYYY年MM月DD日 HH:mm:ss');
                }
            },
            // 局部过滤器
            filters: {
                //第一个参数是管道符 | 前边那玩意儿
                //第二个参数str来个默认值,如果传了str就给,不传就用默认值
                timeFormater(val, str = 'YYYY年MM月DD日 HH:mm:ss') {
                    // console.log(val);
                    return dayjs(this.time).format(str);
                },
                mySlice(val) {
                    //这里的val是上一个过滤器的返回值
                    return val.slice(0, 4);
                }
            }
        })
    </script>

内置指令

v-bind : 单向绑定解析表达式, 可简写为 :xxx
v-model : 双向数据绑定
v-for : 遍历数组/对象/字符串
v-on : 绑定事件监听, 可简写为@
v-if : 条件渲染(动态控制节点是否存存在)
v-else : 条件渲染(动态控制节点是否存存在)
v-show : 条件渲染 (动态控制节点是否展示)

v-text指令:
1.作用:向其所在的节点中渲染文本内容。
2.与插值语法的区别:v-text会替换掉节点中的所有内容,{{xx}}则不会

v-html指令:
作用:向指定节点中渲染包含html结构的内容。
与插值语法的区别:
(1)v-html会替换掉节点中所有的内容,{{xx}}则不会,这点和v-text一样。
(2)v-html可以识别html结构,这点和v-text区别,v-text不能渲染标签。

严重注意:v-html有安全性问题!!!!
(1)在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击。
(2)一定要在可信的内容上使用v-html,永不要用在用户提交的内容上!


v-cloak指令(没有值):
(1)本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性。
(2)使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题,先隐藏标签,然后Vue渲染完了之后删除v-cloak,那么就能显示渲染完之后的页面了


v-once指令:
(1)v-once所在节点在初次动态渲染后,就视为静态内容了,也就是只读一次。
(2)以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能。

v-pre指令:
(1)跳过其所在节点的编译过程。
(2)可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译。

cookie
在这里插入图片描述
批量编辑器
在这里插入图片描述
自定义指令
函数式

   <!-- 准备一个容器 -->
    <div id="hello">
        <h1>当前n值是:<span v-text="n"></span></h1>
        <h1>放大十倍后的n值是:<span v-big="n"></span></h1>
        <button @click="n++">点我n+1</button>
    </div>

    <script>
        const vm = new Vue({
            el: '#hello',
            data: {
                n: 1
            },
            directives: {
                //一、函数式
                // 需求1:定义一个v-big指令,和v-text功能类似,但会把绑定的数值放大10倍。
                //第一个参数是指令所在的标签,第二个参数是一个存着指令值的对象
                big(element, binding) {
                    //big函数何时会被调用? 
                    //1.指令与元素成功绑定时(一上来,没放入页面之前)  2.指令所在的模板被重新解析时
                    console.log('我被调用了');
                    element.innerText = binding.value * 10;
                },
            }
        })
    </script>

对象式

   <!-- 准备一个容器 -->
    <div id="hello">
        <h1>当前n值是:<span v-text="n"></span></h1>
        <button @click="n++">点我n+1</button>
		<!-- 在输入框中显示n的值动态变化 -->
        <input v-fbind:value="n">
    </div>

    <script>
        const vm = new Vue({
            el: '#hello',
            data: {
                n: 1
            },
            directives: {
                // 需求2:定义一个v-fbind指令,和v-bind功能类似,但可以让其所绑定的input元素默认获取焦点。
                //函数无法实现该需求
                // fbind(element, binding) {
                //     element.innerText = binding.value * 10;
                //     //下面这个focus,必须在放到页面之后才调用
                //     element.focus(); //不奏效,因为big函数调用时还没放入页面
                // }
                //二、对象式
                fbind: {
                    // 指令与元素成功绑定时(一上来,没放入页面之前)
                    bind(element, binding) {
                        element.value = binding.value;
                    },
                    // 指令所在元素被插入页面时
                    inserted(element, binding) {
                        element.focus();
                    },
                    // 指令所在的模板被重新解析时
                    update(element, binding) {
                        element.value = binding.value;
                    }
                }
            }
        })
    </script>

生命周期

 <script type="text/javascript">
        new Vue({
            el:'#root',
            data:{
                a:false,
                opacity:1
            },
            methods: {
                
            },
            mounted() {
                console.log('mounted',this)
                setInterval(()=>{
                    this.opacity -=0.01
                    if(this.opacity<=0) this.opacity = 1
                },16)
            },
        })
    </script>

生命周期图示

八个钩子

   <!-- 准备一个容器 -->
    <div id="hello">
        <h1>欢迎来到{{n}}年代</h1>
        <button @click="add">点击n+1</button>
    </div>

    <script>
        const vm = new Vue({
            el: '#hello',
            data: {
                n: 1
            },
            methods: {
                add() {
                    this.n++;
                }
            },
            beforeCreate() {
                console.log('beforeCreate');
                console.log(this);
                // debugger;
            },
            created() {
                console.log('created');
            },
            beforeMount() {
                console.log('beforeMount');
            },
            mounted() {
                console.log('mounted');
            },
            beforeUpdate() {
                console.log('beforeUpdate');
            },
            updated() {
                console.log('updated');
            },
            beforeDestroy() {
                console.log('beforeDestroy');
            },
            destryed() {
                console.log('destryed');
            }
        })
    </script>

在这里插入图片描述

案例

<!-- 准备一个容器 -->
<div id="hello">
    <h1 :style="{opacity: opacity}">欢迎来到2024</h1>
    <button @click="stop">点击停止闪烁</button>
</div>

<script>
    const vm = new Vue({
        el: '#hello',
        data: {
            opacity: 1
        },
        methods: {
            stop() {
                // clearInterval(this.timer);  vm自杀可以这么写,他杀需要写在beforeDestroy中
                this.$destroy();  //vm自杀
            }
        },
        //挂载意思就是放在页面上
        //挂载函数,Vue完成模板的解析并把*初始的(只调用一次)*真实DOM放入页面后(完成挂载)调用mounted
        mounted() {
            this.timer = setInterval(() => {
                console.log('计时器调用');
                this.opacity -= 0.01;
                if (this.opacity <= 0) this.opacity = 1;  //js里玩儿小数一般碰不到0 
            }, 16)
        },

        beforeDestroy() {
            console.log('vm即将被销毁');
            // 为什么vm的后事需要写在这里,是因为vm很有可能是被别人干掉的
            clearInterval(this.timer);
        },

    })

    //通过外部的定时器实现(不推荐)
    // setInterval(() => {
    //     vm.opacity -= 0.01;
    //     if (vm.opacity <= 0) vm.opacity = 1;  //js里玩儿小数一般碰不到0
    // }, 16);
</script>

第六天

使用组件
在这里插入图片描述

<div id="root">
    <hello></hello>
    <hr>
    <h1>{{msg}}</h1>
    <school></school>
     <hr>
    <student></student>
 </div>
 <div id="root2">
    <hello></hello>
 </div>

<script type="text/javascript">
    //创建school组件
    const school = Vue.extend({
        template:`
        <div>
        <h2>学校名称:{{schoolName}}</h2>
        <h2>学校地址:{{address}}</h2>
        <button @click="showName">点我提示校名</button>
        </div>
        `,
        data(){
            return{
                schoolName:'尚硅谷',
                address:'长沙'
            }
        },
        methods: {
            showName(){
                alert(this.schoolName)
            }
        },
    })
     //创建student组件
     const student = Vue.extend({
        template:`
        <div>
            <h2>学生姓名:{{studentName}}</h2>
            <h2>学生年龄:{{age}}</h2>
        </div>    
        `,
        data(){
            return{
                studentName:'张三',
                age:18
            }
        }
    })

    const hello = Vue.extend({
        template:`
        <div>
            <h2>你好啊!</h2>
            </div>
        `,
        data(){
            return{
                name:'Tom'
            }
        }
    })

    //全局注册组件
    Vue.component('hello',hello)

    //创建vm
    new Vue({
        el:'#root',
        //注册组件(局部注册)
        components:{
           school,
           student
        }
    })

    new Vue({
        el:'#root2',
    })
</script>

注意点
在这里插入图片描述
组件的嵌套

 <div id="root">
    <app></app>
  </div>
   <script type="text/javascript">
    //定义student组件
    const student = Vue.extend({
        name:'student',
        template:`
        <div>
            <h2>学生姓名:{{name}}</h2>
            <h2>学生年龄:{{age}}</h2>
        </div>    
        `,
        data(){
            return{
                name:'张三',
                age:18
            }
        }
    })

    //定义school组件
    const school = Vue.extend({
        name:'school',
        template:`
        <div>
            <h2>学校名称:{{name}}</h2>
            <h2>学校地址:{{address}}</h2>
            <student></student>
            </div>
        `,
        data(){
            return{
                name:'尚硅谷',
                address:'北京'
            }
        },
        //注册组件(局部)
        components:{
            student
        }
    })

    //定义hello组件
    const hello = Vue.extend({
        template:`
        <h1>{{msg}}</h1>
        `,
        data(){
            return{
                msg:'欢迎来到尚硅谷学习'
            }
        }
    })

    //定义app组件
    const app = Vue.extend({
        template:`
        <div>
            <hello></hello>
            <school></school>
            </div>
        `,
        components:{
            school,
            hello
        }
    })

    //创建vm
    new Vue({
        el:'#root',
        //注册组件(局部)
        components:{
            app
        }
    })
   </script>

VueComponent
在这里插入图片描述

<div id="root">
    <hello></hello>
    <school></school>
  </div>
   <script type="text/javascript">
    //定义student组件
    
    //定义school组件
    const school = Vue.extend({
        name:'school',
        template:`
        <div>
            <h2>学校名称:{{name}}</h2>
            <h2>学校地址:{{address}}</h2>
            <button @click="showName">点我提示学校名</button>
            </div>
        `,
        data(){
            return{
                name:'尚硅谷',
                address:'北京'
            }
        },
        methods: {
            showName(){
            // alert(this.name)
            console.log('showName',this)
        }
        },
    })

    const test = Vue.extend({
        template:`<span>hahahaha</span>`,
    })

   //定义hello组件
   const hello = Vue.extend({
    template:`
    <div>
        <h2>{{msg}}</h2>
        <test></test>
        </div>
    `,
    data(){
        return{
            msg:'你好'
        }
    },
    components:{
        test
    }
   })
  
//    console.log('@',school)
//    console.log('#',hello)
    //定义app组件
   
    //创建vm
    new Vue({
        el:'#root',
        //注册组件(局部)
        components:{
            school,
            hello
        }
    })
   </script>

重要的内置关系
在这里插入图片描述

<div id="root">

  </div>

  <script type="text/javascript">
    //定义一个构造函数
    function Demo(){
        this.a = 1
        this.b = 1
    }
    //创建一个Demo的实例对象
    const d = new Demo()

    console.log(Demo.prototype)//显示原型属性
    console.log(d._proto_)//隐式原型属性
    console.log(Demo.prototype === d._proto_)

    

    //程序员通过显示原型属性对象,追加一个x属性,值为99
    Demo.prototype.x = 99

    console.log('@',d)
  </script>

单文件组件
School.vue

<template>
        <div class="demo">
        <h2>学校名称:{{schoolName}}</h2>
        <h2>学校地址:{{address}}</h2>
        <button @click="showName">点我提示校名</button>
        </div>
</template>

<script>
//组件交互相关代码(数据、方法等等)
//Vue.extend可省略
export default {
    name:'School',
    data(){
            return{
                schoolName:'尚硅谷',
                address:'长沙'
            }
        }, 
        methods: {
            showName(){
                alert(this.schoolName)
            }
        },
}
   // export default school  默认暴露
</script>

<style>
/* 组件样式 */
.demo{
    background-color:pink;
}
</style>

app.vue
<v +回车 调出架子

<template>
  <div>
    <School></School>
  </div>
</template>

<script>
    //引入组件
    import School from './School.vue'

    export default {
        name:'App',
        components:{
            School
        }
    }
</script>

<style>

</style>

main.js

import App from './App.vue'

new Vue({
    el:'#root',
    template:`<App></App>`,
    components:{App},
})

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="root">
        <!-- <App></App> -->
    </div>
    <!-- <script type="text/javascript" src="../vue.js"></script>
    <script type="text/javascript" src="./main.js"></script> -->
</body>
</html>

Vue脚手架
是Vue官方提供的标准化开发工具
开发文档
建议先安装node.js
教程
vue安装步骤:

npm install -g @vue/cli
vue

一定要记得目录,别待会找不到

vue create name

选好用2还是3
再按指示操作

npm run serve

在这里插入图片描述
单词别写错了
在这里插入图片描述
emmmmNetwork: unavailable怎么解决……
在这里插入图片描述
等大佬救我……
解决了,这个IP号填错了,每个wifi有对应的号,点开wifi进入属性,看ipv4复制就行
在这里插入图片描述
在这里插入图片描述
本地存储也跟着解决了,,,,加油加油

然后复制链接回车
停止工程可以按两次ctrl +c
(报错可能是权限问题,命令提示符用管理员身份进)

进入文件
调出终端快捷键:ctrl + ~

├── node_modules 
├── public
│   ├── favicon.ico: 页签图标
│   └── index.html: 主页面
├── src
│   ├── assets: 存放静态资源
│   │   └── logo.png
│   │── component: 存放组件
│   │   └── HelloWorld.vue
│   │── App.vue: 汇总所有组件
│   │── main.js: 入口文件
├── .gitignore: git版本管制忽略的配置
├── babel.config.js: babel的配置文件
├── package.json: 应用包配置文件 
├── README.md: 应用描述文件
├── package-lock.json:包版本控制文件

index.html

<!DOCTYPE html>
<html lang="">
  <head>
    <meta charset="utf-8">
    <!-- 针对IE浏览器的一个特殊配置,含义是让IE浏览器以最高的渲染级别渲染页面 -->
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <!-- 开启移动端的理想视口 -->
    <meta name="viewport" content="width=device-width,initial-scale=1.0">     
   <!--  配置页签图标  -->                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           -->
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <!-- 配置网页标题 -->
    <title><%= htmlWebpackPlugin.options.title %></title>
  </head>
  <body>
    <!-- 当浏览器不支持js时noscript中元素就会被渲染 -->
    <noscript>
      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <!-- 容器 -->
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

main.js

//入口文件
//引入Vue
import Vue from 'vue'
//引入App组件,它是所有组件的父组件
import App from './App.vue'
//关闭vue的生产提示
Vue.config.productionTip = false
//创建Vue实例对象---vm
new Vue({
  render: h => h(App),
}).$mount('#app')

render函数
扮演了vue中解析template模板的那块儿代码

ref属性
被用来给元素或子组件注册引用信息(id的替代者)
应用在html标签上获取的是真实DOM元素,应用在组件标签上是组件实例对象(vc)
使用方式:
1、打标识:


2、获取:this.$refs.xxx

<template>
    <div>
        <h1 v-text="msg" ref="title"></h1>
        <button @click="showDom" ref="btn">点我输出上方的DOM元素</button>
        <MySchool111 ref="school" id="school"></MySchool111>
    </div>
</template>

<script>
// 如果组件没写名字,那么就用的import后面起的名字
import MySchool111 from './compoments/MySchool.vue';

export default {
    name: 'Appppp',  //这里如果写名字,开发者工具里看的就是这个名字
    components: {
        MySchool111
    },
    data() {
        return {
            msg: '从蓬莱写到仙台,哥们儿代码信手拈来'
        }
    },
    methods: {
        showDom() {
            // console.log(document.getElementById('title')); //这种写法拿不到组件
            console.log(this.$refs.title); //拿到h1真实DOM元素标签
            console.log(this.$refs.btn); //拿到button真实DOM元素标签
            console.log(this.$refs.school); //拿到组件的实例(MySchool的vc)

            //如果这么写,拿到的是组件template中的内容,相当于给根的div加了个id="school"
            console.log(document.getElementById('school'));
        }
    },
}
</script>

props配置
让组件接收外部传过来的数据。
props这个配置项就类似微信转账,App那边的标签里传过来,这边得接一下子

<template>
    <div>
        <!-- 加个单项数据绑定,引号里面就不是字符串了,就是表达式了 -->
        <Student name="李四" sex="女" :age="20"></Student>
        <Student name="王五" sex="男" :age="20 + 1" />
        <!-- <Student name="zzy" sex="男" age="20" /> -->
    </div>
</template>

简单接收

props: ['name', 'age', 'sex']

接收的同时对数据进行类型限制

props: {
    name: String,
    age: Number,
    sex: String
}

接收时同时对数据:进行类型校验+默认值指定+必要性限制

props: {
        name: {
            type: String,   //name的类型是字符串
            required: true  //name是必须填的
        },
        age: {
            type: Number, //age的类型时数值
            default: 99  //age可以不填,不填就是99
        },
        sex: {
            type: String,   //sex的类型是字符串
            required: true  //sex是必须填的
        }
    }

Student.vue

<template>
    <div>
        <h1>{{ msg }}</h1>
        <h2>学生名称:{{ name }}</h2>
        <h2>学生性别:{{ sex }}</h2>
        <!-- 实现年龄+1 要加v-bind把引号里的东西变成js表达式,否则是字符串+1-->
        <!-- <h2>学生年龄:{{ age*1+1 }}</h2> 强制类型转换一下-->
        <h2>学生年龄age:{{ age + 1 }}</h2>
        <h2>学生年龄myAge:{{ myAge + 1 }}</h2>
        <button @click="updateAge">尝试修改收到的年龄</button>
    </div>
</template>

<script>
export default {
    name: 'Student',
    data() {
        return {
            msg: '从蓬莱写到仙台,哥们儿代码信手拈来',
            //想要修改age,就要用一个新的变量myAge来接收传进来的值
            //然后页面显示myAge就能实现修改,props里的东西是只读的
            myAge: this.age
            // name: 'zzy',
            // age: 18,
            // sex: '男'
        }
    },
    methods: {
        updateAge() {
            // this.age++;  //会报错但是能改但是不建议改
            this.myAge++;
        }
    },
    //props这个配置项就类似微信转账,App那边的标签里传过来,这边得接一下子
    //props中的内容优先级最高,先接这边的数据放vc里,再去读data,若有重复不会覆盖
    props: ['name', 'age', 'sex']
}
</script>

在这里插入图片描述

mixin(混入)
功能:可以把多个组件共用的配置提取成一个混入对象

Student.vue

<template>
  <div>
    <h2 @click="showName">学生姓名:{{name}}</h2>
    <h2>学生性别:{{sex}}</h2>
  </div>
</template>

<script>

import {hunhe,hunhe2}from '../mixin'
export default {
    name:'Student',
    data(){
            return{
                name:'张三',
                sex:'男'
            }
        }, 
        mixins:[hunhe,hunhe2]
}
</script>

<style>

</style>

School.vue

<template>
        <div >
        <h2 @click="showName">学校名称:{{name}}</h2>
        <h2>学校地址:{{address}}</h2>
        <!-- <button @click="showName">点我提示校名</button> -->
        </div>
</template>

<script>
//组件交互相关代码(数据、方法等等)
//Vue.extend可省略
import {hunhe,hunhe2}from '../mixin'
export default {
    name:'School',
    data(){
            return{
                name:'尚硅谷',
                address:'长沙'
            }
        }, 
        mixins:[hunhe,hunhe2]
}
   // export default school  默认暴露
</script>

<style>

</style>

mixin.js

export const hunhe = {
    methods: {
        showName(){
            alert(this.name)
        }
    },
    mounted() {
        console.log('你好')
    },
}
export const hunhe2 = {
    data(){
        return{
            x:100,
            y:200
        }
    }
}

在这里插入图片描述
插件
功能:用于增强Vue
本质:包含install方法的一个对象,install的第一个参数是Vue,第二个以后的参数是插件使用者传递的数据。
使用插件Vue.use()

//在main.js中引入插件并起个名儿
import plugins from './plugins';
//使用插件,要在new Vue之前使用
Vue.use(plugins, 1, 2, 3);

在这里插入图片描述

定义插件:可以在另一个js中配置插件,然后通过import引入到main.js中

const plusobj = {
    install(Vue, x, y, z) {
        console.log(Vue);  //第一个参数是Vue构造函数
        console.log(x, y, z); //后面的参数是使用者传进来的东西123

        //1.定义一个全局过滤器
        Vue.filter('mySlice', function (val) {
            return val.slice(0, 4);  //返回值别忘了
        });

        //2.定义一个全局自定义指令,元素默认获取焦点
        Vue.directive('fbind', {
            bind(el, binding) {
                el.value = binding.value;
            },
            inserted(el) {
                el.focus();
            },
            update(el, binding) {
                el.value = binding.value;
            }
        })

        //3.定义一个全局混合,不用引入就能给所有的vm和vc
        Vue.mixin({
            data() {
                return {
                    x: 1,
                    y: 2
                }
            }
        })

        //4.给Vue的原型对象添加实例方法,vm和vc都能用
        Vue.prototype.hello = () => { alert('hello!') }
    }
}

export default plusobj;

scoped样式
作用:让样式在局部生效,防止冲突。
写法:

指定使用 less写法:

备注:
查看webpack所有版本 当前项目文件目录>npm view webpack versions
安装less版本7当前项目文件目录>npm i less-loader@7

第七天

TodoList案例
在这里插入图片描述
app.vue

<template>
	<div id="root">
		<div class="todo-container">
			<div class="todo-wrap">
				<MyHeader :addTodo="addTodo"/>
				<MyList :todos="todos" :checkTodo="checkTodo" :deleteTodo="deleteTodo"/>
				<MyFooter :todos="todos" :checkAllTodo="checkAllTodo" :clearAllTodo="clearAllTodo"/>
			</div>
		</div>
	</div>
</template>

<script>
	import MyHeader from './components/MyHeader'
	import MyList from './components/MyList'
	import MyFooter from './components/MyFooter.vue'

	export default {
		name:'App',
		components:{MyHeader,MyList,MyFooter},
		data() {
			return {
				//由于todos是MyHeader组件和MyFooter组件都在使用,所以放在App中(状态提升)
				todos:[
					{id:'001',title:'抽烟',done:true},
					{id:'002',title:'喝酒',done:false},
					{id:'003',title:'开车',done:true}
				]
			}
		},
		methods: {
			//添加一个todo
			addTodo(todoObj){
				this.todos.unshift(todoObj)
			},
			//勾选or取消勾选一个todo
			checkTodo(id){
				this.todos.forEach((todo)=>{
					if(todo.id === id) todo.done = !todo.done
				})
			},
			//删除一个todo
			deleteTodo(id){
				this.todos = this.todos.filter( todo => todo.id !== id )
			},
			//全选or取消全选
			checkAllTodo(done){
				this.todos.forEach((todo)=>{
					todo.done = done
				})
			},
			//清除所有已经完成的todo
			clearAllTodo(){
				this.todos = this.todos.filter((todo)=>{
					return !todo.done
				})
			}
		}
	}
</script>

<style>
	/*base*/
	body {
		background: #fff;
	}
	.btn {
		display: inline-block;
		padding: 4px 12px;
		margin-bottom: 0;
		font-size: 14px;
		line-height: 20px;
		text-align: center;
		vertical-align: middle;
		cursor: pointer;
		box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
		border-radius: 4px;
	}
	.btn-danger {
		color: #fff;
		background-color: #da4f49;
		border: 1px solid #bd362f;
	}
	.btn-danger:hover {
		color: #fff;
		background-color: #bd362f;
	}
	.btn:focus {
		outline: none;
	}
	.todo-container {
		width: 600px;
		margin: 0 auto;
	}
	.todo-container .todo-wrap {
		padding: 10px;
		border: 1px solid #ddd;
		border-radius: 5px;
	}
</style>

MyFooter.vue

<template>
	<div class="todo-footer" v-show="total">
		<label>
			<!-- <input type="checkbox" :checked="isAll" @change="checkAll"/> -->
			<input type="checkbox" v-model="isAll"/>
		</label>
		<span>
			<span>已完成{{doneTotal}}</span> / 全部{{total}}
		</span>
		<button class="btn btn-danger" @click="clearAll">清除已完成任务</button>
	</div>
</template>

<script>
	export default {
		name:'MyFooter',
		props:['todos','checkAllTodo','clearAllTodo'],
		computed: {
			//总数
			total(){
				return this.todos.length
			},
			//已完成数
			doneTotal(){
				//此处使用reduce方法做条件统计
				/* const x = this.todos.reduce((pre,current)=>{
					console.log('@',pre,current)
					return pre + (current.done ? 1 : 0)
				},0) */
				//简写
				return this.todos.reduce((pre,todo)=> pre + (todo.done ? 1 : 0) ,0)
			},
			//控制全选框
			isAll:{
				//全选框是否勾选
				get(){
					return this.doneTotal === this.total && this.total > 0
				},
				//isAll被修改时set被调用
				set(value){
					this.checkAllTodo(value)
				}
			}
		},
		methods: {
			/* checkAll(e){
				this.checkAllTodo(e.target.checked)
			} */
			//清空所有已完成
			clearAll(){
				this.clearAllTodo()
			}
		},
	}
</script>

<style scoped>
	/*footer*/
	.todo-footer {
		height: 40px;
		line-height: 40px;
		padding-left: 6px;
		margin-top: 5px;
	}

	.todo-footer label {
		display: inline-block;
		margin-right: 20px;
		cursor: pointer;
	}

	.todo-footer label input {
		position: relative;
		top: -1px;
		vertical-align: middle;
		margin-right: 5px;
	}

	.todo-footer button {
		float: right;
		margin-top: 5px;
	}
</style>

MyHeader.vue

<template>
	<div class="todo-header">
		<input type="text" placeholder="请输入你的任务名称,按回车键确认" v-model="title" @keyup.enter="add"/>
	</div>
</template>

<script>
	import {nanoid} from 'nanoid'
	export default {
		name:'MyHeader',
		//接收从App传递过来的addTodo
		props:['addTodo'],
		data() {
			return {
				//收集用户输入的title
				title:''
			}
		},
		methods: {
			add(){
				//校验数据
				if(!this.title.trim()) return alert('输入不能为空')
				//将用户的输入包装成一个todo对象
				const todoObj = {id:nanoid(),title:this.title,done:false}
				//通知App组件去添加一个todo对象
				this.addTodo(todoObj)
				//清空输入
				this.title = ''
			}
		},
	}
</script>

<style scoped>
	/*header*/
	.todo-header input {
		width: 560px;
		height: 28px;
		font-size: 14px;
		border: 1px solid #ccc;
		border-radius: 4px;
		padding: 4px 7px;
	}

	.todo-header input:focus {
		outline: none;
		border-color: rgba(82, 168, 236, 0.8);
		box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
	}
</style>

MyItem.vue

<template>
	<li>
		<label>
			<input type="checkbox" :checked="todo.done" @change="handleCheck(todo.id)"/>
			<!-- 如下代码也能实现功能,但是不太推荐,因为有点违反原则,因为修改了props -->
			<!-- <input type="checkbox" v-model="todo.done"/> -->
			<span>{{todo.title}}</span>
		</label>
		<button class="btn btn-danger" @click="handleDelete(todo.id)">删除</button>
	</li>
</template>

<script>
	export default {
		name:'MyItem',
		//声明接收todo、checkTodo、deleteTodo
		props:['todo','checkTodo','deleteTodo'],
		methods: {
			//勾选or取消勾选
			handleCheck(id){
				//通知App组件将对应的todo对象的done值取反
				this.checkTodo(id)
			},
			//删除
			handleDelete(id){
				if(confirm('确定删除吗?')){
					//通知App组件将对应的todo对象删除
					this.deleteTodo(id)
				}
			}
		},
	}
</script>

<style scoped>
	/*item*/
	li {
		list-style: none;
		height: 36px;
		line-height: 36px;
		padding: 0 5px;
		border-bottom: 1px solid #ddd;
	}

	li label {
		float: left;
		cursor: pointer;
	}

	li label li input {
		vertical-align: middle;
		margin-right: 6px;
		position: relative;
		top: -1px;
	}

	li button {
		float: right;
		display: none;
		margin-top: 3px;
	}

	li:before {
		content: initial;
	}

	li:last-child {
		border-bottom: none;
	}

	li:hover{
		background-color: #ddd;
	}
	
	li:hover button{
		display: block;
	}
</style>

MyList.vue

<template>
	<ul class="todo-main">
		<MyItem 
			v-for="todoObj in todos"
			:key="todoObj.id" 
			:todo="todoObj" 
			:checkTodo="checkTodo"
			:deleteTodo="deleteTodo"
		/>
	</ul>
</template>

<script>
	import MyItem from './MyItem'

	export default {
		name:'MyList',
		components:{MyItem},
		//声明接收App传递过来的数据,其中todos是自己用的,checkTodo和deleteTodo是给子组件MyItem用的
		props:['todos','checkTodo','deleteTodo']
	}
</script>

<style scoped>
	/*main*/
	.todo-main {
		margin-left: 0px;
		border: 1px solid #ddd;
		border-radius: 2px;
		padding: 0px;
	}

	.todo-empty {
		height: 40px;
		line-height: 40px;
		border: 1px solid #ddd;
		border-radius: 2px;
		padding-left: 5px;
		margin-top: 10px;
	}
</style>

浏览器本地存储
上面Network: unavailable问题没解决下面也会有问题,服啦
在这里插入图片描述
localStorage.html

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>localStorage</title>
	</head>
	<body>
		<h2>localStorage</h2>
		<button onclick="saveData()">点我保存一个数据</button>
		<button onclick="readData()">点我读取一个数据</button>
		<button onclick="deleteData()">点我删除一个数据</button>
		<button onclick="deleteAllData()">点我清空一个数据</button>

		<script type="text/javascript" >
			let p = {name:'张三',age:18}

			function saveData(){
				localStorage.setItem('msg','hello!!!')
				localStorage.setItem('msg2',666)
				localStorage.setItem('person',JSON.stringify(p))
			}
			function readData(){
				console.log(localStorage.getItem('msg'))
				console.log(localStorage.getItem('msg2'))

				const result = localStorage.getItem('person')
				console.log(JSON.parse(result))

				// console.log(localStorage.getItem('msg3'))
			}
			function deleteData(){
				localStorage.removeItem('msg2')
			}
			function deleteAllData(){
				localStorage.clear()
			}
		</script>
	</body>
</html>

sessionStorage.html

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>sessionStorage</title>
	</head>
	<body>
		<h2>sessionStorage</h2>
		<button onclick="saveData()">点我保存一个数据</button>
		<button onclick="readData()">点我读取一个数据</button>
		<button onclick="deleteData()">点我删除一个数据</button>
		<button onclick="deleteAllData()">点我清空一个数据</button>

		<script type="text/javascript" >
			let p = {name:'张三',age:18}

			function saveData(){
				sessionStorage.setItem('msg','hello!!!')
				sessionStorage.setItem('msg2',666)
				sessionStorage.setItem('person',JSON.stringify(p))
			}
			function readData(){
				console.log(sessionStorage.getItem('msg'))
				console.log(sessionStorage.getItem('msg2'))

				const result = sessionStorage.getItem('person')
				console.log(JSON.parse(result))

				// console.log(sessionStorage.getItem('msg3'))
			}
			function deleteData(){
				sessionStorage.removeItem('msg2')
			}
			function deleteAllData(){
				sessionStorage.clear()
			}
		</script>
	</body>
</html>

在这里插入图片描述

第八天

组件自定义事件
在这里插入图片描述
累了,毁灭吧

第九天

动画效果
Test.vue

<template>
  <div>
    <button @click="isShow =!isShow">显示/隐藏</button>
    <transition name="hello" appear>
        <h1 v-show="isShow" class="come">你好啊</h1>
    </transition>

    <!-- <transition name="h2" appear>
        <h2 v-show="isShow">尚硅谷</h2>
    </transition> -->
      </div>
</template>

<script>
    export default {
        name:'Test',
        data(){
            return{
                isShow:true
            }
        },
    }
</script>

<style scoped>
h1{
    border-color: orange;
}

.hello-enter-active{
    animation: atguigu 1s linear; 
}
.hello-leave-active{
    animation: atguigu 1s linear reverse;
}

@keyframes atguigu {
    from{
        transform: translateX(-100px);
    }
    to{
        transform: translateX(0px);
    }
}

</style>

过渡效果
Test2.vue

<template>
    <div>
      <button @click="isShow =!isShow">显示/隐藏</button>
      <transition name="hello" appear>
          <h1 v-show="isShow">你好啊</h1>
      </transition>
  
      <!-- <transition name="h2" appear>
          <h2 v-show="isShow">尚硅谷</h2>
      </transition> -->
        </div>
  </template>
  
  <script>
      export default {
          name:'Test',
          data(){
              return{
                  isShow:true
              }
          },
      }
  </script>
  
  <style scoped>
  h1{
      border-color: orange;
      transform: 0.5s linear;
  }
  
  .hello-enter,.hello-leave-to{
       transform: translateX(-100%);
  }

  .hello-enter-active,.hello-leave-active{
    transform: 0.5s linear;
  }

  .hello-enter-to,.hello-leave{
    transform: translateX(0);
  }

  
  </style>

app.vue

<template>
  <div >
    <Test></Test>
    <Test2></Test2>
   </div>
</template>

<script>
import Test from './components/Test.vue'
import Test2 from './components/Test2.vue';

export default {
  name: 'App',
  components: {
    Test,Test2
  },
}
</script>

<style>

</style>

样式库
Animate.css
链接位置

安装npm install animate.css+引入import ‘animate.css’在这里插入图片描述
Test3.vue

<template>
    <div>
      <button @click="isShow =!isShow">显示/隐藏</button>
      <transition-group
         appear
         name="animate_animated animate_bounce"
         enter-active-class="animate_swing"
         leave-active-class="animate_backOutUp"
         >
          <h1 v-show="!isShow" key="1">你好啊</h1>
          <h1 v-show="isShow" key="2">尚硅谷</h1>
      </transition-group>
  
   
        </div>
  </template>
  
  <script>
    import 'animate.css'
      export default {
          name:'Test',
          data(){
              return{
                  isShow:true
              }
          },
      }
  </script>
  
  <style scoped>
  h1{
      border-color: orange;
      transform: 0.5s linear;
  }
  
 

  
  </style>

配置代理
引入axios

npm i axios

app.vue

<template>
  <div >
<button @click="getStudents">获取学生信息</button>
   </div>
</template>

<script>
import axios from 'axios'
export default {
  name: 'App',
  methods:{
    getStudents(){
      axios.get('http://localhost:8080/students').then(
        response =>{
          console.log('请求成功了',response.data)
        },
        error=>{
          console.log('请求失败了',error.message)
        }
      )
    }
  },
}
</script>

<style>

</style>

vue.config.js

module.exports = {
    pages:{
        index:{
            entry:'src/main.js',
        },
    },
    lintOnSave:false,
    devServer: {
        proxy: 'http://localhost:5000'
      }
}

第二种配置代理
app.vue

<template>
  <div >
<button @click="getStudents">获取学生信息</button>
<button @click="getCars">获取汽车信息</button>

   </div>
</template>

<script>
import axios from 'axios'
export default {
  name: 'App',
  methods:{
    getStudents(){
      axios.get('http://localhost:8080/atguigu/students').then(
        response =>{
          console.log('请求成功了',response.data)
        },
        error=>{
          console.log('请求失败了',error.message)
        }
      )
    },
    getCars(){
      axios.get('http://localhost:8080/demo/cars').then(
        response =>{
          console.log('请求成功了',response.data)
        },
        error=>{
          console.log('请求失败了',error.message)
        }
      )
    }
  },
}
</script>

<style>

</style>

vue.config.js

module.exports = {
    pages:{
        index:{
            entry:'src/main.js',
        },
    },
    lintOnSave:false,
    devServer: {
        proxy: {
          '/atguigu': {
            target: 'http://localhost:5000',
            pathRewrite:{'^/atguigu':''},
           /*  ws: true,  //用于支持websocket
            changeOrigin: true */
          },
          '/demo':{
            target:'http://localHost:5001',
            pathRewrite:{
                '^/demo':''
            },
          }
          /* '/foo': {
            target: '<other_url>'
          } */
        }
      }
}

在这里插入图片描述
github案例
List.vue

<template>
    <div class="row">
		<!-- 展示用户列表 -->
		<div v-show="info.users.length" class="card" v-for="user in info.users" :key="user.login">
			<a :href="user.html_url" target="_blank">
				<img :src="user.avatar_url" style='width: 100px'/>
			</a>
			<p class="card-text">{{user.login}}</p>
		</div>
		<!-- 展示欢迎词 -->
		<h1 v-show="info.isFirst">欢迎使用!</h1>
		<!-- 展示加载中 -->
		<h1 v-show="info.isLoading">加载中....</h1>
		<!-- 展示错误信息 -->
		<h1 v-show="info.errMsg">{{info.errMsg}}</h1>
	</div>
</template>

<script>
    export default {
        name:'List',
        data(){
            info:{
				return{
				isFirst:true,
				isLoading:false,
				errMsg:'',
                users:[]
            }
			}
        },
		mounted(){
			/* this.$bus.$on('getUsers',(isFirst,isLoading,errMsg,users)=>{
				console.log('我是List组件',users)
				this.isFirst=isFirst
				this.isLoading=isLoading
				this.errMsg=errMsg
				this.users=users
			}) */
			this.$bus.$on('updateListDate',(dataObj)=>{
				this.info={
					...this.info,...dataObj
				}
				console.log(this)
			})
			/* this.$bus.$on('getFirst',(isFirst)=>{
				this.isFirst=isFirst
			}) */
		},
    }
</script>

<style>

</style>

Search.vue

<template>
	<section class="jumbotron">
		<h3 class="jumbotron-heading">Search Github Users</h3>
		<div>
			<input type="text" placeholder="enter the name you search" v-model="keyWord"/>&nbsp;
			<button @click="searchUsers">Search</button>
		</div>
	</section>
</template>

<script>
	import axios from 'axios'
	export default {
		name:'Search',
		data() {
			return {
				keyWord:''
			}
		},
		methods: {
			searchUsers(){
				//请求前更新List的数据
				this.$bus.$emit('updateListData',{isLoading:true,errMsg:'',users:[],isFirst:false})
				axios.get(`https://api.github.com/search/users?q=${this.keyWord}`).then(
					response => {
						console.log('请求成功了')
						//请求成功后更新List的数据
						this.$bus.$emit('updateListData',{isLoading:false,errMsg:'',users:response.data.items})
					},
					error => {
						//请求后更新List的数据
						this.$bus.$emit('updateListData',{isLoading:false,errMsg:error.message,users:[]})
					}
				)
			}
		},
	}
</script>

vue-resource
安装

npm i vue-resource

这个文档太长了,,,换个新文档写了

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

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

相关文章

【网络编程基础(一)】网络基础和SOCKET

这里写目录标题 1、网络三要素2、IPV4和IPV6区别3、网络交互3.1、交互模型图3.2、基础通信协议3.3、OSI参考模型与TCP/IP参考模型对应关系 4、SOCKET网络套接字4.1、SOCKET分类4.2、基于流式套接字的编程流程4.3、网络通信雏形4.4、socket函数4.4.1、socket函数示例 4.5、bind函…

小红书图片怎么提取?小红书图片提取原图方法!

说到小红书&#xff0c;不少女性群体都知道这个&#xff0c;他的价值很高而且变现对于大多数做自媒体的小伙伴来说&#xff0c;也是不错的选择&#xff01; 小红书对于普通大众还是互联网创作者来说&#xff0c;都太实用了&#xff0c;唯一的缺点可能就是当我们需要存储他的图…

计算机设计大赛 题目:基于深度学习卷积神经网络的花卉识别 - 深度学习 机器视觉

文章目录 0 前言1 项目背景2 花卉识别的基本原理3 算法实现3.1 预处理3.2 特征提取和选择3.3 分类器设计和决策3.4 卷积神经网络基本原理 4 算法实现4.1 花卉图像数据4.2 模块组成 5 项目执行结果6 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基…

基于springboot+vue实现药品信息管理系统项目【项目源码+论文说明】

基于springbootvue实现药品信息管理系统演示 摘要 本文介绍了一种基于SpringBoot的药品信息管理系统的设计与实现。该系统旨在提高药品管理的效率和准确性&#xff0c;包括药品信息的录入、修改、查询和删除、药品入库、出库等功能。该系统采用了SpringBoot框架、MySQL数据库、…

如何快速搭建物联网工业云平台

随着物联网技术的快速发展&#xff0c;物联网工业云平台已经成为推动工业领域数字化转型的重要引擎。合沃作为专业的物联网云服务提供商&#xff0c;致力于为企业提供高效、可靠的物联网工业云平台解决方案。本文将深入探讨物联网工业云平台的功能、解决行业痛点的能力以及如何…

用户数据的FLASH存储与应用(FPGA架构)

该系列为神经网络硬件加速器应用中涉及的模块接口部分&#xff0c;随手记录&#xff0c;以免时间久了遗忘。 一 背景 我们知道&#xff0c;在FPGA做神经网络应用加速时&#xff0c;涉及到权重参数的存储和加载。通常在推理过程中&#xff0c;会将权重参数存储在外部DDR或片上S…

WAAP全站防护是什么,有什么作用

WAAP全站防护是基于风险管理和WAAP理念打造的安全方案&#xff0c;以“体系化主动安全” 取代安全产品的简单叠加&#xff0c;为各类Web、API业务等防御来自网络层和应用层的攻击&#xff0c;帮助企业全面提升Web安全水位和安全运营效率。 主要的特性在于&#xff1a; 1.全周…

19双体系Java学习之数组的Arrays类

数组的Arrays类 ★小贴士 sort方法对数组进行排序&#xff0c;方法调用完成后&#xff0c;数组按升序排列。 binarySearch方法对数组进行二分查找&#xff0c;如果能找到需要查找的元素则返回该元素的下标&#xff0c;否则返回一个负数&#xff0c;详见binarySearch的范例代码。…

CSS:mix-blend-mode 颜色混合

一、属性 mix-blend-mode: normal; //正常 mix-blend-mode: multiply; //正片叠底 mix-blend-mode: screen; //滤色 mix-blend-mode: overlay; //叠加 mix-blend-mode: darken; //变暗 mix-blend-mode: lighten; //变亮 mi…

取钱——动态规划

题目链接&#xff1a;1.取钱 - 蓝桥云课 (lanqiao.cn) 用动态规划的方法&#xff0c;定义一个dp数组&#xff0c;存放从0开始的取钱所需要的钞票数&#xff08;0就是取0元&#xff0c;所以钞票数也是0&#xff09; package lanqiao;import java.util.Arrays; import j…

AI视频混剪定时发送|罐头鱼AI视频矩阵获客

AI视频混剪定时发送系统&#xff1a;智能化视频创作与发布一体化解决方案 随着数字内容的快速增长&#xff0c;视频已成为各行业推广和传播的首选方式。然而&#xff0c;许多人在制作高质量视频时面临挑战。现在&#xff0c;有了全新的AI视频混剪定时发送系统&#xff0c;您可以…

二叉树OJ练习

本文旨在讲解有关二叉树的OJ题目&#xff0c;希望读完本文&#xff0c;能让读者都二叉树有更深一步的认识&#xff01; 正文开始&#xff01; 106. 根据二叉树创建字符串 算法思想&#xff1a; 根据题目的输出结果&#xff0c;可以观察出如下规律&#xff01; 1.若左右结点都…

MySQL语法分类 DDL(2)

DDL&#xff08;2&#xff09; C(Create):创建 //复制表 create table 表名 like 被复制的表名;//数据类型 1. int : 整数类型 2. double : 小数类型 //double(5,2) 最多五位且保留两位小数 3. date : 日期类型 //只包含年月日 yyyy-MM-dd 4. datetime : 日期 //包含年月日时…

影像质感再升级:JOEL FAMULARO Phantom LUTs让作品焕然一新

JOEL FAMULARO Phantom LUTs是一套专业的电影级别的预设&#xff0c;旨在为电影制作人和视频编辑人员提供高质量的颜色校正和调整工具。它为用户提供了一系列精心设计的色彩预设&#xff0c;旨在帮助摄影师在电影、电视和照片后期制作中快速实现专业且一致的色彩风格。这些预设…

(含代码)利用NVIDIA Triton加速Stable Diffusion XL推理速度

在 NVIDIA AI 推理平台上使用 Stable Diffusion XL 生成令人惊叹的图像 扩散模型正在改变跨行业的创意工作流程。 这些模型通过去噪扩散技术迭代地将随机噪声塑造成人工智能生成的艺术&#xff0c;从而基于简单的文本或图像输入生成令人惊叹的图像。 这可以应用于许多企业用例&…

整型溢出问题及解决之道

【题目描述】 例题2-2 3n&#xff0b;1问题 猜想&#xff1a;对于任意大于1的自然数n&#xff0c;若n为奇数&#xff0c;则将n变为3n&#xff0b;1&#xff0c;否则变为n的一半。 经过若干次这样的变换&#xff0c;一定会使n变为1。例如&#xff0c;3→10→5→16→8→4→2→…

基于Spring Boot+Vue的校园二手交易平台

目录 一、 绪论1.1 开发背景1.2 系统开发平台1.3 系统开发环境 二、需求分析2.1 问题分析2.2 系统可行性分析2.2.1 技术可行性2.2.2 操作可行性 2.3 系统需求分析2.3.1 学生功能需求2.3.2 管理员功能需求2.3.3游客功能需求 三、系统设计3.1 功能结构图3.2 E-R模型3.3 数据库设计…

【蓝桥杯每日一题】填充颜色超详细解释!!!

为了让蓝桥杯不变成蓝桥悲&#xff0c;我决定在舒适的周日再来一道题。 例&#xff1a; 输入&#xff1a; 6 0 0 0 0 0 0 0 0 1 1 1 1 0 1 1 0 0 1 1 1 0 0 0 1 1 0 0 0 0 1 1 1 1 1 1 1 输出&#xff1a; 0 0 0 0 0 0 0 0 1 1 1 1 0 1 1 2 2 1 1 1 2 2 2 1 1 2 2 2 2 1 1…

Requests教程-17-请求代理设置

上一小节我们学习了requests解决乱码的方法&#xff0c;本小节我们讲解一下requests设置代理的方法。 代理基本原理 代理实际上指的就是代理服务器&#xff0c; 英文叫作proxy server &#xff0c;它的功能是代理网络用户去取得网络信息。形象地说&#xff0c;它是网络信息的中…

【DFS深度优先搜索专题】【蓝桥杯备考训练】:迷宫、奶牛选美、树的重心、大臣的旅费、扫雷【已更新完成】

目录 1、迷宫&#xff08;《信息学奥赛一本通》&#xff09; 2、奶牛选美&#xff08;USACO 2011 November Contest Bronze Division&#xff09; 3、树的重心&#xff08;模板&#xff09; 4、大臣的旅费&#xff08;第四届蓝桥杯省赛Java & C A组&#xff09; 5、扫…