首页 > 其他分享 >【全栈第一课】Vue快速入门

【全栈第一课】Vue快速入门

时间:2023-12-04 16:32:26浏览次数:37  
标签:index Vue 自定义 webpack js 第一课 全栈 vue 组件


一、前端工程化

【全栈第一课】Vue快速入门_前端

JS的复用就是模块化

UI样式复用就是组件化(LayUI里面的都是组件化)

所以说前端工程化就是有规范的写,不能你一个样式我一个样式,不够统一不够专业!

二、WebPack

是什么

【全栈第一课】Vue快速入门_vue.js_02

前端工程化的具体实现方案

基本使用

实现奇偶行变色

1.初始化包管理工具

通过npm init -y生成

【全栈第一课】Vue快速入门_javascript_03

2.安装jquery

-S的意思是–save

npm install jquery -S
3.在项目中安装webpack

-D就是把包放到devDependencies下,打包运行的时候不会被打包

-D为–save-dev简写

npm install [email protected] [email protected] -D

【全栈第一课】Vue快速入门_Vue_04

4.在项目中配置webpack

在项目根目录中,创建名为 webpack.config.js 的 webpack 配置文件,并初始化如下的基本配置:

module.exports = {
    mode: 'development'
};

在 package.json 的 scripts 节点下,新增 dev 脚本如下:

【全栈第一课】Vue快速入门_Vue_05

tips:webpack要和src同目录

【全栈第一课】Vue快速入门_vue.js_06

5.运行代码

通过npm run dev运行

这里的webpack将用jQuery写的操作和一些新的写法转换成了能被浏览器兼容的js文件(dist下的main.js)

【全栈第一课】Vue快速入门_vue.js_07

实现效果如下:

【全栈第一课】Vue快速入门_html_08

mode 的可选值

development

开发环境

不会对打包生成的文件进行代码压缩和性能优化

打包速度快,适合在开发阶段使用

production

生产环境

会对打包生成的文件进行代码压缩和性能优化

打包速度很慢,仅适合在项目发布阶段使用

【全栈第一课】Vue快速入门_vue.js_09

webpack.config.js 文件的作用

webpack.config.js 是 webpack 的配置文件。

webpack 在真正开始打包构建之前,会先读取这个配置文件, 从而基于给定的配置,对项目进行打包。

注意:由于 webpack 是基于 node.js 开发出来的打包工具,因此在它的配置文件中,支持使用 node.js 相关 的语法和模块进行 webpack 的个性化配置。

webpack 中的默认约定

在 webpack 4.x 和 5.x 的版本中,有如下的默认约定:

① 默认的打包入口文件为 src -> index.js

② 默认的输出文件路径为 dist -> main.js

注意:可以在 webpack.config.js 中修改打包的默认约定

自定义打包的入口与出口

在 webpack.config.js 配置文件中,通过 entry 节点指定打包的入口。通过 output 节点指定打包的出口。

示例代码如下:

const path = require('path')//导入node.js中专门操作路径的模块

module.exports = {
    mode: 'production',
    entry: path.join(__dirname,'./src/index.js'),//打包的入口文件
    output: {
        path: path.join(__dirname,'./dist'),//存放路径
        filename: "nice.js"//输入的文件名
    }
};

【全栈第一课】Vue快速入门_javascript_10

webpack中的插件

webpack 插件的作用

通过安装和配置第三方的插件,可以拓展 webpack 的能力,从而让 webpack 用起来更方便。最常用的webpack 插件有如下两个:

① webpack-dev-server

类似于 node.js 阶段用到的 nodemon 工具(修改代码自动重新打包和构建)

每当修改了源代码,webpack 会自动进行项目的打包和构建(最常用)

② html-webpack-plugin

webpack 中的 HTML 插件(类似于一个模板引擎插件)

可以通过此插件自定制 index.html 页面的内容

安装之后我们还不能直接访问,因为打包生成的文件存放到了内存中

生成到内存中的文件该如何访问?

webpack-dev-server 生成到内存中的文件,默认放到了项目的根目录中,而且是虚拟的、不可见的。

可以直接用 / 表示项目根目录,后面跟上要访问的文件名称,即可访问内存中的文件

例如 /bundle.js 就表示要访问 webpack-dev-server 生成到内存中的 bundle.js 文件

所以我们只有把index页面放到根目录它才能和bundle.js联合使用,才能实现实时更新

怎么实现呢?拷贝过去一份不就行了!我们用下面的方法来实现

html-webpack-plugin

html-webpack-plugin 是 webpack 中的 HTML 插件,可以通过此插件自定制 index.html 页面的内容。

需求:通过 html-webpack-plugin 插件,将 src 目录下的 index.html 首页,复制到项目根目录中一份!

安装

npm install [email protected] -D

配置

const path = require('path')//导入node.js中专门操作路径的模块
const HtmlPlugin = require('html-webpack-plugin')

// 创建html插件的实例对象
const htmlPlugin = new HtmlPlugin({
    template: './src/index.html',//源文件存放路径
    filename: './index.html'//生成的文件存放路径
})

module.exports = {
    mode: 'development',
    plugins: [htmlPlugin]//通过plugins节点,使htmlPlugin插件生效
};

总结

  • 通过 HTML 插件复制到项目根目录中的 index.html 页面,也被放到了内存中
  • HTML 插件在生成的 index.html 页面,自动注入了打包的 bundle.js 文件

devServer 节点

在 webpack.config.js 配置文件中,可以通过 devServer 节点对 webpack-dev-server 插件进行更多的配置, 示例代码如下:

module.exports = {
    mode: 'development',
    plugins: [htmlPlugin],//通过plugins节点,使htmlPlugin插件生效
    devServer: {
        open: true,
        // host: '',
        port: 80
    }
};

mac中要加sudo才能监听

【全栈第一课】Vue快速入门_vue.js_11

webpack 中的 loader

loader 概述

在实际开发过程中,webpack 默认只能打包处理以 .js 后缀名结尾的模块。其他非 .js 后缀名结尾的模块, webpack 默认处理不了,需要调用 loader 加载器才可以正常打包,否则会报错!

loader 加载器的作用:协助 webpack 打包处理特定的文件模块。比如:

  • css-loader 可以打包处理 .css 相关的文件
  • less-loader 可以打包处理 .less 相关的文件
  • babel-loader 可以打包处理 webpack 无法处理的高级 JS 语法

【全栈第一课】Vue快速入门_html_12

loader 的调用过程

【全栈第一课】Vue快速入门_javascript_13

打包处理 css 文件

module: {
  rules: [
    {
      test: /\.css$/, use: ['style-loader', 'css-loader']
    }
  ]
}

【全栈第一课】Vue快速入门_vue.js_14

打包处理 less 文件

less文件可以让CSS写的更简单,这里是让无序列表的间隙消失

html,
body,
ul{
  margin: 0;
  padding: 0;
  li{
    line-height: 30px;
    padding-left: 20px;
    font-size: 12px;
  }
}

之后在index.js文件中引入改less文件即可

如果不设置less文件加载器,也会报错.所以运行 npm i [email protected] [email protected] -D 命令

