学习Vue及项目工程化


Vue

构建用户界面的渐进式框架
在这里插入图片描述

快速上手

创建一个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>
</head>
<body>

    <div class="box2">
        {{msg}}
    </div>

    <div class="box">
        {{count}}
    </div>

    <div id="app">
        <!-- 这里将来会编写一些用于渲染的代码逻辑 -->
        <h1>{{msg}}</h1>
        <a href="#">{{count}}</a>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>


    <script>
        //一旦引入VueJS核心包,在全局环境,就依赖Vue构造函数
        const app = new Vue({
            // 通过el配置选择器,指定Vue管理的是哪个盒子
            el: '#app',
            // 通过data提供数据
            data: {
                msg: 'Hello World',
                count: 666
            }
        })

    </script>

</body> 
</html>

插值表达式

<!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>
</head>
<body>

    <div id="app">
        <p>{{nickname}}</p>
        <p>{{nickname.toUpperCase()}}</p>
        <p>{{nickname + '你好'}}</p>
        <p>{{age >= 18 ? '成年' : '未成年'}}</p>
        <p>{{friend.name}}</p>
        <p>{{friend.desc}}</p>

        //不能使用
        <!-- <p title="{{nickname}}">我是p标签</p> -->

    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
    <script>
        const app = new Vue({
            el: '#app',
            data: {
                nickname: 'tony',
                age: 18,
                friend: {
                    name: 'jepson',
                    desc:'热爱学习Vue'
                }
            }
        })

    </script>





</body> 
</html>

Vue基本命令

v-html

在这里插入图片描述

v-show

v-show和v-if都可以做隐藏:
v-show主要用于频繁切换的地方,如购物车显示
v-if主要用于不频繁切换,如弹窗提示
在这里插入图片描述

v-if 和 v-else 和 v-else-if

<!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>
</head>
<body>

    <!-- 
        v-show底层原理:切换css的display:one 来控制显示隐藏
        v-if底层原理:根据判断条件控制元素创建和移除(条件渲染)
    -->

    <div id="app">
        <div v-html="msg"></div>  <!-- v-html解析特殊标签 -->

        <div v-show="flag" class="box">v-show控制</div>
        <div v-if="flag" class="box">v-if控制</div>


        <p v-if="gender === 1">性别:男</p>
        <p v-else>性别:女</p>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
    
    <script>
        const app = new Vue({
            el: '#app',
            data: {
                msg: 
                   '<a href="https://www.baidu.com" target="_blank">百度一下</a>',
                flag: false,
                gender: 2
            }
        })

    </script>
</body> 
</html>

v-on和@click函数调用

在这里插入图片描述

<!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>
</head>
<body>

    <div id="app">
        <button v-on:click="count--">-</button>
        <span>{{ count }}</span>
        <button v-on:click="count++">+</button>

        <br>
        <br>
        <button @click="fn">切换显示隐形</button>
        <h1 v-show="isShow">程序员</h1>

        <div class="box">
            <h3>小王自动贩卖机</h3>
            <button @click="buy(5)">可乐5元</button>
            <button @click="buy(10)">咖啡10元</button>
        </div>
        <p>银行卡余额:{{ money }}元</p>  

    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
    
    <script>
        const app = new Vue({
            el: '#app',
            data: {
                count: 100,
                isShow: true,
                money: 1000
            },
            methods: {
                fn() {
                    console.log('切换显示')
                    app.isShow = !app.isShow
                },
                buy (price) {
                    console.log('扣费')
                    this.money -= price
                }
            }
        })

    </script>

</body> 
</html>

v-bind

在这里插入图片描述

<!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>
</head>
<body>

    <div id="app">
        <img v-bind:src="imgUrl" v-bind:title="msg" alt="">
        <img :src="imgUrl" :title="msg" alt=""> <!-- 简写 -->
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
    
    <script>
        const app = new Vue({
            el: '#app',
            data: {
                imgUrl: './imgs/maven.jpg',
                msg: 'Maven Logo'
            }
        })
    </script>

</body> 
</html>

