Vue学习笔记

目录

Vue简介

​编辑

第一个vue程序

el挂载点

data数据对象

el和data的两种写法

MVVM

Vue指令

v-text和v-html

v-on

v-show

v-if

v-bind

v-for

v-for中:key的作用原理

v-model

记事本案例

axios网络请求库

1、安装

2、使用,作一个音乐播放器

vue数据代理

computed计算属性

watch监视属性

Vue生命周期

创建之前和创建之后

挂载之前和挂载之后

更新之前和更新之后

销毁之前和销毁之后

Vue的组件

组件的使用

VueComponent

Vue脚手架

使用脚手架创建项目

项目的目录结构

ref属性 与 props配置对象

ref属性

 props配置对象

Vue收集表单数据

Todo-list 案例(组件开发流程)

1.实现静态组件:

2.展示动态数据:

3.交互——从绑定事件监听开始


Vue简介

Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架

版本有vue2和vue3

大纲

vue基础

第一个vue程序

{{xxx}}xxx只能写js表达式(就是这个表达式最后解析后返回一个值的),xxx会到data中识别所有属性。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>hello world-vue</title>

    <!-- 引入vue.js,开发环境版本,包含了有帮助的命令行警告 -->
    <!-- <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script> -->
    <script src="../js/vue.js"></script>
</head>

<body>

    <!-- 一个模板 -->
    <div id="app">
        {{ message }}
    </div>
    

    <script>
        Vue.config.productionTip = false;

        // 创建一个Vue实例
        var app = new Vue({
            // el:'元素选择器' 将new的Vue实例和Dom元素绑定起来,设置vue实例的挂载点,指定这个Vue实例为谁服务
            el: '#app',

            // data中用于定义数据,数据供Vue服务的模板使用。
            data: {
                message: 'hello world!'
            }
        })
    </script>
</body>
</html>

这边要注意vue.js的引入位置,需要在用到vue之前执行,也就是要在new Vue前执行,我第一次放在后面导致vue is not defined报错。

Vue指令

v-text和v-html

vue-cli

vue-router

vuex

element-ui

vue3

----------------------------

el挂载点

语法                 el:'元素选择器'

作用                将new的Vue实例和Dom元素绑定起来,设置vue实例的挂载点

作用范围        vue实例只作用于其挂载的的元素以及后代元素。

data数据对象

vue实例的挂载元素中如果有{{}}的话,会被解析并将data对象中的数据渲染进去。

会解析上面的html,一旦解析到有vue的语法,就会自动按照vue的语法将data中的数据渲染进去。

<body>
    <div id="app">
       <b>一名屌丝的基本信息</b><br>
       在干嘛:{{message}}<br>
       院校信息:{{school.name}} <br>
       爱好:{{interest[1]}}
    </div>

    <script>
        var app = new  Vue({
            el:"#app",

            data:{
                // 基本数据类型
                message:"学vue第一天",

                // 对象
                school:{
                    name:"莆田学院",
                    address:"莆田市城厢区",
                    phone:"18120997089"
                },

                // 数组
                interest:["跑步",3,"乒乓球","打游戏"]
                
            }
        })
    </script>
</body>

el和data的两种写法

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    
    <!-- 引入vue.js,开发环境版本,包含了有帮助的命令行警告 -->
    <script src="../js/vue.js"></script>
</head>
<body>
    <div id="app">
        <h2>{{hello}}</h2>
    </div>

    <script>
        /* // el挂载的两种写法,这两种写法都可以
        var app = new Vue({
            // 第一种写法
            // el:"#app",
            data:{
                hello:"how are you"
            }
        })

        // 第二种写法 mount挂载
        app.$mount("#app"); */

        // data的两种写法
        var app = new Vue({
            
            el:"#app",
            // 第一种写法:对象式
            // data:{
            //     hello:"how are you"
            // }

            // 第二种写法:函数式,函数的返回值就是data种的属性
            // 以后学到组件后,data必须用函数式,由Vue管理的函数,一定不能用箭头函数,否则this就不是代表vue实例了.
            data(){
                return{
                    hello:"data函数式"
                }
            }
        })
    </script>
</body>
</html>

MVVM

将数据都定义在Model中,View和Model进行数据绑定后,Model中的数据一旦变化,View中有用到data的地方,都会随之发生改变。