在 webpack.config.js 的 module -> rules 数组中,添加 loader 规则如下:

module: {
    rules: [
        {test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader']}
    ]
}

效果不放了因为太刺眼了

打包发布

通过前面的学习我们也能知道,你输入npm run dev 的时候它就会生成一个dist目录,这个dist目录其实就是打包好的,可以直接点index文件去访问的

现在项目要上线了,我们要减少dist文件的体积,其实就是运行npm run 生产环境的配置

在package.json配置一下:

"scripts": {
  "dev": "webpack serve",
  "build": "webpack --mode production"
},

【全栈第一课】Vue快速入门_前端_15

运行程序:

npm run build

总结

webpack了解概念即可,后面使用脚手架这东西都是配置好的

  • 运行程序npm run dev
  • 发布程序npm run build

如果不是这个两个命令,那就去看它的package咋写的替换run 后面的单词即可

三、Vue基础入门

Vue简介

什么是Vue

构建用户界面的框架

  • 构建用户界面

用 vue 往 html 页面中填充数据,非常的方便

  • 框架

框架是一套现成的解决方案,程序员只能遵守框架的规范,去编写自己的业务功能!

要学习 vue,就是在学习 vue 框架中规定的用法!

vue 的指令、组件(是对 UI 结构的复用)、路由、Vuex、vue 组件库

Vue 的两个特性

数据驱动视图:

  • 数据的变化会驱动视图自动更新
  • 好处:程序员只管把数据维护好,那么页面结构会被 vue 自动渲染出来!

【全栈第一课】Vue快速入门_javascript_16

双向数据绑定:

在网页中,form 表单负责采集数据,Ajax 负责提交数据

  • js 数据的变化,会被自动渲染到页面上
  • 页面上表单采集的数据发生变化的时候,会被 vue 自动获取到,并更新到 js 数据中

注意:数据驱动视图和双向数据绑定的底层原理是 MVVM(Mode 数据源、View 视图、ViewModel 就是 vue 的实例)

【全栈第一课】Vue快速入门_vue.js_17

MVVM的原理

【全栈第一课】Vue快速入门_javascript_18

【全栈第一课】Vue快速入门_Vue_19

总结

课件其实已经总结的很好了,MVVM最重要的就是VUE的实例VM(ViewModel)

  • 它监听DOM的变化,当表单中的值发生变化时,VM会把数据同步到Model源中
  • 它监听Model的变化,当Model发生变化时,它会把最新数据同步到View里

Vue的基本使用

Vue的基本使用步骤

  • 导入vue.js文件
  • 在页面声明一个将要被vue所控制的DOM区域
  • 创建vm实例
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Title</title>
  </head>
  <body>
    <div id="app">{{username}}</div>

    <script src="./lib/vue-2.6.12.js"></script>

    <script>
      const vm = new Vue({
        el: "#app",
        data: {
          username: "zs",
        },
      });
    </script>
  </body>
</html>

基本代码与 MVVM 的对应关系

【全栈第一课】Vue快速入门_javascript_20

Vue指令

内容渲染指令

  1. v-text 指令的缺点:会覆盖元素内部原有的内容!
  2. {{ }} 插值表达式:在实际开发中用的最多,只是内容的占位符,不会覆盖原有的内容!
  3. v-html 指令的作用:可以把带有标签的字符串,渲染成真正的 HTML 内容!

属性绑定指令

注意:插值表达式只能用在元素的内容节点中,不能用在元素的属性节点中!

  • 在 vue 中,可以使用 v-bind: 指令,为元素的属性动态绑定值;
  • 简写是英文的 :
  • 在使用 v-bind 属性绑定期间,如果绑定内容需要进行动态拼接,则字符串的外面应该包裹单引号,例如:
<div :title="'box' + index">这是一个 div</div>

事件绑定

  1. v-on: 简写是 @
  2. 语法格式为:
<button @click="add"></button>

methods: {
   add() {
			// 如果在方法中要修改 data 中的数据,可以通过 this 访问到
			this.count += 1
   }
}
  1. $event 的应用场景:如果默认的事件对象 e 被覆盖了,则可以手动传递一个 $event。例如:
<button @click="add(3, $event)"></button>

methods: {
   add(n, e) {
			// 如果在方法中要修改 data 中的数据,可以通过 this 访问到
			this.count += 1
   }
}
  1. 事件修饰符:
  • .prevent
<a @click.prevent="xxx">链接</a>
  • .stop
<button @click.stop="xxx">按钮</button>

【全栈第一课】Vue快速入门_前端_21

v-model 指令

  1. input 输入框
  • type=“radio”
  • type=“checkbox”
  • type=“xxxx”
  1. textarea
  2. select

条件渲染指令

  1. v-show 的原理是:动态为元素添加或移除 display: none 样式,来实现元素的显示和隐藏
  • 如果要频繁的切换元素的显示状态,用 v-show 性能会更好
  1. v-if 的原理是:每次动态创建或移除元素,实现元素的显示和隐藏
  • 如果刚进入页面的时候,某些元素默认不需要被展示,而且后期这个元素很可能也不需要被展示出来,此时 v-if 性能更好

在实际开发中,绝大多数情况,不用考虑性能问题,直接使用 v-if 就好了!!!

v-if 指令在使用的时候,有两种方式:

  1. 直接给定一个布尔值 true 或 false
<p v-if="true">被 v-if 控制的元素</p>
  1. 给 v-if 提供一个判断条件,根据判断的结果是 true 或 false,来控制元素的显示和隐藏
<p v-if="type === 'A'">良好</p>

过滤器

Vue3已经放弃,Vue2可以用

怎么理解过滤器?就跟linux里的grep命令一样,就是筛选,它定义在filters里面

我们来看看代码示例:

  • 要定义到 filters 节点下,本质是一个函数
  • 在过滤器函数中,一定要有 return 值
  • 在过滤器的形参中,可以获取到“管道符”前面待处理的那个值
  • 如果全局过滤器和私有过滤器名字一致,此时按照“就近原则”,调用的是”私有过滤器“
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <p>message的值是{{message | capi}}</p>
</div>

<script src="/lib/vue-2.6.12.js"></script>

<script>
    const vm = new Vue({
        el: '#app',
        data: {
            message: 'hello vue.js'
        },
        filters:{
            //过滤器函数形参中的val,永远都是"管道符"前面的那个值
            capi(val){
                const first = val.charAt(0).toUpperCase()
                const other = val.slice(1)
                
                return first + other
            }
        }
    })
</script>

</body>
</html>

全局过滤器

全局过滤器 - 独立于每个 vm 实例之外
Vue. filter()方法接收两个参数:
第1 个参数,是全局过滤器的”名字”
第2 个参数,是全局过滤器的”处理函数”

Vue.filter('capi',(val) =>{
	return val.charAt(0).toUpperCase() + val.slice(1) + '~~~~~~~~~~~~~'
})

连续调用多个过滤器

把 message 的值,交给 filterA 进行处理
把 filterA 处理的结果,再交给 filterB 进行处理
最终把 filterB 处理的结果,作为最终的值這染到页面上
{{ message 1 filterA I filterB }}

{{ message | filterA | filterB }}

过滤器传参

过滤器的本质是 JavaScript 函数,因此可以接收参数,格式如下:

【全栈第一课】Vue快速入门_前端_22

示例代码如下:

【全栈第一课】Vue快速入门_vue.js_23

入门实例

实现增删查功能

实现思路:

  • 增加功能

首先要收集品牌名称,然后阻止表单的默认提交行为,改为调用自定义方法add

在add中定义要添加的对象,name为收集到的brand,状态为status设置为默认值即可,创建时间也设置一个默认值即可

id的话想要保证自增,所以可以自定义一个id,然后每添加一个对象id+1

对象创建好之后,直接push进list列表即可

  • 删除功能

从list列表中过滤对象,通过传入的对象id即可过滤

  • 查询功能

通过v-for去遍历data区域的list数组

【全栈第一课】Vue快速入门_前端_24

完整代码如下:

<!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>
    <link rel="stylesheet" href="./lib/bootstrap.css">
    <link rel="stylesheet" href="./css/brandlist.css">
</head>

<body>

<div id="app">
    <!-- 卡片区域 -->
    <div class="card">
        <div class="card-header">
            添加品牌
        </div>
        <div class="card-body">
            <!-- 添加品牌的表单区域 -->
            <!--            表单有默认的提交行为,通过@submit.prevent可以阻止它的默认行为-->
            <form @submit.prevent="add">
                <div class="form-row align-items-center">
                    <div class="col-auto">
                        <div class="input-group mb-2">
                            <div class="input-group-prepend">
                                <div class="input-group-text">品牌名称</div>
                            </div>
                            <input type="text" class="form-control" placeholder="请输入品牌名称" v-model.trim="brand">
                        </div>
                    </div>
                    <div class="col-auto">
                        <button type="submit" class="btn btn-primary mb-2">添加</button>
                    </div>
                </div>
            </form>
        </div>
    </div>

    <!-- 表格区域 -->
    <table class="table table-bordered table-hover table-striped">
        <thead>
        <tr>
            <th scope="col">#</th>
            <th scope="col">品牌名称</th>
            <th scope="col">状态</th>
            <th scope="col">创建时间</th>
            <th scope="col">操作</th>
        </tr>
        </thead>
        <tbody>
        <tr v-for="item in list" :key="item.id">
            <td>{{item.id}}</td>
            <td>{{item.name}}</td>
            <td>
                <div class="custom-control custom-switch">
                    <input type="checkbox" class="custom-control-input" :id="'cd' + item.id" v-model="item.status">
                    <label class="custom-control-label" :for="'cd' + item.id" v-if="item.status">已启用</label>
                    <label class="custom-control-label" :for="'cd' + item.id" v-else>已禁用</label>
                </div>
            </td>
            <td>{{item.time}}</td>
            <td>
                <a href="javascript:;" @click="remove(item.id)">删除</a>
            </td>
        </tr>
        </tbody>
    </table>
</div>

<script src="./lib/vue-2.6.12.js"></script>

<script>
    const vm = new Vue({
        el: '#app',
        data: {
            //品牌的列表数据
            brand: "",
            list: [
                {id: 1, name: '宝马', status: true, time: new Date()},
                {id: 2, name: '奔驰', status: false, time: new Date()},
                {id: 3, name: '奥迪', status: true, time: new Date()},
            ],
            nextId: 4,
        },
        methods: {
            remove(id) {
                // console.log(id)
                this.list = this.list.filter(item => item.id != id)
            },
            add() {
                // console.log(this.brand)
                // 如果判断到brand的值为空字符串,则return出去
                if (this.brand === '') return alert("必须填写品牌名称")

                // 如果没有return出去,应该去执行添加的逻辑
                // 先把要添加的品牌对象,整理出来
                const obj = {
                    id: this.nextId,
                    name: this.brand,
                    status: true,
                    time: new Date()
                }
                this.list.push(obj)
                this.brand = ''
                this.nextId += 1

            }
        }
    })
</script>
</body>

</html>

四、Vue基础进阶

watch 侦听器

什么是侦听器

watch 侦听器允许开发者监视数据的变化,从而针对数据的变化做特定的操作

【全栈第一课】Vue快速入门_vue.js_25

侦听器的格式

  1. 方法格式的侦听器
  • 缺点1:无法在刚进入页面的时候,自动触发!!!
  • 缺点2:如果侦听的是一个对象,如果对象中的属性发生了变化,不会触发侦听器!!!
  1. 对象格式的侦听器
  • 好处1:可以通过 immediate 选项,让侦听器自动触发!!!

【全栈第一课】Vue快速入门_html_26

  • 好处2:可以通过 deep 选项,让侦听器深度监听对象中每个属性的变化!!!

【全栈第一课】Vue快速入门_javascript_27

侦听器测试

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div id="app">
    <input type="text" v-model="username">
</div>
<script src="/lib/vue-2.6.12.js"></script>


<script>
    const vm = new Vue({
        el: '#app',
        data: {
            username: '',
        },
        watch: {
            username(newOlder, oldValue) {
                console.log('监听到了username发生了变化', newOlder, oldValue)
            },

        }
    })
</script>


</body>
</html>

【全栈第一课】Vue快速入门_Vue_28

计算属性

是什么?

计算属性指的是通过一系列运算之后,最终得到一个属性值。

这个动态计算出来的属性值可以被模板结构或 methods 方法使用。示例代码如下:

【全栈第一课】Vue快速入门_javascript_29

特点

  • 定义的时候,要被定义为“方法”
  • 使用计算属性的时候,当普通的属性使用即可

好处

  • 实现了代码的复用
  • 只要计算属性中依赖的数据源变化了,则计算属性会自动重新求值!

axios

axios(发音:艾克C奥斯) 是一个专注于网络请求的库!

它封装了Ajax(通过 Ajax 可以异步从服务器请求数据并将数据更新到网页中,整个过程不需要重载(刷新)整个网页,可以将网页的内容更快的呈现给用户。)

axios 的基本使用

发起 GET 请求
axios({
  // 请求方式
  method: 'GET',
  // 请求的地址
  url: 'http://www.liulongbin.top:3006/api/getbooks',
  // URL 中的查询参数
  params: {
    id: 1
  },
  //请求体参数
  data:{}
}).then(function (result) {
  console.log(result)
})

简写:

const resu = axios.get('https://www.escook.cn/api/cart')
resu.then(function (books) {
	console.log(books)
})

axios返回的是一个Promise对象,在Promise对象中并不是服务器返回的结果,而是axios对服务器返回的结果又进行了一次封装,如下:

【全栈第一课】Vue快速入门_Vue_30

简化如下:

【全栈第一课】Vue快速入门_html_31

发起 POST 请求
document.querySelector('#btnPost').addEventListener('click', async function () {
  // 如果调用某个方法的返回值是 Promise 实例,则前面可以添加 await!
  // await 只能用在被 async “修饰”的方法中
  const { data: res } = await axios({
    method: 'POST', 
    url: 'http://www.liulongbin.top:3006/api/post',
    data: {
      name: 'zs',
      age: 20
    }
  })

  console.log(res)
})

使用解构赋值

基于axios

【全栈第一课】Vue快速入门_html_32

vue-cli

什么是单页面应用程序?

SPA(Single Page Application)

指的就是一个Web网站中只有唯一的一个HTML页面,所有的功能与交互都是在这唯一的一个页面完成

一般Vue项目打包之后会生成一个dist文件,这个dist文件就是下面这个样式的

【全栈第一课】Vue快速入门_vue.js_33

什么是vue-cli?

快速生成一个vue项目的开发环境,程序员可以专注在撰写应用上,而不必花好几天去纠结 webpack 配置的问题。

安装和使用

【全栈第一课】Vue快速入门_html_34

  1. 在终端下运行如下的命令,创建指定名称的项目:
vue cerate 项目的名称
  1. vue 项目中 src 目录的构成:
assets 文件夹:存放项目中用到的静态资源文件,例如:css 样式表、图片资源
components 文件夹:程序员封装的、可复用的组件,都要放到 components 目录下
main.js 是项目的入口文件。整个项目的运行,要先执行 main.js
App.vue 是项目的根组件。

vue项目的运行流程

在工程化的项目中,vue 要做的事情很单纯:通过main.jsApp.vue渲染到 index.html 的指定区域中。

【全栈第一课】Vue快速入门_html_35

  • App.vue 用来编写待渲染的模板结构
  • index.html 中需要预留一个 el 区域
  • main.js 把 App.vue 渲染到了 index.html 所预留的区域中

渲染之后,会代替index页面原有的代码

【全栈第一课】Vue快速入门_Vue_36

vue组件

组件化开发

组件化开发指的是:根据封装的思想,把页面上可重用的 UI 结构封装为组件,从而方便项目的开发和维护。

vue 中的组件化开发

vue 是一个支持组件化开发的前端框架。 vue 中规定:组件的后缀名是 .vue。之前接触到的 App.vue 文件本质上就是一个 vue 的组件

vue 组件的三个组成部分

每个.vue组件都由3部分构成,分别是:

template -> 组件的模版结构

Script -> 组件的JavaScript行为

Style -> 组件的样式

其中,每个组件中必须包含 template 模板结构,而 script 行为和 style 样式是可选的组成部分

template

vue 规定:每个组件对应的模板结构,需要定义到<template>节点中

<template>
<!--当前组件的DOM结构,需要定义到template标签的内部 -->
</template>

tips:

  • template是vue提供的容器标签,只起到包裹性质的作用,他不会被渲染为真正的DOM元素
  • template 中只能包含唯一的根节点
script

vue 规定:开发者可以在 <script> 节点中封装组件的 JavaScript 业务逻辑。

【全栈第一课】Vue快速入门_javascript_37

.vue 组件中的 data 必须是函数

【全栈第一课】Vue快速入门_前端_38

style

【全栈第一课】Vue快速入门_vue.js_39

【全栈第一课】Vue快速入门_html_40

实例
<template>
  <div class="wahahaha">
    <h3>这是用户自定义的vue组件--{{ username }}</h3>
  </div>
</template>

<!--固定写法-->
<script>
export default {
  data() {
    return {
      username: 'zs'
    }
  }
}
</script>

<style>
  .wahahaha{
    background-color: pink;
  }
</style>
启用less语法以及唯一根节点
  • 组件中只能有一个根节点,也就是说不能写多个一级div,只能在一级div里定义多个低级div
  • less语法就是让css的编写更简单
<template>
  <div>
    <div id="wahahaha">
      <h3>这是用户自定义的vue组件--{{ username }}</h3>
      <button @click="changeName">点我改变名字</button>
    </div>
    <div>123</div>
  </div>

</template>

<!--固定写法-->
<script>
export default {
  data() {
    return {
      username: 'zs'
    }
  },
  methods: {
    changeName() {
      console.log(this),
          this.username = 'Wahahah'
    }
  },
  // 当前组件的监听器
  watch: {},
  // 当前组件的计算属性
  computed: {}
}
</script>

<style lang="less">
#wahahaha {
  background-color: pink;

  h3 {
      color: azure;
  }
}
</style>