v-for

在这里插入图片描述

在这里插入图片描述

<!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>
</head>
<body>

    <div id="app">
        <h3>小王水果店</h3>
        <ul>
            <li v-for="(item, index) in list">
                {{ item }} - {{ index }}
            </li>
        </ul>

    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
    
    <script>
        const app = new Vue({
            el: '#app',
            data: {
                list: ['西瓜','苹果','鸭梨','榴莲']
            }
        })
    </script>

</body> 
</html>

案例–书架

<!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>
</head>
<body>

    <div id="app">
        <h3>小王的书架</h3>
        <ul>
            <!-- key给列表项添加唯一标识。便于Vue进行正确排序复用 -->
            <li v-for="(item, index) in booksList" ::key="item.id">
                <span>{{ item.name }}</span>
                <span>{{ item.author }}</span>
                <button @click="del(item.id)">删除</button>
            </li>
        </ul>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
    
    <script>
        const app = new Vue({
            el: '#app',
            data: {
                booksList: [
                    {id: 1, name: '《红楼梦》', author: '曹雪芹'},
                    {id: 2, name: '《西游记》', author: '吴承恩'},
                    {id: 3, name: '《三国演义》', author: '罗贯中'},
                    {id: 4, name: '《水浒传》', author: '施耐庵'}
                ]
            },
            methods: {
                del (id) {
                    //fillter不会删除原数组会把结果保存在新数组里,所以我们要把原数组重新赋值
                    this.booksList = this.booksList.filter(item => item.id !== id)
                }
            },
        })
    </script>

</body> 
</html>

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>
</head>
<body>

    <div id="app">
        <!-- v-model 数据和视图双向数据绑定 -->
        账号:<input type="text" v-model="username"> <br><br>
        密码:<input type="password" v-model="password"> <br><br>
        <button @click="login">登录</button>
        <button @click="reset">重置</button>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
    
    <script>
        const app = new Vue({
            el: '#app',
            data: {
                username: '',
                password: ''
            },
            methods: {
                login () {
                    console.log('登录');
                    console.log(this.username);
                    console.log(this.password);
                },
                reset () {
                    console.log('重置');
                    this.username = '';
                    this.password = '';
            }
        }
        })
    </script>

</body> 
</html>

功能总结

在这里插入图片描述

综合案例-小黑记事本

列表渲染

删除功能

添加功能

底部统计

清空

项目工程化

更换npm镜像

设置镜像源:npm config set registry https://registry.npmmirror.com

查看当前使用的镜像地址:npm config get registry

方式一:在网页是去创建

在命令行中,执行如下指令:

vue ui

方式二:在命令行里创建

在命令行中,执行如下指令:

npm init vue@latest

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

案例:文章搜索

在这里插入图片描述

main.js

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

createApp(App).use(router).mount('#app')

Api.vue

<!-- <script>
export default {
    data() {
        return {
            message: 'Hello, Vue 3!'
        }
    }
  }
</script> -->

<script setup>
  import { ref } from 'vue'
  //导入 Api.vue文件
  import ApiVue from './Api.vue'
  //导入 Article.vue文件
  import ArticleVue from './Article.vue'
  import ArticleVue1 from './Article1.vue'

  //调用ref函数,定义响应式数据
  const message = ref('Hello, Vue 3!')



</script>


<template>
  <h1>{{ message }}</h1>
  <!-- 导入并使用 Api.vue组件 -->
  <ApiVue />

  <!-- 导入并使用 Article.vue组件 -->
  <!-- <ArticleVue /> -->

  <!-- 导入并使用 Article1.vue组件 -->
  <ArticleVue1 />


</template>

<style>
  h1 {
    color: blue;
  }
</style>

Article.vue

<script setup>
import { ref } from 'vue'
import axios from 'axios'

//定义响应式数据 ref
const articleList = ref([]);

//发送异步请求,获取所有文章数据
axios.get('http://localhost:8080/product/findByCate?cate_id=1')
  .then(result => {
    // console.log(result.data);
    //把服务器响应的数据保存起来
    articleList.value = result.data.data;
  }).catch(err => {
    console.log(err);
  })