View中的一些数据发送改变,也会改变Model中的数据,如v-model。`

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    
    <!-- 引入vue.js,开发环境版本,包含了有帮助的命令行警告 -->
    <script src="../js/vue.js"></script>
</head>
<body>
    <!-- 
        MVVM
        Model:模板,代表Vue实例中的data数据
        View:视图,就是我们写的html和css页面
        ViewModel:视图模型,就是我们的Vue实例

        MVVM模型
        1. M:模型(Model) : data中的数据
        2. V: 视图(View) :模板代码
        3. VM: 视图模型(ViewModel): Vue实例
        观察发现:
        1. data中所有的属性,最后都出现在了vm身上。)
        2.vm身上所有的属性及Vue原型上所有属性,在Vue模板中都可以直接使用。
     -->

     <!-- view视图 -->
     <div id="app">
        名字:{{name}}
        <br>
        地址:{{address}}
     </div>

     <script>
        // 
        var vm = new Vue({
            el:"#app",
            data:{
                name:"莆田学院",
                address:"学园中街1103号"
            }
        })

        console.log("vm",vm)
     </script>
</body>
</html>

Vue指令

v-text和v-html

<body>
    <!-- 
        v-text 会将标签体的内容全部替换掉,而且只能原封不动的将data中的数据替换标签体,
        若只想替换部分内容可以用vue的插值语法{{}}

        v-html 也是将标签体中的内容全部替换掉,但是如果data数据中有
                html内容,会先解析好后再替换标签体内容。
     -->

    <div id="app">
        <h1 v-text="message+'!'">一段文本</h1>
        <h2>{{info+"!"}}一段文本</h2>

        <p v-html="content">wen</p>
        <p v-text="content">wen</p>
    </div>

    <script>
        var vue = new Vue({
            el:"#app",

            // 准备一些数据
            data:{
                message:"hello",
                info:"内容",

                content:"<a href='https://www.baidu.com/'>百度</a>"
            }
        })
    </script>
    
</body>

v-on

<body>
    <!-- 
        v-on:事件名="方法名"    指令可以给元素绑定事件,当事件触发后,会执行方法。
        v-on: 可替换为@

        v-on:click  单击事件
     -->
    <div id="app">
        <input type="button" value="提交" v-on:click="method1"></input>

        <p v-on:click="showTime">{{time}}</p>
    </div>


    <script>
        var vue = new Vue({
            el: "#app",

            data: {
                time: "点击查看时间"
            },

            // 定义方法
            methods: {
                method1: function () {
                    alert("你要加油!");
                    console.log("数据:"+this.time);
                },

                showTime: function () {
                    // this可以获取到data对象,this.数据名可以操作数据内容,从而改变dom中的内容,不用像以前操作dom元素来修改内容。
                    var t = new Date();
                    this.time = t;
                }
            }
        })
    </script>

</body>

v-on的补充

<body>

    <!-- 
        v-on:事件名='方法名' 
        对v-on事件绑定的补充:
        1.我们可以给事件触发的方法传参数,前提是在方法的定义处需要定义形参来接收我们的实参.
        2.事件修饰符
         @keyup.enter
         @keyup是键盘事件, .enter给事件添加修饰符,就是当回车时才触发,通过'.xxx'来添加事件修饰符.

     -->
    <div id="app">
        <input type="text"  @keyup.enter="login('小明')">
        <button>登录</button>
    </div>

    <script>
        var app = new Vue({
            el:"#app",
            data:{

            },
            methods:{
                login(userName){
                    alert(userName + "登录成功");
                }
            }
        })
    </script>
</body>

v-show

<body>
    <!-- 
        当v-show后面的表达式值为true时,才显示标签元素,否则隐藏。
        表达式可以直接取到data中的数据。
        这个原理是操作标签的样式:style="display: none;" 实现元素的隐藏。
     -->

    <div id="app">
        <div>
            <img src="../img/monkey.png" v-show="isShow==true">
        </div>
        
<br>
        <button @click="showChange">按我</button>
    </div>

    <script>
        var vue = new Vue({
            el:"#app",
            data:{
                isShow:true
            },
            methods:{
                showChange:function(){
                    this.isShow = !this.isShow;
                }
            }
        })
    </script>
    
</body>

v-if

<body>
    <!-- 
        v-if 和v-show效果一样,都是当表达式的值为true时,才显示。
        
        但是原理不同,v-if是直接操作dom树,删除或添加元素到dom树中。
        当频繁切换显示,使用v-show,v-if直接操作dom树,开销大。
     -->
    <div id="app">
        <span v-if="temp > 3">hello </span>
        <button v-on:click="add">切换显示状态</button>
    </div>

    <script>
        var vue = new Vue({
            el: "#app",
            data: {
                temp: 2
            },
            mehtods: {
                add: function () {
                    this.temp++;
                    console.log(this.temp);
                }
            }
        })
    </script>
</body>

v-bind

<body>
    <!-- 
        v-bind 可以给标签的属性绑定一个data对象中的数据,从而控制标签的属性。
        v-bind 可以省略
    -->

    <div id="app">
        <img v-bind:title="imgTitle" src="http://tva2.sinaimg.cn/large/83e2e207jw1fchpgbeyg8j21c00u0dkb.jpg"
            class="imgStyle" />
        <br>
        <!-- <span v-bind:class="{isActive:textL}">一段文本</span> -->

        <!-- isActive为真才取textL值 -->
        <span v-bind:class="{textL:isActive}" @click="changeClass">一段文本</span>
    </div>


    <script>
        var app = new Vue({
            el: "#app",
            data: {
                imgTitle: "你的名字",
                isActive: true
            },
            methods: {
                changeClass: function () {
                    this.isActive = !this.isActive;
                }
            }
        })
    </script>

</body>

v-for

<body>
    <!-- 
        1.v-for="item in items" 会遍历整个items,item代表每一个数据遍历项.
          v-for="(item,index) in items" item表示每一个数据遍历项,index代表索引值.
        2.v-for作用的标签,有几个遍历项,标签就渲染几次.
        3.使用{{}}插值语法来取数据.
     -->
    <div id="app">
        <h4>周末做什么:</h4>
        <ol>
            <li v-for="todo in todos">{{todo}}</li>
        </ol>

        <h4>无序列表:</h4>
        <ul>
            <li v-for="(item,index) in users" v-bind:title="item.age">
                {{index}} --> {{item.name}}
            </li>
        </ul>

        <button @click="addUser">添加用户</button>
        <button @click="minusUser">减少用户</button>
    </div>

    <script>
        var app = new Vue({
            el: "#app",
            data: {
                // 基本数组
                todos: [
                    "吃饭",
                    "睡觉",
                    "打游戏",
                    "看剧"
                ],

                // 对象数组
                users: [
                    { name: "小明", age: 23 },
                    { name: "小花", age: 21 },
                    { name: "明华", age: 33 }
                ]
            },
            methods:{
                addUser(){
                    this.users.push({name:"某某",age:24})
                },
                minusUser(){
                    this.users.shift();
                }
            }
        })
    </script>
</body>

v-for中:key的作用原理

v-for="(item,index) in items" :key=index,用遍历的索引值作为key

:key会作为遍历项的一个属性出现,存在于虚拟dom中,真实dom看不见,用index的话,假如你是从数据数组的头加入新数据老刘,就会生成以下新的dom,会拿着key=0去和旧的虚拟dom比对,找到一样的key后,看这个值不一样,就不能复用旧的虚拟dom,就用老刘-30,但是输入框一样,就复用旧的了,张三-18。用index作为key,就会出现这样比对错乱的问题。所以最好用下面数据自身的id作为key标识。

如果不写:key=xxx的话,Vue默认是用遍历的索引index。

v-for="item in items" :key=item.id ,用元素自身的id标识

v-model

<body>

    <!-- 
        v-model用于表单元素和vue数据对象的双向绑定
        1.v-model只能用于表单元素,常见的表单元素有:input(text,button,radio...),select,checkbox...
          v-model双向绑定,vue数据和表单元素数据两者相互影响.
        2.v-bind只是单向绑定,vue数据改变才会改变属性数据,属性数据改变不影响vue数据.
     -->
     <div id="app">
        <!-- <span v-model="message"></span> -->
        <input type="text" v-model="message" @keyup.enter="showData">

        <input type="text" v-bind:value="message" @keyup.enter="showData">
     </div>

     <script>
        var app = new Vue({
            el:"#app",
            data:{
                message:"默认文本"
            },
            methods: {
                showData() {
                    alert("vue实例中的数据:" + this.message);
                },
            },
        })
     </script>
</body>

记事本案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>记事本</title>
    
    <!-- 引入vue.js,开发环境版本,包含了有帮助的命令行警告 -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
    <style>
        .w{
            padding-left: 26‒;
            margin-left: 38px;
        }
    </style>
</head>
<body>
    <div id="app">
        <h2>小菜鸡记事本</h2>
        <!-- v-model和输入框的value属性绑定,可以用于获取用户的输入. -->
        <input type="text" placeholder="请输入任务" @keyup.enter="addItem()" v-model="inputValue">
        <ul>
            <li v-for="(item,index) in items" @mouseenter="floatDelete" @mouseleave="hideDelete">
               {{index+1+'.'}} {{item}}
               <span v-show="isDelete" @click="deleteItem(index)">x</span>
            </li>

            
        </ul>
        <span v-show="items.length != 0">{{items.length}} items left</span>    <span v-show="items.length != 0" class="w" @click="clear">clear</span>
    </div>
    
    <script>
        var app = new Vue({
            el:"#app",
            data:{
                items:[
                    "吃饭",
                    "睡觉",
                    "打游戏"
                ],
                inputValue:"",
                isDelete:false,
                total: 3
            },
            methods:{
                addItem(){
                    console.log("inputValue:"+this.inputValue);
                    this.items.push(this.inputValue);
                    this.inputValue = "";
                    // console.log("inputValue:"+this.inputValue);
                },
                floatDelete:function(){
                    
                    this.isDelete = true;
                },
                hideDelete(){
                    this.isDelete = false;
                },
                deleteItem(index){
                    this.items.splice(index,1);
                    this.total = this.items.length;
                    if(this.items.length == 0){
                        this.isDelete = false;
                    }
                },
                clear(){
                    this.items.splice(0);
                }
            }
        })
    </script>
</body>
</html>

axios网络请求库

是一个网络请求库,我的理解就是向后台发送请求,返回自己需要的资源。

1、安装

方式一:使用npm下载axios依赖

npm install axios

方式二:在线导入(要保证联网)

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

2、使用,作一个音乐播放器

两种常用的请求:GET POST

axios.get(地址?参数列表).then(function(response){},function(err){})

请求成功则执行前面的函数        失败执行后面的函数

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <meta http-equiv="X-UA-Compatible" content="ie=edge" />
  <title>悦听player</title>
  <!-- 样式 -->
  <link rel="stylesheet" href="./css/index.css">
  <!-- 开发环境版本,包含了有帮助的命令行警告 -->
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <!-- 官网提供的 axios 在线地址 -->
  <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>

<body>
  <div class="wrap">
    <!-- 播放器主体区域 -->
    <div class="play_wrap" id="player">
      <div class="search_bar">
        <img src="images/player_title.png" alt="" />
        <!-- 搜索歌曲 -->
        <input type="text" autocomplete="off" v-model="key" @keyup.enter="search" />
      </div>
      <div class="center_con">
        <!-- 搜索歌曲列表 -->
        <div class='song_wrapper'>
          <ul class="song_list">
            <li v-for="song in songs"><a href="javascript:;" @click="play(song.id,song.al.picUrl)"></a>
              <b>{{song.name}}</b> 
              <span><i v-if="song.mv > 0"><img src="./images/mv.png" @click="playMv(song.mv)"></i></span>
            </li>
            <!-- <li><a href="javascript:;"></a> <b>你好</b> <span><i></i></span></li> -->
          </ul>
          <img src="images/line.png" class="switch_btn" alt="">
        </div>
        <!-- 歌曲信息容器 -->
        <div class="player_con" :class="{playing:isPlay}">
          <img src="images/player_bar.png" class="play_bar" />
          <!-- 黑胶碟片 -->
          <img src="images/disc.png" class="disc autoRotate" />
          <img v-bind:src="songPicUrl" class="cover autoRotate" />
        </div>
        <!-- 评论容器 -->
        <div class="comment_wrapper">
          <h5 class='title'>热门留言</h5>
          <div class='comment_list'>
            <dl>
              <dt><img src="./images/person.png" alt=""></dt>
              <dd class="name">盐焗西兰花</dd>
              <dd class="detail">
                绝对值得一听,吹爆
              </dd>
            </dl>
          </div>
          <img src="images/line.png" class="right_line">
        </div>
      </div>
      <div class="audio_con">
        <audio ref='audio' @play="doPlay" @pause="pause" v-bind:src="songUrl" controls autoplay loop
          class="myaudio"></audio>
      </div>
      <div class="video_con" v-show="mvUrl != ''">
        <video controls="controls" :src="mvUrl"></video>
        <div class="mask" @click="closeMv"></div>
      </div>
    </div>
  </div>


  <script src="./js/main.js"></script>
</body>

</html>

var app = new Vue({
    el:"#player",
    data:{
        key:"",
        songs:[],
        songUrl:"",
        songPicUrl:"",
        isPlay:false,
        mvUrl:""
    },
    methods:{
        // 查询歌曲
        search(){
            var that = this;

            axios.get("https://autumnfish.cn/cloudsearch?keywords="+this.key)
            .then(function(response){
                console.log(response.data.result.songs);
                that.songs = response.data.result.songs;
            },function(err){})
        },

        // 获取歌曲播放url
        play(id,url){
            this.songUrl = "https://music.163.com/song/media/outer/url?id="+id+".mp3";
            this.songPicUrl = url;
        },

        doPlay(){
            this.isPlay = true;
        },
        pause(){
            this.isPlay = false;
        },

        playMv(mvId){
            var that = this;
            axios.get("https://autumnfish.cn/mv/url?id="+mvId).then(function(response){
                console.log(response.data.data.url)
                that.mvUrl = response.data.data.url;
            })
        },

        closeMv(){
            this.mvUrl = "";
        }
    }
})

vue数据代理

computed计算属性

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    
    <!-- 引入vue.js,开发环境版本,包含了有帮助的命令行警告 -->
    <script src="../js/vue.js"></script>
</head>
<body>
    <!-- 
        计算属性computed,可以动态的计算出一个属性供我们使用。
     -->

     <div id="app">
        姓:<input type="text" v-model="firstName"> <br>
        名:<input type="text" v-model="lastName"> <br>
        全名:<span>{{fullName}}</span><br>
        全名:<span>{{fullName}}</span><br>
        全名:<span>{{fullName}}</span><br>

     </div>

     <script>
        var vm = new Vue({
            el:"#app",
            data:{
                firstName:"张",
                lastName:"三"
            },
            // 全名我们我通过姓和名计算出来。
            computed:{
                // fullName是要被计算的属性名。:{}因为要计算,可能比较复杂,所以用一个配置对象
                fullName:{
                    // 所有 getter 和 setter 的 this 自动地绑定为 Vue 实例。但是如果用箭头函数的话,this就不是vue实例了

                    // get()方法的返回值作为计算属性的值,且值会被缓存起来,计算所依赖的属性值发生变化会重新计算。
                    // get()方法调用时间:计算属性第一次读取.计算所依赖的属性值发生变化
                    get(){
                        console.log("getter");
                        return this.firstName + "-" + this.lastName;
                    },
                    
                    // 当计算属性一被修改就调用,且会接收修改的新值
                    set(value){
                        console.log("setter",value.split('-'));

                        var arr = value.split('-');
                        this.firstName = arr[0];
                        this.lastName = arr[1];
                    }
                }
            }
        })
     </script>

</body>
</html>

watch监视属性

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <!-- 引入vue.js,开发环境版本,包含了有帮助的命令行警告 -->
    <script src="../js/vue.js"></script>
</head>

<body>
    <div id="app">
        <h2>今天天气是{{weather}}</h2><br>
        <input type="button" value="点我切换天气" @click="change">

        <hr>
        <h2>深度监视</h2>
        <span>a的值:{{numbers.a}}</span> <input type="button" value="a++" @click="numbers.a++"><br>
        <span>d的值:{{numbers.c.d}}</span> <input type="button" value="d++" @click="numbers.c.d++">
    </div>

    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                ishtot: true,
                numbers:{
                    a:1,
                    b:2,
                    c:{
                        d:2
                    }
                }
            },
            methods: {
                change() {
                    this.ishtot = !this.ishtot;
                }
            },
            computed: {
                weather: {
                    get() {
                        return this.ishtot ? "大太阳" : "多云";
                    }
                }
            },

            // watch监视属性
            watch: {
                // ishot要监视的属性
                ishtot: {
                    // 是否初始化时就调用handler方法.true的话,没等监视的属性变化就调用handler
                    immediate: true,

                    // handler方法在被监视的属性变化时就会被调用.
                    handler(old, newValue) {
                        console.log("ishot改变了", old, newValue);
                    }
                },
                'numbers.a':{
                    handler(){
                        console.log("numbers中的a属性改变了..")
                    }
                },

                // 深度监视
                'numbers':{
                    // 是否深度监视.默认只监视外层属性,想要监视内部属性,要深度监视.
                    deep:true,
                    handler(){
                        console.log("numbers发生改变");
                    }
                }
            }
        })

        // 另一种写法
        // vm.$watch("ishtot", {
        //     // handler方法在被监视的属性变化时就会被调用.
        //     handler(old, newValue) {
        //         console.log("另一种写法:ishot改变了", old, newValue);
        //     }
        // })

    </script>
</body>

</html>

Vue生命周期

创建之前和创建之后、挂载之前和挂载之后、更新之前和更新之后、销毁之前和销毁之后。

这边的模板指的是我们vue所挂载的节点中的所有元素内容。

<body>
    <div id="app">
        <h2>n的值: {{n}}</h2>
        <button @click="n++">n+1</button>
    </div>

    <script>
        var vm = new Vue({
        el:'#app',
        data:{
            n:1
        },
        methods:{
        }
        })
    </script>
</body>
这就是模板:
<h2>n的值: {{n}}</h2>
<button @click="n++">n+1</button>


 理解:

创建之前和创建之后

挂载之前和挂载之后

 

更新之前和更新之后

销毁之前和销毁之后

Vue的组件

为什么要学组件?

 什么是Vue组件?

组件就是页面中的用于实现局部效果的代码(htm、css、js)和资源(map3、mp4、ttl...)的集合。这个集合构成一个局部效果页面。

组件的好处:提高代码的复用率,哪里有个部分一样,直接引入即可。简化项目编码。

 

 

组件的使用

VueComponent

Vue的原型对象(Vue.prototype)上有这些东西,这些东西Vue实例对象vm和组件实例对象vc都可以访问到,当vm.属性/方法名()或vc.属性/方法名()执行的时候,会先在自己身上找这个属性或方法,如果没有,就会顺着线找到Vue的原型对象身上,就是下面这些。

Vue脚手架

使用脚手架创建项目

第一步(仅第一次执行):全局安装@vue/cli。

cmd命令行下输入命令:npm install -g @vue/cli

备注:如出现下载缓慢请配置 npm 淘宝镜像:npm config set registry https://registry.npm.taobao.org

第二步:切换到你要创建项目的目录,然后使用命令创建vue前端项目

vue create xxxx项目名

第三步:启动项目

npm run serve

项目的目录结构

ref属性 与 props配置对象

ref属性

1. 作用:用于给节点打标识,类似节点设置id属性,方便操作dom元素

2. 读取方式:this.$refs.xxxxxx

<template>
    <div>
        <!-- ref属性用在html标签属性上 -->
        <h1 ref="msg">{{msg}}</h1>

        <!-- ref属性用在组件标签上 -->
        <student ref="stu"></student>
        <button @click="showDOM">点我操作dom</button>
    </div>
</template>

<script>
    import Student from "./components/Student.vue"
    export default {
        name:"App",
        components:{Student},
        data() {
            return {
                msg: "学生",
            };
        },
        methods:{
            showDOM(){
                // 组件中的this代表组件实例对象VueComponent
                console.log(this.$refs.msg);
                console.log(this.$refs.stu);
            }
        }
        
    }
</script>

<style>

</style>

 props配置对象

作用:用于父组件给子组件传递数据,数据不再在组件的data中写死,父组件中传什么数据给子组件,子组件就展示什么数据。

背景:

    <div>
        <!-- 
            当组件的样式啥是固定的,但是里面展示的数据想要动态的传入的话,可以使用props配置对象.
            age="23"传的是字符串,要写成 v-bind:age="23" 或 :age="23" 属性绑定,才会传数字,因为23会被当成表达式.
         -->
         <!-- 付款方 -->
        <Student name="张三" sex="男" :age="23"></Student>
        <hr>
        <Student name="李四" sex="女" :age="26"></Student>

    </div>

Vue收集表单数据

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    
    <!-- 引入vue.js,开发环境版本,包含了有帮助的命令行警告 -->
    <script src="../js/vue.js"></script>
</head>
<body>
    <!-- 
        若:<input type="text"/>,则v-model收集的是value值,用户输入的就是value值。

  若:<input type="radio"/>,则v-mode收集的是value值,且要给标签配置value值,因为单选框无法再输入值了。

  若:<input type="checkbox"/>

    1、没有配置input的value属性,name(v-model)收集的就是checked(勾选 or 未勾选,是布尔值)

    2、配置input的value属性:

      (1)v-model的初始值是非数组,不是用数组收集,那么收集的就是checked(勾选 or 未勾选,是布尔值)

      (2)v-model的初始值是数组,用数组收集,那么收集的就是value组成的数组

  备注:v-model的三个修饰符:

      (1)lazy:失去焦点在收集数据

      (2)number:输入字符串转为有效的数字
            <input type="number" 是规定页面输入的时候只能输数字
            v-model.number="phone"> 这样vue就能自动将收集到的数字帮我们转为数值型

      (3)trim:输入首尾空格过滤
        
     -->

    <div id="app">
        <form action="" @submit.prevent="finish">
            账号: <input type="text" v-model.trim="account"> <br><br>
            密码: <input type="password" v-model="password" autocomplete> <br><br>
            电话: <input type="number" v-model.number="phone"> <br><br>
            
            性别: 
            男<input type="radio" name="sex" v-model="sex" value="male">
            女<input type="radio" name="sex" v-model="sex" value="female">
            <br><br>
            爱好: 
            看电影<input type="checkbox" v-model="hobby" value="film">
            打游戏<input type="checkbox" v-model="hobby" value="game">
            看妹子<input type="checkbox" v-model="hobby" value="beauty">
            <br><br>
            所属地区: 
            <select name="" id="" v-model="area">
                <option>请选择地区</option>
                <option>莆田</option>
                <option>福州</option>
                <option>泉州</option>
                <option>厦门</option>
            </select>
            <br><br>

            其他信息: 
            <textarea v-model.lazy="other">
            </textarea>
            <br><br>
            <input type="checkbox" v-model="agree">阅读并接受<a href="http:www.baidu.com">《用户协议》</a>

            <button>提交</button>
        </form>
    </div>

    <script>
        var vm = new Vue({
        el:'#app',
        data:{
            account:"",
            password:"",
            other:"",
            sex:"female",
            // hobby:""
            hobby:[],
            area:"",
            agree:false,
            phone:""
        },
        methods:{
            finish(){
                console.log(JSON.stringify(this._data));
            }
        }
        })
    </script>

</body>
</html>

Todo-list 案例(组件开发流程)

1.实现静态组件:

抽取组件,使用组件实现静态页面效果

拆分组件:可以按功能点拆分(组件是实现界面局部功能点的代码和资源的集合)

Header组件:具有输入任务名,和添加任务的功能。

List组件:具有展示任务的功能

        Item组件:具有勾选任务和删除任务的功能

Footer组件:具有展示已完成和全部任务数、还有删除完成的任务等交互功能

注意:当你分的组件,不好起名字时,说明可能你拆分的组件不合适,可以考虑重新拆分。 组件的命名不要和html元素一样。

2.展示动态数据:

2.1. 数据的类型、名称是什么?

类型考虑好,常用的:[{},{},{},{},....]。名称要做到见名知意。

2.2. 数据保存在哪个组件?

若数据只有某个组件自己用的,那么data数据就写在组件自身身上就可以。如果是几个组件一起用,那么将数据放在几个组件共同的父组件身上(方便组件通信用)。

3.交互——从绑定事件监听开始

组件的通信:

父组件==>子组件:父组件给子组件传递数据data、方法method等:可以用props传递。

子组件==>父组件:父组件要先使用props给子组件传递一个方法,然后子组件接收后,调用这个方法给父组件传递数据。

子组件==>子组件:现在只知道可以通过父组件这个中转站实现。

 webStorage(

Vue配置代理解决跨域请求

Vue中发送请求的几种方式

这边推荐使用axios,使用命令npm i axios安装一下

什么是跨域请求?

当前发起请求的域 与 所请求的资源 所在的域不一样,就是跨域请求。这里的域指的是这样的一个概念:我们认为如果协议 + 域名 + 端口号均相同,那么就是同域,否则则是跨域的

为了安全起见,浏览器设置了同源策略,当页面执行脚本的时候,浏览器会检查访问的资源是否同源,如果不是,就会报错。

如何解决跨域问题?

1、cors

2、jsonp

3、配置代理服务器(可以使用nginx配置一台代理服务器或使用vue-cli起一台代理服务器)

使用vue-cli配置代理服务器

在Vue.config文件中配置代理,修改完这个文件,记得重启项目才能生效

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  lintOnSave:false, /*关闭语法检查*/
  
  // 配置一个代理服务器(方式一)
/*   devServer: {
    // 这个配置的是要代理的请求要代发送给谁
    // 这种有两个不好的地方:只能配置一台要转发的服务器。如果本服务器上有和代理请求一样的资源名时,就不会走代理了,直接返回本服务器上同名的资源,不能灵活控制是否走代理。
    // public目录下就是本服务器上的资源.
    proxy: 'http://localhost:5000'
  } */

  // 配置一个代理服务器(方式二)
  devServer: {
    proxy: {
      // 当资源路径以 /stu 开头时,一定走代理
      '/stu': {
        // 告诉代理服务器请求发送给谁
        target: 'http://localhost:5000',
        // 代理请求路径重写,匹配路径http://localhost:8080/stu/students中的/stu改为''
        pathRewrite:{'^/stu':''},
        // 开启支持websocket
        ws: true,
        // 是否将请求的host和目标服务器的host保持一致
        changeOrigin: true
      },

      
      '/car': {
        target: 'http://localhost:5001',
        pathRewrite:{'^/car':''},

        // 以下两个配置在vue中默认是true
        // ws: true,
        // changeOrigin: true
      },
    }
  }


})

app组件

export default {
  name: "App",
  methods: {
    getStu() {
      // 发送请求获取学生信息
      axios.get("http://localhost:8080/stu/students").then(
        // 请求成功返回给你一个response对象
        response => {
          console.log("收到学生数据了:",response.data)
        },
        // 请求失败返回给你一个error对象
        error => {
          console.log("请求失败:",error.message)
        }
      )
    },
    getCars() {
      // 请求代理服务器,让他代发请求,解决跨域
      axios.get("http://localhost:8080/car/cars").then(
        response => {
          console.log("收到汽车数据了:",response.data)
        },
        error => {
          console.log("请求失败:",error.message)
        }
      )
    },
  },
};

Vuex

专门在 Vue 中实现集中式状态(数据)管理的一个 Vue 插件,对 vue 应 用中多个组件的共享状态(数据)进行集中式的管理(读/写),也是一种组件间通信的方 式,且适用于任意组件间通信。

什么时候用Vuex?

当多个组件共享一个数据时。

如何使用Vuex?

 

安装vuex3:npm i vuex@3

 store是管理Actions、Mutations和State三个的。

Vue中路由

Vue中的路由就是为了实现单页面应用,整个应用只有一个页面index.html,点击页面中的导航不会刷新页面,只会做页面的局部刷新,所需的数据通过Ajax请求回来。

一个路由就是一个请求路径对应一个组件的key-value键值对,key是路径,value是组件。

路由器是管理多个路由的。

当我们点击了学科管理后,地址栏地址变成xxx/subject,然后vue的router就会检测到路径的改变,于是乎去路由规则里面去找有没有对应的组件和/subject对应,如果有的话则展示学科组件。(这个路由规则是我们自己定的)

安装使用

vue2只能安装vue-router3的用,npm i vue-router@3

几个注意点

相关 API:

1. this.$router.push(path): 相当于点击路由链接(可以返回到当前路由界面)

2. this.$router.replace(path): 用新路由替换当前路由(不可以返回到当前路由界面)

3. this.$router.back(): 请求(返回)上一个记录路由

4. this.$router.go(-1): 请求(返回)上一个记录路由

5. this.$router.go(1): 请求下一个记录路由

编程式路由导航

不借助router-link标签实现路由,之前我们一直使用router-link标签实现路由,实质上最后会转为a标签让我们点击实现路由切换。

this.$router.push/replace直接指定要切换哪个路由

 pushShow(m){
      // push切换路由
      this.$router.push({
        path:'/home/message/detail',
        query:{
          id:m.id,
          title:m.title
        }
      })
    },
    replaceShow(m){
      // push切换路由
      this.$router.replace({
        name:'detail',
        query:{
          id:m.id,
          title:m.title
        }
      })
    }
  }
{
            // 如果请求路径是/home,则展示Home组件内容
            path:'/home',
            component:Home,

            // 二级路由,/home/xxx,二级路由路径不用加/,因为会自己加
            children:[
                {
                    path:'news',
                    component:News
                },
                {
                    path:'message',
                    component:Message,
                    children:[
                        {
                            name:'detail',
                            path:'detail',
                            component:Detail
                        }
                    ]
                },
            ]
        },

缓存路由组件

在要被缓存的组件外加keep-alive标签,属性include指定要缓存的组件名。如果不加include属性的话,只要在这个地方展示过的组件都会被缓存起来。

 

 两个关于路由的生命周期函数

activated(){} 路由切到当前组件且展示当前组件时执行,组件活了

deactivated(){} 路由切到其他组件且展示其他组件时执行,组件失活

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

躺着听Jay

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值