组件之间的父子关系

【全栈第一课】Vue快速入门_vue.js_41

使用组件的三个步骤

【全栈第一课】Vue快速入门_javascript_42

实例

【全栈第一课】Vue快速入门_Vue_43

Hello.vue是我后来加

【全栈第一课】Vue快速入门_html_44

通过 components 注册的是私有子组件

例如:

  • 在组件 A 的 components 节点下,注册了组件 F。
  • 则组件 F 只能用在组件 A 中;不能被用在组件 C 中。

注册全局组件

在 vue 项目的 main.js 入口文件中,通过 Vue.component() 方法,可以注册全局组件。

实例如下:

【全栈第一课】Vue快速入门_前端_45

组件的props

props 是组件的**自定义属性**,在封装通用组件的时候,合理地使用 props 可以极大的提高组件的复用性!

  • props中的数据,可以直接在模版结构中使用

【全栈第一课】Vue快速入门_Vue_46

实例

left组件

  • 使用v-bind可以给属性赋值
  • 这里init自定义属性为字符串类型,通过v-bind代表你后面写的是js表达式,数字在js中就是Number型
<template>
  <div class="left-container">
    <h3>我是left</h3>
    <MyCount :init="9"></MyCount>
  </div>
</template>

<script>
export default {
  name: "Left",
}
</script>