//定义响应式数据 searchConditions
const searchConditions = ref({
  name: ''
})

//定义search函数
const search = () => {
  //发送异步请求,根据条件查询文章数据
  axios.get('http://localhost:8080/product/findName', {
    params: {...searchConditions.value}}).then(result => {
    console.log(result.data);
    //把服务器响应的数据保存起来
    articleList.value = result.data.data;
  }).catch(err => {
    console.log(err);
  })
}

</script>


<template>
  <!-- <div>{{ articleList }}</div> -->
  <div>
    文章标题: <input type="text" v-model="searchConditions.name">
    文章分类: <input type="text" v-model="searchConditions.category">
    发布状态: <input type="text" v-model="searchConditions.state">
    <button v-on:click="search">搜索</button>
    <br />
    <br />
    <table border="1 solid" colspa="0" cellspacing="0">
      <tr>
        <th>文章标题</th>
        <th>分类</th>
        <th>发表时间</th>
        <th>状态</th>
        <th>操作</th>
      </tr>
      <tr v-for="(article, index) in articleList" :key="index">
        <td>{{ article.name }}</td>
        <td>{{ article.cate_id }}</td>
        <td>{{ article.create_time }}</td>
        <td>{{ article.sales_volume }}</td>
        <td>
          <button>编辑</button>
          <button>删除</button>
        </td>
      </tr>
    </table>
  </div>
</template>


优化

接口调用的js代码一般封装在.js文件中,并以函数的形式暴露给外部
article.js
import axios from 'axios'

//获取所有文章数据函数
export async function articleGetAllService() {
    //发送异步请求,获取所有文章数据
    //同步等待服务器响应的结果,并返回,async  await
    return await axios.get('http://localhost:8080/product/findByCate?cate_id=1')
        .then(result => {
            return result.data.data;
        }).catch(err => {
            console.log(err);
        })
}

//获取单个文章数据函数
export async function articleSearchService(conditions) {
    //发送异步请求,根据条件查询文章数据
    return await axios.get('http://localhost:8080/product/findName', {
        params: conditions
    }).then(result => {
        return result.data.data;
    }).catch(err => {
        console.log(err);
    })
}
Article1.vue
<script setup>
import { ref } from 'vue'
import { articleGetAllService, articleSearchService } from '@/api/article.js'; // 导入函数

//定义响应式数据 ref
const articleList = ref([]);

//获取所有文章数据
// let data = articleGetAllService();
// articleList.value = data;
//同步获取articleGetAllService的返回结果  async await
const getAllArticle = async function () {
    let data = await articleGetAllService();
    articleList.value = data;
}
getAllArticle();


//定义响应式数据 searchConditions
const searchConditions = ref({
    name: ''
})

//定义search函数
const search = async function() {
    //文章搜索
    let data = await articleSearchService({...searchConditions.value})
    articleList.value = data;
}


</script>


<template>
    <!-- <div>{{ articleList }}</div> -->
    <div>
        文章标题: <input type="text" v-model="searchConditions.name">
        文章分类: <input type="text" v-model="searchConditions.category">
        发布状态: <input type="text" v-model="searchConditions.state">
        <button v-on:click="search">搜索</button>
        <br />
        <br />
        <table border="1 solid" colspa="0" cellspacing="0">
            <tr>
                <th>文章标题</th>
                <th>分类</th>
                <th>发表时间</th>
                <th>状态</th>
                <th>操作</th>
            </tr>
            <tr v-for="(article, index) in articleList" :key="index">
                <td>{{ article.name }}</td>
                <td>{{ article.cate_id }}</td>
                <td>{{ article.create_time }}</td>
                <td>{{ article.sales_volume }}</td>
                <td>
                    <button>编辑</button>
                    <button>删除</button>
                </td>
            </tr>
        </table>
    </div>
</template>


定义一个变量,记录公共的前缀,baseURL

const baseURL = ‘http://localhost:8080’;
const instance = axios.create({baseURL})

instance.get(‘/product/findByCate?cate_id=1’)

拦截器 request.js

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

request.js
//定制请求的实例

//导入axios  npm install axios
import axios from 'axios';
//定义一个变量,记录公共的前缀  ,  baseURL
const baseURL = 'http://localhost:8080';
const instance = axios.create({baseURL})


//添加响应拦截器
instance.interceptors.response.use(
    result=>{
        return result.data.data;
    },
    err=>{
        alert('服务异常');
        return Promise.reject(err);//异步的状态转化成失败的状态
    }
)

export default instance;
article1.js
/* //导入axios  npm install axios
import axios from 'axios';
//定义一个变量,记录公共的前缀  ,  baseURL
const baseURL = 'http://localhost:8080';
const instance = axios.create({baseURL}) */

import request from '@/util/request.js'

export async function articleGetAllService() {
    return request.get('/product/findByCate?cate_id=1');

}

export async function articleSearchService(conditions) {
    return request.get('/product/findName', { params: conditions });
}

element

安装

首先查看自己安装vue的版本,输入vue -V

如果自己的vue版本是3.0以上说明需要引入的是element-ui plus而不是element-ui

Vue3

npm install element-plus --save
如果下载的时候还会报错,执行这条指令:npm install element-plus --save --legacy-peer-deps

Vue2

npm install --save element-ui
如果下载的时候还会报错,执行这条指令:npm install element-ui --save --legacy-peer-deps

快速上手

在这里插入图片描述

完整引入

main.js

import Vue from ‘vue’;
import ElementUI from ‘element-ui’;
import ‘element-ui/lib/theme-chalk/index.css’;
import App from ‘./App.vue’;

Vue.use(ElementUI);

new Vue({
el: ‘#app’,
render: h => h(App)
});

Button.vue
<template>
<el-row>
    <el-button>默认按钮</el-button>
    <el-button type="primary">主要按钮</el-button>
    <el-button type="success">成功按钮</el-button>
    <el-button type="info">信息按钮</el-button>
    <el-button type="warning">警告按钮</el-button>
    <el-button type="danger">危险按钮</el-button>
  </el-row>
  
  <el-row>
    <el-button plain>朴素按钮</el-button>
    <el-button type="primary" plain>主要按钮</el-button>
    <el-button type="success" plain>成功按钮</el-button>
    <el-button type="info" plain>信息按钮</el-button>
    <el-button type="warning" plain>警告按钮</el-button>
    <el-button type="danger" plain>危险按钮</el-button>
  </el-row>
  
  <el-row>
    <el-button round>圆角按钮</el-button>
    <el-button type="primary" round>主要按钮</el-button>
    <el-button type="success" round>成功按钮</el-button>
    <el-button type="info" round>信息按钮</el-button>
    <el-button type="warning" round>警告按钮</el-button>
    <el-button type="danger" round>危险按钮</el-button>
  </el-row>
  
  <el-row>
    <el-button icon="el-icon-search" circle></el-button>
    <el-button type="primary" icon="el-icon-edit" circle></el-button>
    <el-button type="success" icon="el-icon-check" circle></el-button>
    <el-button type="info" icon="el-icon-message" circle></el-button>
    <el-button type="warning" icon="el-icon-star-off" circle></el-button>
    <el-button type="danger" icon="el-icon-delete" circle></el-button>
  </el-row>
</template>

案例

环境准备

在这里插入图片描述

跨域

在这里插入图片描述

配置代理来解决跨域

在这里插入图片描述

在这里插入图片描述

优化axios响应拦截器

在这里插入图片描述

路由

在这里插入图片描述
在这里插入图片描述

子路由

在这里插入图片描述

Bug:前端没有接收token

Pinia状态管理库

在这里插入图片描述

优化:Axios请求拦截器

在这里插入图片描述

在这里插入图片描述

Bug:刷新时,Pinia数据丢失

persist-Pinia持久化插件

在这里插入图片描述
在这里插入图片描述

未登录处理

在这里插入图片描述

  • 25
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值