<style>
.left-container {
  padding: 0 20px 20px;
  background-color: #42b983;
  min-height: 250px;
  flex: 1;
}
</style>

count组件

<template>
  <div>
    <p>count的值是:{{ init }}</p>
    <button @click="init += 1">Hi,点我给count+1</button>
  </div>
</template>

<script>
export default {
  props: ['init'],
  name: "Count",
  data() {
    return {
      count: 0,
    }
  }
}
</script>

<style scoped>

</style>

如图所示:

【全栈第一课】Vue快速入门_前端_47

props 是只读的

【全栈第一课】Vue快速入门_Vue_48

要想修改 props 的值,可以把 props 的值转存到 data 中,因为 data 中的数据都是可读可写的!

所以props值的作用就是做一个初始化,最好是去操作data里的数据,所以这里可以通过this.init去把初始值赋给data里的count

this代表当前组件对象

<template>
  <div>
    <p>count的值是:{{ count }}</p>
    <button @click="count += 1">Hi,点我给count+1</button>
  </div>
</template>

<script>
export default {
  props: ['init'],
  name: "Count",
  data() {
    return {
      count: this.init
    }
  }
}
</script>

<style scoped>

</style>
props 的 default 默认值

在声明自定义属性时,可以通过 default 来定义属性的默认值。示例代码如下:

props:{

自定义属性A:{},

自定义属性B:{},

自定义属性C:{},

}

export default {
  props: {
    init: {
      default: 0,
    }
  },
  name: "Count",
  data() {
    return {
      count: this.init
    }
  }
}
props 的 type 值类型

在声明自定义属性时,可以通过 type 来定义属性的值类型。示例代码如下:

export default {
  props: {
    init: {
      default: 0,
    }
  },
  name: "Count",
  data() {
    return {
      count: this.init,
      type: Number
    }
  }
}
props 的 required 必填项

就是说,你自定义的这个属性是必填项,不填就会报错

【全栈第一课】Vue快速入门_vue.js_49

组件之间的样式冲突问题

scoped

默认情况下,写在 .vue 组件中的样式会全局生效,因此很容易造成多个组件之间的样式冲突问题。

导致组件之间样式冲突的根本原因是:

  • 单页面应用程序中,所有组件的 DOM 结构,都是基于唯一的 index.html 页面进行呈现的
  • 每个组件中的样式,都会影响整个 index.html 页面中的 DOM 元素

为了提高开发效率和开发体验,vue 为 style 节点提供了 scoped 属性,从而防止组件之间的样式冲突问题:

【全栈第一课】Vue快速入门_html_50

/deep/ 样式穿透

【全栈第一课】Vue快速入门_html_51

什么时候会用到

如果代码引入了第三方组件库,想修改它的样式不能去直接修改它的源码,找到要修改的组件位置通过/deep/做样式穿透

五、生命周期&数据共享

生命周期 & 生命周期函数

生命周期(Life Cycle)是指一个组件从创建 -> 运行 -> 销毁的整个阶段,强调的是一个时间段

生命周期函数:是由 vue 框架提供的内置函数,会伴随着组件的生命周期,自动按次序执行。

注意:生命周期强调的是时间段,生命周期函数强调的是时间点。

组件生命周期函数的分类

【全栈第一课】Vue快速入门_html_52

生命周期详解

简洁版本

回调函数是你留个处理方法给事件,事件发生了以后会自动执行你留下调处理方法

钩子函数是好比找了个代理,监视事件是否发生,如果发生了这个代理就执行你的事件处理方法;在这个过程中,代理就是钩子函数

在某种意义上,回调函数做的处理过程跟钩子函数中要调用调方法一样
但是有一点: 钩子函数一般是由事件发生者提供的。直白了说,它留下一个钩子,这个钩子的作用就是钩住你的回调方法

==钩子函数是在一个事件触发的时候,在系统级捕获到了他,然后做一些操作。==一段用以处理系统消息的程序,用以处理系统消息的程序,是说钩子函数是用于处理系统消息的

【全栈第一课】Vue快速入门_html_53

详细版本

【全栈第一课】Vue快速入门_前端_54

最重要的三个阶段

  • created
    组件的 porps/data/methods已创建好,都处于可用的状态。但是组件的模板结构尚未生成!
  • mounted
    已经把内存中的 HTML 结构,成功的渲染到了浏览器之中。此时浏览器中己然包含了当前组件的 DOM 结构。
  • update
    组件的最新数据,可以操作最新的DOM结构

组件之间的关系

在项目开发中,组件之间的最常见的关系分为如下两种:

① 父子关系

② 兄弟关系

【全栈第一课】Vue快速入门_Vue_55

父子组件之间的数据共享

父子组件之间的数据共享又分为:

① 父 -> 子共享数据

② 子 -> 父共享数据

父组件向子组件共享数据

父组件向子组件共享数据需要使用自定义属性

如下:

父组件

<template>
  <img alt="Vue logo" src="./assets/logo.png">
  <HelloWorld msg="Welcome to Your Vue.js App"/>
  <div class="box">
    <Left></Left>
    <Right :username=userinfo :passwd=passwd></Right>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'
import Left from "@/components/Left";
import Right from "@/components/Right";

export default {
  name: 'App',
  components: {
    HelloWorld,
    Left,
    Right
  },
  data() {
    return {
      userinfo: {name: 'zs', age: 12},
      passwd: 123
    }
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}

.box {
  display: flex;
}
</style>

子组件

<template>

  <div class="rightContainer">
    <h2>
      我是right
    </h2>

    <h2>您的姓名是:{{username}}</h2>
    <h2>您的密码是:{{passwd}}</h2>
  </div>


</template>

<script>
export default {
  name: "Right",
  props: ['username','passwd']
}
</script>

<style scoped>
.rightContainer {
  background-color: aquamarine;
  flex: 1;
  height: 300px;
}
</style>
子组件向父组件共享数据

子组件向父组件共享数据使用自定义事件。

【全栈第一课】Vue快速入门_html_56

如下:

【全栈第一课】Vue快速入门_html_57

【全栈第一课】Vue快速入门_html_58

兄弟组件之间的数据共享

在 vue2.x 中,兄弟组件之间数据共享的方案是 EventBus

【全栈第一课】Vue快速入门_前端_59

EventBus 的使用步骤

  1. 创建 eventBus.js 模块,并向外共享一个 Vue 的实例对象
  2. 在数据发送方,调用 bus.$emit(‘事件名称’, 要发送的数据) 方法触发自定义事件
  3. 在数据接收方,调用 bus.$on(‘事件名称’, 事件处理函数) 方法注册一个自定义事件

ref 引用

ref 用来辅助开发者在不依赖于 jQuery 的情况下,获取 DOM 元素或组件的引用。

每个 vue 的组件实例上,都包含一个 $refs 对象,里面存储着对应的 DOM 元素或组件的引用。默认情况下,组件的 $refs 指向一个空对象。

什么是 ref 引用

ref 用来辅助开发者在不依赖于 jQuery 的情况下获取 DOM 元素或组件的引用。

每个 vue 的组件实例上,都包含一个 $refs 对象,里面存储着对应的 DOM 元素或组件的引用。默认情况下,

组件的 $refs 指向一个空对象。

【全栈第一课】Vue快速入门_vue.js_60

使用 ref 引用 DOM 元素

如果想要使用 ref 引用页面上的 DOM 元素,则可以按照如下的方式进行操作:

【全栈第一课】Vue快速入门_Vue_61

使用 ref 引用组件实例

【全栈第一课】Vue快速入门_vue.js_62

控制文本框和按钮的按需切换

【全栈第一课】Vue快速入门_javascript_63

让文本框自动获得焦点

当文本框展示出来之后,如果希望它立即获得焦点,则可以为其添加 ref 引用,并调用原生 DOM 对象的 .focus() 方法即可。示例代码如下:

【全栈第一课】Vue快速入门_javascript_64

this.$nextTick(cb) 方法

组件的 $nextTick(cb) 方法,会把 cb 回调推迟到下一个 DOM 更新周期之后执行。通俗的理解是:等组件的 DOM 更新完成之后,再执行 cb 回调函数。从而能保证 cb 回调函数可以操作到最新的 DOM 元素。

【全栈第一课】Vue快速入门_javascript_65

【全栈第一课】Vue快速入门_前端_66

数组中的方法

some循环

  • 简单来说some循环就是遇到终止条件可以停止继续寻找
  • foreach即使遇到终止条件也会继续寻找
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<script>
    const arr = ['詹姆斯', '科比', '2届MVP得主库里', '1.5']

    arr.forEach((item, index) => {
        console.log('ok')
        if (item === '2届MVP得主库里') {
            console.log(index)
        }
    })

    console.log('arr.some使用效果如下:')

    arr.some((item, index) => {
        console.log('ok')
        if (item === '2届MVP得主库里') {
            console.log(index)
            return true
        }
    })

</script>

</body>
</html>

【全栈第一课】Vue快速入门_Vue_67

foreach循环

foreach就是循环每一项,some是循环到满足条件就停下来

every循环

判断数组中的数据是否被全选了使用every循环

【全栈第一课】Vue快速入门_前端_68

reduce的基本用法

不用reduce计算总和

【全栈第一课】Vue快速入门_javascript_69

用reduce计算总和

【全栈第一课】Vue快速入门_html_70

reduce的简化写法

【全栈第一课】Vue快速入门_html_71

购物车案例

导入,注册,使用组件

这里的组件是写好的,我们直接导入,注册,使用

Tips:

  • 导入的组件名称一般都给它设置为首字母大写.这样和普通标签能有一个区分

【全栈第一课】Vue快速入门_html_72

基于axios请求列表数据

axios是对ajax的封装,向后端发送请求就用它

这里是先定义一个封装请求列表数据的方法,然后在vue的created的生命周期阶段调用

created() {
  this.initCartList()
},
methods: {
  //封装请求列表数据的方法
  async initCartList() {
    //调用axios的get方法,请求列表数据
    const {data: res} = await axios.get('https://www.escook.cn/api/cart')
    // 只要请求回来的数据,在页面渲染期间要用到,则必须转存到data里
    this.list = res.list
  }
},

这里的await是用来解构赋值的它一般和async联合使用

那么解构赋值是什么呢?

就是前段通过axios向后端发送请求之后,后端返回的数据会先经过axios进行一次封装,不能直接拿到真实数据

如下:

【全栈第一课】Vue快速入门_vue.js_73

所以为了直接拿到真实数据,我们需要解构,从回复的数据中取出真实数据

{{data:res}}这是啥意思呢?

axios返回的是一个Promise对象,在Promise对象中并不是服务器返回的结果,而是axios对服务器返回的结果又进行了一次封装,如下:

【全栈第一课】Vue快速入门_javascript_74

通过{{data:res}}意思就是取出Promise对象中的data区域数据,并把名字重命名为res

渲染Goods组件

1.商品数据其实就是一个个Goods组件

导入,注册,使用组件

<Goods></Goods>

2.给组件赋值,这里通过v-for来实现

首先看看请求到的结果

【全栈第一课】Vue快速入门_javascript_75

list数组里不就是如下一个个的对象吗,然后赋值的时候通过对象.属性即可取得对应的值

这里的:key,:id,:title等都是为子组件的自定义属性,父组件向子组件传递数据就是通过自定义属性来进行传递的

<!--    这里为啥一直要写v-bind呢因为在等号后面我们写的是js表达式,如果不写v-bind则相当于我们传给它了一个字符串!-->
<Goods
    v-for="item in list"
    :key="item.id"
    :id="item.id"
    :title="item.goods_name"
    :img="item.goods_img"
    :price="item.goods_price"
    :state="item.goods_state "
>
</Goods>

3.修改商品的勾选状态

修改商品的勾选状态为子组件向父组件共享数据

通过自定义事件来实现

3.1 在子组件中为复选框绑定自定义事件

复选框状态每发生一次改变就会触发自定义事件

<input type="checkbox" class="custom-control-input" :id="'cb' + id" :checked="state"
       @change="stateChange"/>

3.2 在子组件中自定义事件如下

自定义时间名字为state-change,传递给父组件的数据为id和value

  • id表示当前商品
  • value表示最新的勾选状态
methods: {
  stateChange(e) {
    // console.log(e)
    console.log(e.target.checked)
    const newState = e.target.checked
    // 触发自定义事件
    this.$emit('state-change', {id: this.id, value: newState})
  }
}

3.3 父组件绑定自定义事件

通过参数e来接受子组件传来的数据

通过some循环找到改变状态的子组件判断的条件是id,找到之后给组件的状态赋值为子组件传来的真实数据

<Goods @state-change="getNewState"></Goods>
methods: {
    getNewState(e) {
      console.log(e)
      this.list.some(item => {
        if (item.id === e.id) {
          item.goods_state = e.value
        }
      })
    }
  },

渲染Footer组件

引入footer组件

footer组件做二件事:

  • 全选
  • 计算总价

全选为子组件向父组件共享数据 => 自定义事件

计算总价为父组件向子组件共享数据 => 自定义属性

<Footer
    :is-full="fullState"
    @fullChange="getFullState"
    :total-prices="amt"
></Footer>

全选功能的实现

//子组件
<input type="checkbox" class="custom-control-input" id="cbFull" :checked="isFull" @change="fullChange"/>

  methods: {
    fullChange(e) {
      // console.log(e.target.checked)
      // 触发自定义事件
      this.$emit('fullChange', e.target.checked)
    }
  }


// 动态计算全选的状态是true还是false
fullState() {
  return this.list.every(item => item.goods_state)
},
  
//父组件
  // 动态计算全选的状态是true还是false
  fullState() {
    return this.list.every(item => item.goods_state)
  },

计算总价功能的实现

子组件

props: {
  isFull: {
    type: Boolean,
      default: true
  },
    totalPrices: {
      type: Number,
        default: 0
    }
},

<div>
    <span>合计:</span>
<span class="total-price">¥{{ totalPrices.toFixed(2) }}</span>
</div>

<!-- 结算按钮 -->
<button type="button" class="btn btn-primary btn-settle">结算({{ totalPrices.toFixed() }})</button>

父组件

computed: {
  //总价格
  amt() {
    // 先filter过滤,在reduce累加
    return this.list
        .filter(item => item.goods_state)
        //只有一行的箭头函数,可以省略return和{}花括号
        .reduce((total, item) =>
            (total += item.goods_price * item.goods_count),0)
  }
},

购买数量实现

和计算总价实现一个思路

  • 从集合中过滤出选中的商品
  • 取得选中商品的数量

取得数量之后,还需要和子组件共享数据,所以就用自定义属性来传递数据

computed: {
  //总数量
  totalQuantity() {
    return this.list
        .filter(item => item.goods_state)
        .reduce((total, item) => (total += item.goods_count), 0)
  }

子组件

<!-- 结算按钮 -->
<button type="button" class="btn btn-primary btn-settle">结算({{ totalNum}})</button>

  props: {
    totalNum:{
      type:Number,
      default:0
    }
  },

六、动态组件&插槽&自定义指令&axios

动态组件

什么是动态组件

动态组件指的是动态切换组件的显示与隐藏

如何实现动态组件渲染

vue 提供了一个内置的 组件,专门用来实现动态组件的渲染。示例代码如下:

【全栈第一课】Vue快速入门_vue.js_76

使用 keep-alive 保持状态

默认情况下,切换动态组件时无法保持组件的状态。此时可以使用 vue 内置的 组件保持动态组 件的状态。示例代码如下:

【全栈第一课】Vue快速入门_vue.js_77

keep-alive 对应的生命周期函数

当组件被缓存时,会自动触发组件的 deactivated 生命周期函数。

当组件被激活时,会自动触发组件的 activated 生命周期函数。

【全栈第一课】Vue快速入门_Vue_78

keep-alive 的 include 属性

include 属性用来指定:只有名称匹配的组件会被缓存。多个组件名之间使用英文的逗号分隔:

【全栈第一课】Vue快速入门_Vue_79

插槽

插槽(Slot)是 vue 为组件的封装者提供的能力。允许开发者在封装组件时,把不确定的、希望由用户指定的 部分定义为插槽。

【全栈第一课】Vue快速入门_Vue_80

可以把插槽认为是组件封装期间,为用户预留的内容的占位符。

体验插槽的基础用法

在封装组件时,可以通过 元素定义插槽,从而为用户预留内容占位符。示例代码如下:

【全栈第一课】Vue快速入门_vue.js_81

vue 官方规定:每一个 slot 插槽,都要有一个 name 名称–;
如果省略了 slot 的 name 属性,则有一个默认名称叫做 default

v-slot只能放在组件上和template上,放在其他上面会报错

默认情况下,在使用组件的时候,提供的内容都会被填充到名字为default 的插槽之中

【全栈第一课】Vue快速入门_javascript_82

为具名插槽提供内容

在向具名插槽提供内容的时候,我们可以在一个 <template>(包裹作用) 元素上使用 v-slot 指令,并以 v-slot 的参数的形式提供其名称。示例代码如下:

【全栈第一课】Vue快速入门_前端_83

具名插槽的简写形式

跟 v-on 和 v-bind 一样,v-slot 也有缩写,即把参数之前的所有内容 (v-slot:) 替换为字符 #。

例如 v-slot:header 可以被重写为 #header:

【全栈第一课】Vue快速入门_vue.js_84

作用域插槽

在封装组件的过程中,可以为预留的插槽绑定 props 数据,这种带有 props 数据的 叫做作用 域插槽

示例代码如下:

【全栈第一课】Vue快速入门_javascript_85

使用作用域插槽

可以使用 v-slot: 的形式,接收作用域插槽对外提供的数据。示例代码如下:

【全栈第一课】Vue快速入门_Vue_86

实例

【全栈第一课】Vue快速入门_vue.js_87

解构插槽 Prop

作用域插槽对外提供的数据对象,可以使用解构赋值简化数据的接收过程。

示例代码如下:

【全栈第一课】Vue快速入门_html_88

实例

【全栈第一课】Vue快速入门_Vue_89

自定义指令

什么是自定义指令

vue 官方提供了 v-text、v-for、v-model、v-if 等常用的指令。除此之外 vue 还允许开发者自定义指令。

自定义指令的分类

vue 中的自定义指令分为两类,分别是:

  • 私有自定义指令
  • 全局自定义指令

私有自定义指令

在每个 vue 组件中,可以在 directives 节点下声明私有自定义指令。示例代码如下:

【全栈第一课】Vue快速入门_Vue_90

使用自定义指令

在使用自定义指令时,需要加上 v- 前缀。示例代码如下

【全栈第一课】Vue快速入门_Vue_91

为自定义指令动态绑定参数值

为自定义指令动态绑定参数值

在 template 结构中使用自定义指令时,可以通过等号(=)的方式,为当前指令动态绑定参数值:

【全栈第一课】Vue快速入门_javascript_92

通过 binding 获取指令的参数值

在声明自定义指令时,可以通过形参中的第二个参数,来接收指令的参数值:

【全栈第一课】Vue快速入门_Vue_93

update 函数

bind 函数只调用 1 次:当指令第一次绑定到元素时调用,当 DOM 更新时 bind 函数不会被触发。 update 函 数会在每次 DOM 更新时被调用。示例代码如下:

【全栈第一课】Vue快速入门_javascript_94

函数简写

如果 insert 和update 函数中的逻辑完全相同,则对象格式的自定义指令可以简写成函数格式:

【全栈第一课】Vue快速入门_vue.js_95

全局自定义指令

全局共享的自定义指令需要通过“Vue.directive()”进行声明

示例代码如下:

【全栈第一课】Vue快速入门_html_96

把axios挂载到vue原型上

缺点是无法对api接口实现复用!

【全栈第一课】Vue快速入门_html_97

在其他组件上直接通过this.【全栈第一课】Vue快速入门_javascript_98http.post来发请求就行了

七、路由

是什么?

一组对应关系,在 SPA 项目中,不同功能之间的切换,要依赖于前端路由来完成

前端路由的工作方式

【全栈第一课】Vue快速入门_Vue_99

实现简易的前端路由

步骤1:通过 <component>标签,结合 comName 动态渲染组件。示例代码如下:

【全栈第一课】Vue快速入门_html_100

步骤2:在 App.vue 组件中,为 链接添加对应的 hash 值:

【全栈第一课】Vue快速入门_前端_101

步骤3:在 created 生命周期函数中,监听浏览器地址栏中 hash 地址的变化,动态切换要展示的组件的名称:

【全栈第一课】Vue快速入门_vue.js_102

vue-router 的基本用法

vue-router 是 vue.js 官方给出的路由解决方案。它只能结合 vue 项目进行使用,能够轻松的管理 SPA 项目 中组件的切换。

vue-router 的官方文档地址:https://router.vuejs.org/zh/

vue-router安装

在 vue2 的项目中,安装 vue-router 的命令如下:

npm i vue - [email protected] -S

创建路由模块

在 src 源代码目录下,新建 router/index.js 路由模块,并初始化如下的代码:

【全栈第一课】Vue快速入门_vue.js_103

导入并挂载路由模块

在 src/main.js 入口文件中,导入并挂载路由模块。示例代码如下:

【全栈第一课】Vue快速入门_javascript_104

声明路由链接和占位符

【全栈第一课】Vue快速入门_前端_105

声明路由的匹配规则

【全栈第一课】Vue快速入门_前端_106

路由重定向

路由重定向指的是:用户在访问地址 A 的时候,强制用户跳转到地址 C ,从而展示特定的组件页面。 通过路由规则的 redirect 属性,指定一个新的路由地址,可以很方便地设置路由的重定向:

【全栈第一课】Vue快速入门_javascript_107

嵌套路由

【全栈第一课】Vue快速入门_html_108

声明子路由链接和子路由占位符

【全栈第一课】Vue快速入门_前端_109

通过 children 属性声明子路由规则

【全栈第一课】Vue快速入门_html_110

动态路由匹配

动态路由指的是:把 Hash 地址中可变的部分定义为参数项,从而提高路由规则的复用性。 在 vue-router 中使用英文的冒号(:)来定义路由的参数项。示例代码如下:

【全栈第一课】Vue快速入门_Vue_111

$route.params 参数对象

【全栈第一课】Vue快速入门_前端_112

使用 props 接收路由参数

【全栈第一课】Vue快速入门_前端_113

声明式导航 & 编程式导航

vue-router 中的编程式导航 API

【全栈第一课】Vue快速入门_vue.js_114

$router.push

【全栈第一课】Vue快速入门_vue.js_115

$router.replace

【全栈第一课】Vue快速入门_前端_116

$router.go

【全栈第一课】Vue快速入门_html_117

$router.go 的简化用法

【全栈第一课】Vue快速入门_Vue_118

导航守卫

【全栈第一课】Vue快速入门_前端_119

全局前置守卫

什么是回调函数?

回调函数是一个参数,将这个函数作为参数传到另一个函数里面,当那个函数执行完之后,在执行传进去这个函数,这个过程就叫回调!

白话文:主函数的事先干完,回头在调用传进来的那个函数.

【全栈第一课】Vue快速入门_javascript_120

守卫方法的 3 个形参

【全栈第一课】Vue快速入门_前端_121

next 函数的 3 种调用方式

【全栈第一课】Vue快速入门_html_122

控制后台主页的访问权限

【全栈第一课】Vue快速入门_javascript_123

八、补充知识

URL种的#是什么意思?

#代表网页中的一个位置。

比如,http://www.example.com/index.html#print就代表网页index.html的print位置。浏览器读取这个URL后,会自动将print位置滚动至可视区域。

在VUE中,路由的实现方式有两种,其中一种就是通过#标识符进行页面内导航从而实现路由切换。

【全栈第一课】Vue快速入门_vue.js_124

HTTP请求不包括#

#是用来指导浏览器动作的,对服务器端完全无用。所以,HTTP请求中不包括#。
比如,访问下面的网址,http://www.example.com/index.html#print,浏览器实际发出的请求是这样的:

GET /index.html HTTP/1.1

Host: www.example.com

#后的字符

在第一个#后面出现的任何字符,都会被浏览器解读为位置标识符。这意味着,这些字符都不会被发送到服务器端。
比如,下面URL的原意是指定一个颜色值:http://www.example.com/?color=#fff,但是,浏览器实际发出的请求是:

GET /?color= HTTP/1.1
 
Host: www.example.com

改变#不触发网页重载

单单改变#后的部分,浏览器只会滚动到相应位置,不会重新加载网页。
比如,从http://www.example.com/index.html#location1改成http://www.example.com/index.html#location2,浏览器不会重新向服务器请求index.html。

说明同第一个,例如单页面应用SPA一样,路由的切换,不会重新加载页面,只是切换位置,或者切换组件;第二种应用就是在单个页面里面通过name和id切换当前显示的位置。

改变#会改变浏览器的访问历史

每一次改变#后的部分,都会在浏览器的访问历史中增加一个记录,使用"后退"按钮,就可以回到上一个位置。这对于ajax应用程序特别有用,可以用不同的#值,表示不同的访问状态,然后向用户给出可以访问某个状态的链接。值得注意的是,上述规则对IE 6和IE 7不成立,它们不会因为#的改变而增加历史记录。

说明:通过#的切换,是算在浏览器的访问历史中的,前进和后退都是生效的。

?说明

连接作用

通过?来带参数,连接域名和参数,经常会用到。

http://www.xxx.com/Show.asp?id=77&nameid=2905210001&page=1

清除缓存

http://www.xxxxx.com/index.html

http://www.xxxxx.com/index.html?test123123

两个url打开的页面一样,但是后面这个有问号,说明不调用缓存的内容,而认为是一个新地址,重新读取。

因为在做http请求的时候,如果浏览器检测到你的地址完全没变,会从缓存里读取先前请求过的数据,不再发送请求。有些时候是页面资源的加载,有些时候是API的get请求,都有可能。加上这个,会让浏览器认为这是一个新的地址,从而保证重新获取资源。

&说明

不同参数的间隔符

http://www.xxx.com/Show.asp?id=77&nameid=2905210001&page=1


标签:index,Vue,自定义,webpack,js,第一课,全栈,vue,组件
From: https://blog.51cto.com/u_14519396/8679999

相关文章

  • 【全栈第二课】微信小程序快速入门
    前言笔记大部分来自黑马程序员提供的ppt,部分来于自己总结一、起步简介小程序与普通网页开发的区别注册账号和微信开发者工具注册https://mp.weixin.qq.com/主体类型为个人开发工具https://developers.weixin.qq.com/miniprogram/dev/devtools/stable.html微信开发者工具页面组成小......
  • 手写类似于BetterScroll样式的左右联动菜单 uni-app+vue3+ts (使用了script setup语法
     注意:在模拟器用鼠标滚动是不会切换光标的,因为使用的是触摸滑动。【自定义类型贴在最后了】script部分如下:import{onMounted}from'vue'importtype{orderDetail}from'@/types/category'importtype{mainArr}from'@/types/main-arr'import{nextTick,ref}......
  • vue3使用::v-deep深度选择器不生效
    会出现 ::v-deepusageasacombinatorhasbeendeprecated.Use:deep(<inner-selector>)insteadof::v-deep<inner-selector>.的报错::v-depth用作组合子已被弃用。使用:deep(<内部选择器>)而不是::v-deep<内部选择器>。需要改成:deep(class),示例代码如下:deep(.el-checkbo......
  • Vue学习计划--Vue2(一)简单了解vue
    Vue2的终止支持时间为2023年12月31日。在这个矛盾的时间点,还是决定先把vue2的笔记放出来,在Vue2完结后再把Vue3的笔记补上。这样呢,2和3都不落下,也算是来一个启承的作用吧。在工作中呢,旧的项目可以维护,新的项目也可以上手。后续呢会有react16和react18、node、webpack、vite、以及实......
  • [Vue]按页数和行数重新计算表格序号
    转载自:https://blog.csdn.net/qq_48203828/article/details/123224024 1、 2、<el-table-columnlabel="序号"style="width:120px;height:50px"header-align="center"align="center"><templateslot-scope=&quo......
  • Vue3用户代码片段
    1.defineComponent语法{ "Printtoconsole":{ "prefix":"vue3", "body":[ "<template>", "<divclass=\"container\">", "", "</div>&q......
  • 在写springboot和vue时,需要改进的地方
    后端Springboot(1)需要更加熟练使用mysql语句,insertupdatedeleteselect(查询)(2)前后端跨域问题的解决: (3)另外在使用delete语句时,可以在路径中直接添加id,实现通过id删除数据例①未在路径中添加id  ②在路径中使用idpostman中样例:  使用id作为路径参数的注意事项:......
  • Jenkins自动化构建Vue项目的实践
    在现代的Web开发中,Vue.js已经成为一种非常流行的JavaScript框架。为了更高效地管理和部署Vue.js项目,使用自动化构建工具是至关重要的。Jenkins作为一款强大的持续集成和持续部署(CI/CD)工具,为我们提供了一种便捷的方式来自动化构建Vue.js项目。本文将介绍如何在Jenkins中配置和使用自......
  • vue 弹窗组件
    vue弹窗<el-dialog></el-dialog>可以在其中编写所需的弹窗显示的内容也可以在其中放组件标签作为弹窗放一个组件的话,例:<el-dialogv-model="addGoodsDialog":title="addGoodsTitle"width="60%"destroy-on-close="true":close-on-p......
  • vue 编辑器+使用场景+问题解决
    vue编辑器组件添加依赖"dependencies":{"@codemirror/autocomplete":"^6.4.2","@codemirror/commands":"^6.2.1","@codemirror/lang-javascript":"^6.0.2","@codemirror/lan......