Shu-How Zの小窝

Loading...

【vue3.x】2021最新版Vue全套课程#Web框架学习基础+Vue全家桶+Vue实战项目(已完结

https://www.bilibili.com/video/BV1Pz4y1S7Uv/?spm_id_from=333.788.recommend_more_video.1


P1课程说明.mp4
2016

React 绿唉

重新 微信小程序 uni-app
几天就好 我竟然月来 差 勤奋点 早点起床学 坚持

P2认识一下什么是NPM.mp4
npm(全称Node Package Manager,即node包管理器)
是Node.js默认的、以JavaScript编写的软件包管理系统
npm来分享和使用代码已经成了前端的标配

前端静态资源库

静态资源cdn

P3 NPM的安装.mp4
npm i npm -g 简写
npm install npm -g 升级版本

npm install jquery
npm install bootstrap

搭建环境时通过如下代码将npm设置成淘宝镜像
https://www.cnblogs.com/zixuan00/p/11197532.html
npm config get registry

桌面不行 其他目录行 权限不够

P4 NPM的基本使用.mp4
npm list 当前目录

npm list -g查看所有全局安装的模块
npm list vue查看某个模块的版本号
npm-g install npm@5.9.1(@后跟版本号)这样我们就可以更新npm版本
npm install-save moduleName
#-save在package文件的dependencies节点写入依赖.
npm update jquery 更新版本
npm uninstall jquery 卸载

P5 package.json文件属性详解.mp4
package.json文件中版本号的说明,安装的时候代表不同的含义:
"5.0.3"表示安装指定的5.0.3版本
"~5.0.3"表示安装5.0.X中最新的版本"^5.0.3"表示安装5.X.X中最新的版本

Package.json属性说明
name-包名。
version-包的版本号.
description-包的描述。
homepage-包的官网 url.
author-包的作者姓名。
contributors-包的其他贡献者姓名。
dependencies-依赖包列表,如果依赖包没有安装,npm会自动将依赖包安装在nodemodule目录下.
repository-包代码存放的地方的类型,可以是git或svn,git可在Github上。
main-main字段指定了程序的主入口文件,require('moduleName')就会加载这个文件。这个字段的默认值是模块目录下面的indexjs.
keywords 关键字

生成
>npm init --yes

npm init 选择名 填写

npm run test
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
运行里面的脚步

>npm run hello
"scripts": {
"test": "dir",
"hello": "node -v"
},


>npm install jquery --save


npm install
根据配置package-->dependencies/dev*文件下载node_modules文件

"dependencies": {
"jquery": "^3.6.0" ^更新^3.x.x ~更新^3.5.x 什么不写固定
},


P6 NPM安装的包使用.mp4
NPM提供了很多命令,例如install和publish,使用npm help可查看所有命令。
使用npm help <command>可查看某条命令的详细帮助,例如npm help install.
在package.json所在目录下使用npm install.-g可先在本地安装当前命令行程序,可用于发布前的本地测试。
使用npm update <package>可以把当前目录下node-modules子目录里边的对应模块更新至最新版本。
使用npm update <package> -g可以把全局安装的对应命令行程序更新至最新版。
使用npm cache clear可以清空NPM本地缓存,用于对付使用相同版本号发布新版本代码的人
使用npm unpublish <package>@<version>可以撤销发布自己发布过的某个版本代码。

CommonS中很大的一部分便是对模块系统的规范,
使用require语句导入包
新的ES6可以使用import导入包包
require import


$(function(){
alert('xxx')
})

module.exports=100
const $=require('jquery')
let num=require('./foo.js')
console.log(num)

fun(args).log 回车变--->console.log(fun(args))


module.exports=[10,2,5,5,6]
module.exports=function (args) {
let sum=0;
for(let i=0;i<args.length;i++){
sum+=args[i];
}
return sum
}
let nums=require('./foo.js')
const fun=require('./func')
console.log(fun(nums));

P7练习通过npm安装包来解决ES6语法兼容性问题
练习:ES6兼容性解决
兼容表:http://kangax.github.io/compat-table/es6/
IE10+,Chrome,FireFox、移动端、NodeJS现在都支持
兼容低版本浏览器
在线转换(这编译会加大页面渲染的时间)
提前编译(强烈建议这种方式,不影响浏览器渲染时间)
比较通用的工具方案有babel,jsx,traceur,es6-shim等。

IE10 控制台选择版本
前端静态资源库
https://cdn.baomitu.com/
https://www.cnblogs.com/ytkah/p/13869749.html

使用NPM全局安装babel-cli包. (babel -V)
npm install babel-cli -g

<script type="text/babel">
const name='学习园地'
console.log(name)
</script>

>npm install --save-dev babel-cli
>babel -V

.babelrc
{
{
"presets": ["es2015","stage-2"],//设置转换规则
"plugins": ["transform-runtime"] //设置插件
}
}

npm install babel-core babel-preset-es2015 babel-plugin-transform-runtime babel-preset-stage-2 --save-dev

"scripts": {
"test": "dir",
"hello": "node -v",
"build": "babel src -w -d lib"
},

npm run build

P8 NPM的竞品yarn的安装和使用mp4
"Yarn是由Facebook,Google,Exponent和Tilde联合推出了-
个新的JS包管理工具,正如官方文档中写的,Yarn是为了弥补npm的一些缺陷而出现的。因为NPM5以下会出现下面的问题:
-
npm install的时候巨慢。特别是新的项目拉下来要等半天,删除node modules,重新install的时候依旧如此。
同一个项目,多人开发时,由于安装的版本不一致出现bug官网:www.yarnpkg.com

npm install -g yarn
yarn --version
>yarn config set registry https://registry.npm.taobao.org -g
yarn config set sass_binary_site http://cdn.npm.taobao.org/dist/node-sass -g

yarn init //初始化项目同npm init,执行输入信息后,会生成packagejson文件
yarn install //安装packagejson里所有包,并将包及它的所有依赖项保存进yarn.lock
yarn install--flat /安装一个包的单一版本
yarn install--force /强制重新下载所有包
yarn install--production //只安装dependencies里的包
yarn install--no-lockfile //不读取或生成yarn.lock
yarn install--pure-lockfile//不生成yarn.lock
yarn add[package]//在当前的项目中添加一个依赖包,会自动更新到package.json和yarn.lock文件中
yarn add[package]@[version]//安装指定版本,这里指的是主要版本,如果需要精确到小版本,使用-E参数
yarn add[packagel]@[tag]//安装某个taq(比如beta,next或者latest)
yarn add--dev/-D //加到 devDependencies
yarn add--peer/-P //加到 peerDependencies
yarn add-optional/-O //到optionalDependencies


>yarn add jquery
"dependencies" 运行时依赖
>yarn add jquery --dev
"devDependencies" 开发时依赖
>yarn remove jquery

yarn upgrade
更新版本
yarn run

yarn的基本使用 查中文


速度快
安装版本统一
更简洁的输出
多注册来源处理
更好的语义化


P9 webpack的学习目标mp4

初识webpack5
webpack安装和基本体验
webpack的五个核心概念
打包样式资源
打包HTML资源
打包图片资源
打包基他资源
devServer配置与应用
配置可用的基本开发环境
开发环境优化
生产环境优化
》webpack配置文件内容详解
》配置标准的开发和生产环境案例
》配置jQuery+ BootStrap的开发环境


P10认识和了解webpack的工作原理
webpack web拍

认识webpack5
webpack是一个模块打包器(构建工具),它的主要目标是将JavaScript文件打包在一起,
打包后的文件用于在浏览器中使用,但它也能够胜任转换(transform)、
打包(bundle)或包裹(package)任何资源(resource or asset).

官网:https://webpack.js.org/中文文档:https://webpack.docschina.org/

P11 webpack的安装和体验mp4
进入目录初始化NPM操作 npm init -y
安装webpack及webpack-cli:npm install webpack webpack-cli --D

--D == --save-dev

development
production

控制台运行命令:webpack --mode-development(开发环境)
控制台运行命令:webpack --mode-production(生产环境)

webpack -v

import x from './ddd' es6
require('./ss') conmmod

const {n,add,demo} =require('./one')
解构

先找index.js
src

报错 重新打开终端
报错 node使用lts长期版本 14.18.1

dist距离

webstrom
格式代码
ctrl+alt+L


P12 webpack的核心概念mp4

webpack ./src/index.js -o ./build/build.js --mode development
原目录文件 -o输出文件

package.json script命令出也行


默认文件名 没就要指定
webpack.config.js
{
//处理路径函数
const {resolve}=require('path')
module.exports={
entry: './src/index.js',//入口文件
output: { //输出文件目录 文件名字
filename: "build.js",
path: resolve(__dirname,'build') //(当前目录,生成目录名字)
},
//loader 处理css img
module: {
rules: [

]
},
//plugins插件
plugins: [],
mode:'production'
}
}
直接命令 >webpack

里面写的内容
entry 入口(entry)指示webpack以哪个文件作为入口起点开始打包,分析构建内部依赖图。
output 输出(output)指示webpack打包后的资源bundles输出到哪里,以及如何命名。
loader loader让webpack能够去处理那些非JavaScript资源css.img等,将它们处理成webpack能够识别的资源可以理解成一个翻译过程(webpack自身只能理解js和json)
plugins 插件(plugins)可用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量等。
模式(mode)指示webpack使用相应模式的配置。
开发模式(development):配置比较简单,能让代码本地调试运行的环境。
生产模式(production):代码需要不断优化达到性能最好。能让代码优化上线运行的环境。
都会自动启用一些插件,生产模式使用插件更多

module.exports commonjs规范

P13 多入口和 多出口的情况配置.mp4
//处理路径函数
const {resolve}=require('path')
module.exports={
//单入口,如果只有一个入口,使用字符串,指定一个入口文件,打包一个chunk,输出一个bundle,chunk的名称是默认
entry: './src/index.js',//入口文件

//Array,多入口,写多个入口文件,所有的入口文件形成一个chunk,名称是默认的,输出也是只有一个bundle
// entry:['./src/index.js','./src/main.js'],

//Object 多入口。有几个入口文件就会生成几个chunk,并翰出几个bundle,chunk的名称是key
/*entry:{
one:'./src/index.js',
two:'./src/main.js'
},*/

//特殊用法 多入口。有几个入口文件就会生成几个chunk,并翰出几个bundle,chunk的名称是key
/*entry:{
//Array,多入口,写多个入口文件,所有的入口文件形成一个chunk,名称是默认的,输出也是只有一个bundle
onea:['./src/main.js','./src/index.js'],
twob:'./src/index.js'
},*/

output: { //输出文件目录 文件名字
filename: "[name].js",//多个出口 加[name] 单个默认main
path: resolve(__dirname,'build') //(当前目录,生成目录名字)
},
//loader 处理css img
module: {
rules: [

]
},
//plugins插件
plugins: [],
mode:'production'
}


P14打包和压缩HTML资源mp4

插件 html-webpack-plugins
1·下载2.引入 3使用
npm i html-webpack-plugins -D
const HtmlWebpackPlugin=require('html-webpack-plugins')
plugins: [
//默以会创建一个空的,目的就是自动引入打包的资源(js/css)
new HtmlWebpackPlugin({
template:'./src/index.html',
filename: 'demo.html',
//压缩html代码
minify:{
//移除空格
collapseWhitespace:true,
//移除注释
removeComments:true
}
})
]

压缩JS和HTML代码
JS代码只需设置成生产模式(production)模式,会自动压缩

P15 webpack打包多个HTML文件开发案例
19
webpack.config.js
{
//处理路径函数
const {resolve}=require('path');
const HtmlWebpackPlugin=require('html-webpack-plugins');
module.exports={
//单入口,如果只有一个入口,使用字符串,指定一个入口文件,打包一个chunk,输出一个bundle,chunk的名称是默认
// entry: './src/index.js',//入口文件

//Array,多入口,写多个入口文件,所有的入口文件形成一个chunk,名称是默认的,输出也是只有一个bundle
// entry:['./src/index.js','./src/main.js'],

//Object 多入口。有几个入口文件就会生成几个chunk,并翰出几个bundle,chunk的名称是key
/*entry:{
one:'./src/index.js',
two:'./src/main.js'
},*/

//特殊用法 多入口。有几个入口文件就会生成几个chunk,并翰出几个bundle,chunk的名称是key
/*entry:{
//Array,多入口,写多个入口文件,所有的入口文件形成一个chunk,名称是默认的,输出也是只有一个bundle
onea:['./src/main.js','./src/index.js'],
twob:'./src/index.js'
},*/

entry:{
vendor:['./src/js/jquery','./src/js/common.js'],//如果用库 直接jquery 现在模拟要加路径
index:"./src/js/index.js",
cart:'./src/js/cart.js'
},

output: { //输出文件目录 文件名字
// publicPath: "/",
filename: "[name].js",//多个出口 加[name] 单个默认main
path: resolve(__dirname,'build') //(当前目录,生成目录名字)
},
//loader 处理css img
module: {
rules: [

]
},
//plugins插件
plugins: [
//默以会创建一个空的,目的就是自动引入打包的资源(js/css)
// new HtmlWebpackPlugin(
// // {
// // template:'./src/index.html',
// // filename: 'index.html',
// //chunks:['index','vendor'],//指定要加入的js
// // //压缩html代码
// // minify:{
// // //移除空格
// // collapseWhitespace:true,
// // //移除注释
// // removeComments:true
// // }
// // }
// ),
// new HtmlWebpackPlugin(
// // {
// // template:'./src/cart.html',
// // filename: 'cart.html',
// //chunks:['cart','vendor']
// // }
// )
],
mode:'development' //production development
}
}


P16使用webpack打包CSS资源mp4

1.css-loader的作用是处理css中的@import和url这样的外部资源
2.style-loader的作用是把样式插入到DOM中,方法是在head中插入一个style标签,并把样式写入到这个标签的innerHTML里

npm i css-loader style-loader -D
webpack

stylesheet---css

插入js里去 运行也可以

js
require('./style.css')
console.log('index');

webpack.config.js
{
//处理路径函数
const {resolve}=require('path');
const HtmlWebpackPlugin=require('html-webpack-plugins');
module.exports={
//单入口,如果只有一个入口,使用字符串,指定一个入口文件,打包一个chunk,输出一个bundle,chunk的名称是默认
entry: './src/index.js',//入口文件

//Array,多入口,写多个入口文件,所有的入口文件形成一个chunk,名称是默认的,输出也是只有一个bundle
// entry:['./src/index.js','./src/main.js'],

//Object 多入口。有几个入口文件就会生成几个chunk,并翰出几个bundle,chunk的名称是key
/*entry:{
one:'./src/index.js',
two:'./src/main.js'
},*/

//特殊用法 多入口。有几个入口文件就会生成几个chunk,并翰出几个bundle,chunk的名称是key
/*entry:{
//Array,多入口,写多个入口文件,所有的入口文件形成一个chunk,名称是默认的,输出也是只有一个bundle
onea:['./src/main.js','./src/index.js'],
twob:'./src/index.js'
},*/

output: { //输出文件目录 文件名字
// publicPath: "/",
filename: "[name].js",//多个出口 加[name] 单个默认main
path: resolve(__dirname,'build') //(当前目录,生成目录名字)
},
//loader 处理css img
module: {
rules: [
//一个loader {loader:'style-loader'}
{test: /\.css$/,use:['style-loader','css-loader']} //从右到左 先加载再插入
]
},
//plugins插件
plugins: [
//默以会创建一个空的,目的就是自动引入打包的资源(js/css)
/*new HtmlWebpackPlugin(
{
template:'./src/index.html',
filename: 'index.html',
}
)*/
],
mode:'development' //production development
}
}


P17 使用webpack打包less和sass资源
下载
less less-loader
sass node-sass sass-loader

>npm i less less-loader -D

js
require('./style.css')
require('./lessstyle.less')
require('./stylesass.scss')
console.log('index');

less
{
@width:200px;
@height:200px;
@color:red;

#box2{
width:@width;
height: @height;
background: @color;
color: green;
}
}

sass
{
$width:100px;
$height:100px;
#box3{
width: 100px*3;
height: $height*2;
background: blue;
color: yellow;
}
}

webpack.config.js
{
//处理路径函数
const {resolve}=require('path');
const HtmlWebpackPlugin=require('html-webpack-plugins');
module.exports={
//单入口,如果只有一个入口,使用字符串,指定一个入口文件,打包一个chunk,输出一个bundle,chunk的名称是默认
entry: './src/index.js',//入口文件

//Array,多入口,写多个入口文件,所有的入口文件形成一个chunk,名称是默认的,输出也是只有一个bundle
// entry:['./src/index.js','./src/main.js'],

//Object 多入口。有几个入口文件就会生成几个chunk,并翰出几个bundle,chunk的名称是key
/*entry:{
one:'./src/index.js',
two:'./src/main.js'
},*/

//特殊用法 多入口。有几个入口文件就会生成几个chunk,并翰出几个bundle,chunk的名称是key
/*entry:{
//Array,多入口,写多个入口文件,所有的入口文件形成一个chunk,名称是默认的,输出也是只有一个bundle
onea:['./src/main.js','./src/index.js'],
twob:'./src/index.js'
},*/

output: { //输出文件目录 文件名字
// publicPath: "/",
filename: "[name].js",//多个出口 加[name] 单个默认main
path: resolve(__dirname,'build') //(当前目录,生成目录名字)
},
//loader 处理css img
module: {
rules: [
//一个loader {loader:'style-loader'}
{test: /\.css$/,use:['style-loader','css-loader']} ,//从右到左 先加载再插入
{test: /\.less$/,use:['style-loader','css-loader','less-loader']} ,//从右到左 先加载再插入
{test: /\.scss$/,use:['style-loader','css-loader','less-loader','sass-loader']}
]
},
//plugins插件
plugins: [
//默以会创建一个空的,目的就是自动引入打包的资源(js/css)
/*new HtmlWebpackPlugin(
{
template:'./src/index.html',
filename: 'index.html',
}
)*/
],
mode:'development' //production development
}
}


P18提取CSS为单独文件.mp4
插件
mini-css-extract-plugin
>npm i mini-css-extract-plugin -D

const MiniCssExtractPlugin=require('mini-css-extract-plugin')
module: {
rules: [
//一个loader {loader:'style-loader'}
// {test: /\.css$/,use:['style-loader','css-loader']} ,//从右到左 先加载再插入
{test: /\.css$/,use:[MiniCssExtractPlugin.loader,'css-loader']}
{test: /\.less$/,use:['style-loader','css-loader','less-loader']} ,//从右到左 先加载再插入
// {test: /\.scss$/,use:['style-loader','css-loader','less-loader','sass-loader']}
]
},

webpack.config.js
{
//处理路径函数
const {resolve}=require('path');
const HtmlWebpackPlugin=require('html-webpack-plugins');
const MiniCssExtractPlugin=require('mini-css-extract-plugin')
module.exports={
//单入口,如果只有一个入口,使用字符串,指定一个入口文件,打包一个chunk,输出一个bundle,chunk的名称是默认
entry: './src/index.js',//入口文件

//Array,多入口,写多个入口文件,所有的入口文件形成一个chunk,名称是默认的,输出也是只有一个bundle
// entry:['./src/index.js','./src/main.js'],

//Object 多入口。有几个入口文件就会生成几个chunk,并翰出几个bundle,chunk的名称是key
/*entry:{
one:'./src/index.js',
two:'./src/main.js'
},*/

//特殊用法 多入口。有几个入口文件就会生成几个chunk,并翰出几个bundle,chunk的名称是key
/*entry:{
//Array,多入口,写多个入口文件,所有的入口文件形成一个chunk,名称是默认的,输出也是只有一个bundle
onea:['./src/main.js','./src/index.js'],
twob:'./src/index.js'
},*/

output: { //输出文件目录 文件名字
// publicPath: "/",
filename: "[name].js",//多个出口 加[name] 单个默认main
path: resolve(__dirname,'build') //(当前目录,生成目录名字)
},
//loader 处理css img
module: {
rules: [
//一个loader {loader:'style-loader'}
// {test: /\.css$/,use:['style-loader','css-loader']} ,//从右到左 先加载再插入
{test: /\.css$/,use:[MiniCssExtractPlugin.loader,'css-loader']},
{test: /\.less$/,use:[MiniCssExtractPlugin.loader,'css-loader','less-loader']} ,//从右到左 先加载再插入
// {test: /\.scss$/,use:['style-loader','css-loader','less-loader','sass-loader']}
]
},
//plugins插件
plugins: [
//默以会创建一个空的,目的就是自动引入打包的资源(js/css)
/*new HtmlWebpackPlugin(
{
template:'./src/index.html',
filename: 'index.html',
}
),*/
new MiniCssExtractPlugin({
filename: 'demo.css'
})
],
mode:'development' //production development
}
}


P19 处理CSS的浏览器兼容性
使用postcss处理
post-loader postcss-preset-env
npm -i post-loader postcss-preset-env -D

postcss会找到package.json中的browserslist里面的配置,通过配置加载css的兼容性
修改loader的配置,新版需要写postcss.configjs,less和sass兼容性同理


package.json
"browserslist": [
"> 0.2%","last 2 versions","not dead"
]

webpack.config.js
{
//处理路径函数
const {resolve}=require('path');
const HtmlWebpackPlugin=require('html-webpack-plugins');
const MiniCssExtractPlugin=require('mini-css-extract-plugin')
module.exports={
//单入口,如果只有一个入口,使用字符串,指定一个入口文件,打包一个chunk,输出一个bundle,chunk的名称是默认
entry: './src/index.js',//入口文件

//Array,多入口,写多个入口文件,所有的入口文件形成一个chunk,名称是默认的,输出也是只有一个bundle
// entry:['./src/index.js','./src/main.js'],

//Object 多入口。有几个入口文件就会生成几个chunk,并翰出几个bundle,chunk的名称是key
/*entry:{
one:'./src/index.js',
two:'./src/main.js'
},*/

//特殊用法 多入口。有几个入口文件就会生成几个chunk,并翰出几个bundle,chunk的名称是key
/*entry:{
//Array,多入口,写多个入口文件,所有的入口文件形成一个chunk,名称是默认的,输出也是只有一个bundle
onea:['./src/main.js','./src/index.js'],
twob:'./src/index.js'
},*/

output: { //输出文件目录 文件名字
// publicPath: "/",
filename: "[name].js",//多个出口 加[name] 单个默认main
path: resolve(__dirname,'build') //(当前目录,生成目录名字)
},
//loader 处理css img
module: {
rules: [
//一个loader {loader:'style-loader'}
// {test: /\.css$/,use:['style-loader','css-loader']} ,//从右到左 先加载再插入
{test: /\.css$/,use:[MiniCssExtractPlugin.loader,'css-loader','postcss-loader']}, //postcss-loader先转才其他
{test: /\.less$/,use:[MiniCssExtractPlugin.loader,'css-loader','less-loader','postcss-loader']} ,//从右到左 先加载再插入
// {test: /\.scss$/,use:['style-loader','css-loader','less-loader','sass-loader','postcss-loader']}
]
},
//plugins插件
plugins: [
//默以会创建一个空的,目的就是自动引入打包的资源(js/css)
/*new HtmlWebpackPlugin(
{
template:'./src/index.html',
filename: 'index.html',
}
),*/
new MiniCssExtractPlugin({
filename: 'demo.css'
})
],
mode:'development' //production development
}
}

postcss.config.js
{
module.exports={
plugins:[
require('postcss-preset-env')()
]
}
}

P20压缩CSS内容.mp4
24
插件
optimize-css-assets-webpack-plugin
const OptimizeCssAssetsWebpackPlugin=require('optimize-css-assets-webpack-plugin')

plugins:[
new OptimizeCssAssetsWebpackPlugin()
]

P21 webpack打包图片资源mp4
url-loader file-loader
在css引入图片

在html使用图片 下载 html-loader
>npm i url-loader file-loader -D
>npm i html-loader -D
webpack.config.js
{
//处理路径函数
const {resolve}=require('path');
const HtmlWebpackPlugin=require('html-webpack-plugins');
const MiniCssExtractPlugin=require('mini-css-extract-plugin')
const OptimizeCssAssetsWebpackPlugin=require('optimize-css-assets-webpack-plugin')
module.exports={
//单入口,如果只有一个入口,使用字符串,指定一个入口文件,打包一个chunk,输出一个bundle,chunk的名称是默认
entry: './src/index.js',//入口文件

//Array,多入口,写多个入口文件,所有的入口文件形成一个chunk,名称是默认的,输出也是只有一个bundle
// entry:['./src/index.js','./src/main.js'],

//Object 多入口。有几个入口文件就会生成几个chunk,并翰出几个bundle,chunk的名称是key
/*entry:{
one:'./src/index.js',
two:'./src/main.js'
},*/

//特殊用法 多入口。有几个入口文件就会生成几个chunk,并翰出几个bundle,chunk的名称是key
/*entry:{
//Array,多入口,写多个入口文件,所有的入口文件形成一个chunk,名称是默认的,输出也是只有一个bundle
onea:['./src/main.js','./src/index.js'],
twob:'./src/index.js'
},*/

output: { //输出文件目录 文件名字
// publicPath: "/",
filename: "[name].js",//多个出口 加[name] 单个默认main
path: resolve(__dirname,'build') //(当前目录,生成目录名字)
},
//loader 处理css img
module: {
rules: [
//一个loader {loader:'style-loader'}
// {test: /\.css$/,use:['style-loader','css-loader']} ,//从右到左 先加载再插入
// {test: /\.css$/,use:[MiniCssExtractPlugin.loader,'css-loader','postcss-loader']}, //postcss-loader先转才其他
{test: /\.css$/,use:[MiniCssExtractPlugin.loader,'css-loader']},
{test: /\.less$/,use:[MiniCssExtractPlugin.loader,'css-loader','less-loader']} ,//从右到左 先加载再插入
// {test: /\.scss$/,use:['style-loader','css-loader','less-loader','sass-loader','postcss-loader']}
// {test: /\.(png|jpg|jpeg|gif)$/,use:['url-loader',{loader: "file-loader", options: {}}]}
{
test: /\.(png|jpg|jpeg|gif)$/,
loader: 'url-loader',
options: {
publicPath:'./images/',
outputPath:'images/',
limit:1024*8,
name:'[name][hash:10].[ext]'
}
},
{
test: /\.html$/,
loader: 'html-loader'
}
]
},
//plugins插件
plugins: [
//默以会创建一个空的,目的就是自动引入打包的资源(js/css)
/*new HtmlWebpackPlugin(
{
template:'./src/index.html',
filename: 'index.html',
}
),*/
new MiniCssExtractPlugin({
filename: 'demo.css'
}),
new OptimizeCssAssetsWebpackPlugin()
],
mode:'production' //production development
}
}

P22打包其他资源字体图标.mp4
iconfont.cn
不需要优化和压缩处理,直接输出的资源,称为其他资源。
ctrl=d复制一行
require('./iconfont.css')

{
//处理路径函数
const {resolve}=require('path');
const HtmlWebpackPlugin=require('html-webpack-plugins');
const MiniCssExtractPlugin=require('mini-css-extract-plugin')
const OptimizeCssAssetsWebpackPlugin=require('optimize-css-assets-webpack-plugin')
module.exports={
//单入口,如果只有一个入口,使用字符串,指定一个入口文件,打包一个chunk,输出一个bundle,chunk的名称是默认
entry: './src/index.js',//入口文件

//Array,多入口,写多个入口文件,所有的入口文件形成一个chunk,名称是默认的,输出也是只有一个bundle
// entry:['./src/index.js','./src/main.js'],

//Object 多入口。有几个入口文件就会生成几个chunk,并翰出几个bundle,chunk的名称是key
/*entry:{
one:'./src/index.js',
two:'./src/main.js'
},*/

//特殊用法 多入口。有几个入口文件就会生成几个chunk,并翰出几个bundle,chunk的名称是key
/*entry:{
//Array,多入口,写多个入口文件,所有的入口文件形成一个chunk,名称是默认的,输出也是只有一个bundle
onea:['./src/main.js','./src/index.js'],
twob:'./src/index.js'
},*/

output: { //输出文件目录 文件名字
// publicPath: "/",
filename: "[name].js",//多个出口 加[name] 单个默认main
path: resolve(__dirname,'build') //(当前目录,生成目录名字)
},
//loader 处理css img
module: {
rules: [
//一个loader {loader:'style-loader'}
// {test: /\.css$/,use:['style-loader','css-loader']} ,//从右到左 先加载再插入
// {test: /\.css$/,use:[MiniCssExtractPlugin.loader,'css-loader','postcss-loader']}, //postcss-loader先转才其他
{test: /\.css$/,use:[MiniCssExtractPlugin.loader,'css-loader']},
{test: /\.less$/,use:[MiniCssExtractPlugin.loader,'css-loader','less-loader']} ,//从右到左 先加载再插入
// {test: /\.scss$/,use:['style-loader','css-loader','less-loader','sass-loader','postcss-loader']}
// {test: /\.(png|jpg|jpeg|gif)$/,use:['url-loader',{loader: "file-loader", options: {}}]}
{
test: /\.(png|jpg|jpeg|gif)$/,
loader: 'url-loader',
options: {
publicPath:'./images/',
outputPath:'images/',
limit:1024*8,
name:'[name][hash:10].[ext]'
}
},
{
test: /\.html$/,
loader: 'html-loader'
},
//排除法
{
exclude: /\.(js|json|html|css|less|scss|png|gif|jpg|jpeg)$/,
loader: 'file-loader',
options: {
outputPath:'font/',//输出目录
publicPath:'./font',//到这目录找
name:'[name][hash:8].[ext]'
}
}
]
},
//plugins插件
plugins: [
//默以会创建一个空的,目的就是自动引入打包的资源(js/css)
/*new HtmlWebpackPlugin(
{
template:'./src/index.html',
filename: 'index.html',
}
),*/
new MiniCssExtractPlugin({
filename: 'demo.css'
}),
new OptimizeCssAssetsWebpackPlugin()
],
mode:'production' //production development
}
}


P23对js语法配置eslint进行检查mp4
风格
eslint-loader
eslint-config-airhnb-base
eslint-plugin-import

npm i eslint-loader eslint eslint-config-airbnb-base eslint-plugin-import -D

package.json
"eslintConfig": {
"extends": "airbnb-base"
}

webpack.config.js
{
//eslint只检查js语法
test: /\.js$/,
//只检查自己写的代码,不检查第三方库的代码
exclude: /node_modules/,
loader: 'eslint-loader',
options: {
fix:true
}
}
js
//下行eslint所有规则无效
//eslint-disable-next-line
console.log('index');

P24配置开发服务器devServer.mp4
webpack-dev-server
npx webpack serve 本目录执行
webpack5无法刷新 添加target:'web'

>npm i webpack-dev-server -D
>webpack serve
>webpack serve --port 299

webpack.config.js
{
//处理路径函数
const {resolve}=require('path');
const HtmlWebpackPlugin=require('html-webpack-plugins');
const MiniCssExtractPlugin=require('mini-css-extract-plugin')
const OptimizeCssAssetsWebpackPlugin=require('optimize-css-assets-webpack-plugin')
module.exports={
//单入口,如果只有一个入口,使用字符串,指定一个入口文件,打包一个chunk,输出一个bundle,chunk的名称是默认
entry: './src/index.js',//入口文件

//Array,多入口,写多个入口文件,所有的入口文件形成一个chunk,名称是默认的,输出也是只有一个bundle
// entry:['./src/index.js','./src/main.js'],

//Object 多入口。有几个入口文件就会生成几个chunk,并翰出几个bundle,chunk的名称是key
/*entry:{
one:'./src/index.js',
two:'./src/main.js'
},*/

//特殊用法 多入口。有几个入口文件就会生成几个chunk,并翰出几个bundle,chunk的名称是key
/*entry:{
//Array,多入口,写多个入口文件,所有的入口文件形成一个chunk,名称是默认的,输出也是只有一个bundle
onea:['./src/main.js','./src/index.js'],
twob:'./src/index.js'
},*/

output: { //输出文件目录 文件名字
// publicPath: "/",
filename: "[name].js",//多个出口 加[name] 单个默认main
path: resolve(__dirname,'build') //(当前目录,生成目录名字)
},
//loader 处理css img
module: {
rules: [
//一个loader {loader:'style-loader'}
// {test: /\.css$/,use:['style-loader','css-loader']} ,//从右到左 先加载再插入
// {test: /\.css$/,use:[MiniCssExtractPlugin.loader,'css-loader','postcss-loader']}, //postcss-loader先转才其他
{test: /\.css$/,use:[MiniCssExtractPlugin.loader,'css-loader']},
{test: /\.less$/,use:[MiniCssExtractPlugin.loader,'css-loader','less-loader']} ,//从右到左 先加载再插入
// {test: /\.scss$/,use:['style-loader','css-loader','less-loader','sass-loader','postcss-loader']}
// {test: /\.(png|jpg|jpeg|gif)$/,use:['url-loader',{loader: "file-loader", options: {}}]}
{
test: /\.(png|jpg|jpeg|gif)$/,
loader: 'url-loader',
options: {
publicPath:'./images/',
outputPath:'images/',
limit:1024*8,
name:'[name][hash:10].[ext]'
}
},
{
test: /\.html$/,
loader: 'html-loader'
},
//排除法
{
exclude: /\.(js|json|html|css|less|scss|png|gif|jpg|jpeg)$/,
loader: 'file-loader',
options: {
outputPath:'font/',//输出目录
publicPath:'./font',//到这目录找
name:'[name][hash:8].[ext]'
}
},
// {
// //eslint只检查js语法
// test: /\.js$/,
// //只检查自己写的代码,不检查第三方库的代码
// exclude: /node_modules/,
// loader: 'eslint-loader',
// options: {
// fix:true
// }
// }
]
},
//plugins插件
plugins: [
//默以会创建一个空的,目的就是自动引入打包的资源(js/css)
/*new HtmlWebpackPlugin(
{
template:'./src/index.html',
filename: 'index.html',
}
),*/
new MiniCssExtractPlugin({
filename: 'demo.css'
}),
new OptimizeCssAssetsWebpackPlugin()
],
//webpack5需要加上这个配置项才可以自动刷新
target: "web",
devServer: {
port:3001,
compress:true,
open:true
}
// mode:'production' //production development
}
}

package.json
{
{
"name": "webpack",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack serve --mode development",
"build": "webpack --mode production"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"css-loader": "^6.4.0",
"file-loader": "^6.2.0",
"html-loader": "^3.0.0",
"html-webpack-plugins": "^3.0.0",
"less": "^4.1.2",
"less-loader": "^10.2.0",
"mini-css-extract-plugin": "^2.4.3",
"optimize-css-assets-webpack-plugin": "^6.0.1",
"style-loader": "^3.3.1",
"url-loader": "^4.1.1",
"webpack": "^5.59.1",
"webpack-cli": "^4.9.1",
"webpack-dev-server": "^4.3.1"
},
"browserslist": [
"> 0.2%",
"last 2 versions",
"not dead"
],
"eslintConfig": {
"extends": "airbnb-base"
}
}

}

npm run dev
npm run build

P25开发环境的优化HMR模块热替换
29
环境的优化
»开发环境的优化
打包构建速度
优化代码调式
»生产环境的优化
代码运行的性能

{
//处理路径函数
const {resolve}=require('path');
const HtmlWebpackPlugin=require('html-webpack-plugins');
const MiniCssExtractPlugin=require('mini-css-extract-plugin')
const OptimizeCssAssetsWebpackPlugin=require('optimize-css-assets-webpack-plugin')
module.exports={
//单入口,如果只有一个入口,使用字符串,指定一个入口文件,打包一个chunk,输出一个bundle,chunk的名称是默认
entry: ['./src/index.js','./src/index.html'],//入口文件

//Array,多入口,写多个入口文件,所有的入口文件形成一个chunk,名称是默认的,输出也是只有一个bundle
// entry:['./src/index.js','./src/main.js'],

//Object 多入口。有几个入口文件就会生成几个chunk,并翰出几个bundle,chunk的名称是key
/*entry:{
one:'./src/index.js',
two:'./src/main.js'
},*/

//特殊用法 多入口。有几个入口文件就会生成几个chunk,并翰出几个bundle,chunk的名称是key
/*entry:{
//Array,多入口,写多个入口文件,所有的入口文件形成一个chunk,名称是默认的,输出也是只有一个bundle
onea:['./src/main.js','./src/index.js'],
twob:'./src/index.js'
},*/

output: { //输出文件目录 文件名字
// publicPath: "/",
filename: "[name].js",//多个出口 加[name] 单个默认main
path: resolve(__dirname,'build') //(当前目录,生成目录名字)
},
//loader 处理css img
module: {
rules: [
//一个loader {loader:'style-loader'}
// {test: /\.css$/,use:['style-loader','css-loader']} ,//从右到左 先加载再插入
// {test: /\.css$/,use:[MiniCssExtractPlugin.loader,'css-loader','postcss-loader']}, //postcss-loader先转才其他
{test: /\.css$/,use:[MiniCssExtractPlugin.loader,'css-loader']},
{test: /\.less$/,use:[MiniCssExtractPlugin.loader,'css-loader','less-loader']} ,//从右到左 先加载再插入
// {test: /\.scss$/,use:['style-loader','css-loader','less-loader','sass-loader','postcss-loader']}
// {test: /\.(png|jpg|jpeg|gif)$/,use:['url-loader',{loader: "file-loader", options: {}}]}
{
test: /\.(png|jpg|jpeg|gif)$/,
loader: 'url-loader',
options: {
publicPath:'./images/',
outputPath:'images/',
limit:1024*8,
name:'[name][hash:10].[ext]'
}
},
{
test: /\.html$/,
loader: 'html-loader'
},
//排除法
{
exclude: /\.(js|json|html|css|less|scss|png|gif|jpg|jpeg)$/,
loader: 'file-loader',
options: {
outputPath:'font/',//输出目录
publicPath:'./font',//到这目录找
name:'[name][hash:8].[ext]'
}
},
// {
// //eslint只检查js语法
// test: /\.js$/,
// //只检查自己写的代码,不检查第三方库的代码
// exclude: /node_modules/,
// loader: 'eslint-loader',
// options: {
// fix:true
// }
// }
]
},
//plugins插件
plugins: [
//默以会创建一个空的,目的就是自动引入打包的资源(js/css)
/*new HtmlWebpackPlugin(
{
template:'./src/index.html',
filename: 'index.html',
}
),*/
new MiniCssExtractPlugin({
filename: 'demo.css'
}),
new OptimizeCssAssetsWebpackPlugin()
],
//webpack5需要加上这个配置项才可以自动刷新
target: "web",
devServer: {
port:3001,
compress:true,
open:true,
hot:true
}
// mode:'production' //production development
}
}

{
require('./style.css')
require('./lessstyle.less')
require('./iconfont.css')
// require('./stylesass.scss')
const {demo}=require('./print')

demo()
//下行eslint所有规则无效
//eslint-disable-next-line
console.log('index');

if (module.hot){
module.hot.accept('./print.js',function () {
console.log('print.js这个文件内容有改变')
demo()
})
}
}

P26去除项目里的死代码(无用的js和css代码)
tree-shaking js
1·必须使用es6模块化,2.开启production环境

purgecss-webpack-plugin css
{
//处理路径函数
const {resolve,john}=require('path');
// const glob=require('glob')
// const PATHS={src:join(__dirname,'src')}
// const PurgecssPlugin=require('purgecss-webpack-plugin')

const HtmlWebpackPlugin=require('html-webpack-plugins');
const MiniCssExtractPlugin=require('mini-css-extract-plugin')
const OptimizeCssAssetsWebpackPlugin=require('optimize-css-assets-webpack-plugin')
module.exports={
//单入口,如果只有一个入口,使用字符串,指定一个入口文件,打包一个chunk,输出一个bundle,chunk的名称是默认
entry: ['./src/index.js'],//入口文件

//Array,多入口,写多个入口文件,所有的入口文件形成一个chunk,名称是默认的,输出也是只有一个bundle
// entry:['./src/index.js','./src/main.js'],

//Object 多入口。有几个入口文件就会生成几个chunk,并翰出几个bundle,chunk的名称是key
/*entry:{
one:'./src/index.js',
two:'./src/main.js'
},*/

//特殊用法 多入口。有几个入口文件就会生成几个chunk,并翰出几个bundle,chunk的名称是key
/*entry:{
//Array,多入口,写多个入口文件,所有的入口文件形成一个chunk,名称是默认的,输出也是只有一个bundle
onea:['./src/main.js','./src/index.js'],
twob:'./src/index.js'
},*/

output: { //输出文件目录 文件名字
// publicPath: "/",
filename: "[name].js",//多个出口 加[name] 单个默认main
path: resolve(__dirname,'build') //(当前目录,生成目录名字)
},
//loader 处理css img
module: {
rules: [
//一个loader {loader:'style-loader'}
// {test: /\.css$/,use:['style-loader','css-loader']} ,//从右到左 先加载再插入
// {test: /\.css$/,use:[MiniCssExtractPlugin.loader,'css-loader','postcss-loader']}, //postcss-loader先转才其他
{test: /\.css$/,use:[MiniCssExtractPlugin.loader,'css-loader']},
{test: /\.less$/,use:[MiniCssExtractPlugin.loader,'css-loader','less-loader']} ,//从右到左 先加载再插入
// {test: /\.scss$/,use:['style-loader','css-loader','less-loader','sass-loader','postcss-loader']}
// {test: /\.(png|jpg|jpeg|gif)$/,use:['url-loader',{loader: "file-loader", options: {}}]}
{
test: /\.(png|jpg|jpeg|gif)$/,
loader: 'url-loader',
options: {
publicPath:'./images/',
outputPath:'images/',
limit:1024*8,
name:'[name][hash:10].[ext]'
}
},
{
test: /\.html$/,
loader: 'html-loader'
},
//排除法
{
exclude: /\.(js|json|html|css|less|scss|png|gif|jpg|jpeg)$/,
loader: 'file-loader',
options: {
outputPath:'font/',//输出目录
publicPath:'./font',//到这目录找
name:'[name][hash:8].[ext]'
}
},
// {
// //eslint只检查js语法
// test: /\.js$/,
// //只检查自己写的代码,不检查第三方库的代码
// exclude: /node_modules/,
// loader: 'eslint-loader',
// options: {
// fix:true
// }
// }
]
},
//plugins插件
plugins: [
//默以会创建一个空的,目的就是自动引入打包的资源(js/css)
/*new HtmlWebpackPlugin(
{
template:'./src/index.html',
filename: 'index.html',
}
),*/
new MiniCssExtractPlugin({
filename: 'demo.css'
}),
new OptimizeCssAssetsWebpackPlugin(),
// new PurgecssPlugin({
// paths:glob.sync(`${PATHS.src}/**/*`,{nodir:true}),
// })
],
//webpack5需要加上这个配置项才可以自动刷新
target: "web",
devServer: {
port:3001,
compress:true,
open:true,
hot:true
}
// mode:'production' //production development
}
}


P27总结和作业.mp4

P28 ES6课程内容说明.mp4

P29 es6新增let关键字的语法应用.mp4
1,var可以重复声明,2.var无法限制修改,var没有块级作用域

document.getElementByTagName('button')
btns.addEventListener('click',function(){})

以前
<button>one</button>
<button>two</button>
<script>
var btns=document.getElementsByTagName('button')
for(var i=0;i<btns.length;i++){
(function (i) {
btns[i].addEventListener('click',function () {
console.log(i)
})
})(i)
}
</script>
let命令不存在变量提升
let命令不允许在相同作用域内,重复声明同一个变量

P30 es6新增const关键字的使用.mp4

P31箭头函数和this的指向问题.mp4

普通函数的this:指向它的调用者,如果没有调用者则默认指向window.

箭头函数的this:指向箭头函数定义时所处的对象,而不是箭头函数使用时所在的对象,默认使用父级的this.

综上:箭头函数没有自己的this,它的this是继承而来,默认指向在定义它时所处的对象(宿主对象)。

1,如果没有参数,或有多个参数武需要使用()来定义参数列表
2,如果方一个参数,可以不用()
3,如果函数体中只有一条语句,可以不用{},就不用使用return会自动加上

let arr=[2,3,4,5,5]
大小排序
let narr=arr.sort((a,b)=>{
return a-b;
})

简头丽数在返回对象时,必须在对象外面加上()
const fun=id=>({
id:id,
name:'koo'
})
console.log(fun(10).name)

不能new 没有构造方法


P32数组中新增加的高级函数.mp4
36
filter 过滤器
map映射
reduce 汇总

let goods=[33,44,3,3,2]
let goods1=goods.filter(funciton(n){
return n>=10;
})
console.log(goods1)

for( item in arr){}
for(item of arr){}

let goods2=goods1.map(funciton(n){
return n*0.5;
})

let sum =goods2.reduce(funciton(s,n){
return s+n;
})
console.log(sum)

some()
every()

P33 ES6新增的数据结构Map和Set

Map数据结构类似于对象,是键值对的集合,传统的键只能用字符串,Map的键不限于字符串,各种类型的值(包括对象)都可以当作键。
size
set(key,value)
get(key)
has(key)
delete(key)
clear(key)

遍历
keys()
values()
entries()
forEach()

let set=new Set()
set.add('aa')
console.log(set)

set 不能有重复的值
set.delete('aa')
set.has('aa')
forEach()
size
clear()

P34字符串新增的方法和模板字符串
startWith判断以什么字符串开头
endsWith判断以什么字符串结尾

`${a}`模板字符串

P35解构赋值和三点扩展运算符号

解构赋值
左右两边结构必须一样
右边必须有值
声明和赋值不能分开

let [a,b,c]=[3,4,5]
let {name,age}={name:'koo',age:33}

扩展运算符
…三点运算符
展开数组
默认参数
let arr1=[1,2,3]
let arr=[...arr1,4,5]
console.log(arr);

function demo(...args){
console.log(args) //[1,2,3]
}
demo(1,2,3)

P36 ES6中新增class用法和JSON的新应用

ES 6的Class(类)概念
constructor是构造方法
this关键字代表实例对象
通过extends关键字实现继承
super关键字,表示父类的构造函数,用来新建父类的this对象

JSON对象的新应用
JSON.stringify(obj)串行化 转字符串
JSON.parse(str)反串行化 转json
简写
(属性和值)名字一样可以简写name,
方法一样可以简写(function省)demo(){}

class Person{
constructor(name){
this.name=name
}
run(){}
}
class Student extends Person{
constructor(name,age){
super(name)
this.age=age
}
study(){}
}
const s=new Student('koo',33)
s.run()
s.study()

P37 Module模块化編程export和import的使用

模块化优点
减少命名冲突
避免引入时的层层依赖
可以提升执行效率

export命令:用于规定模块的对外接口一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果你希望外部能够读取模块内部的某个变量,就必须使用export关键字输出该变量。

import命令:用于输入其他模块提供的功能import命令接受一对大括号,里面指定要从其他模块导入的变量名。大括号里面的变量名,必须与被导入模块(profile.js)对外接口的名称相同。

<script src='one.js' type='module'></script>

import * as one from './one.js'
one.run()

P38总结和作业.mp4

P39认识axios和了解课程内容.mp4
axios异步网络请求
认识axios
为axios应用准备技口案例
Postman安装和使用
ES6中Promise的原理和应用
axios的入门应用
axios的post和get请求方式

axios处理并发请求
axios的全局配置方案
axios的实例封装
axios的跨域解决方案
axiost 的拦截器应用
重新封装axios的应用

 

Axios简单的理解就是ajax的封装
Axios是一个基于promise的HTTP库,
支持node端和浏览器端
使用Promise管理异步,告别传统callback方式
丰富的配置项,支持拦截器等高级配置
转换请求数据和响应数据


P40 axios应用准备RestFul标准API

项目的两种编程方式-模板式编程和接口式编程

RestFul API规范(URL,HTTP,版本,状态码,返回值,请求条件等规范)
GET(SELECT):从服务器取出资源(一项或多项)。
POST(CREATE):在服务器新建一个资源。
PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。
PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)
DELETE(DELETE):从服务器删除资源。
我们配置接口时,这只是一种规范,只是建议大家按照规范来使用而已。

P41 Postman的安装和基本使用.mp4

Postman-款非常流行的API调试工具。
Postman最早是作用chrome浏览器插件存在的
Postman提供了独立的安装包,不再依赖于Chrome浏览器了。同时支持MAC,Windows和Linux,
推荐你使用这种方式安装https://www.getpostman.com/apps


P42 ES6中新增加的promise应用mp4

主要用于异步计算
可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果
可以在对象之间传递和操作promise,帮助我们处理队列

Promise.all([
new Promise((resolve,rejecct)=>{
resolve('一')
}),
new Promise((resolve,rejecct)=>{
resolve('二')
}),
])

new Promise((resolve,reject)=>{
console.log('这是第一层')
reject(这是一个错误)
resolve('这是第二层')
}).then(res=>{
console.log(res)
/*return new Promise((resolve,reject)=>{
resolve('这是第三层')
})*/
// return Promise.resolve('这是第三层')
return {mess:'这是第三层'}
},err=>{
console.log(err)
}).then(res=>{
// console.log(res);
console.log(res.mess);
})
</scrip>


P43 axios入门应用.mp4
47
bootcdn.cn

<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>

默认get方式请求

<?php
//echo json_encode($_GET);
echo json_encode($_POST);

{
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
</head>
<body>
<script>
// axios('http://localhost/es61/getapi.php?name=koo&age=19').then(res=>{
// console.log(res)
// console.log(res.data)
// })
// axios({
// method:'get',
// url:'http://localhost/es61/getapi.php',
// params:{
// username:'koo',
// age:33,
// sex:'man'
// }
// }).then(res=>{
// console.log(res)
// })
axios({
method:'post',
url:'http://localhost/es61/getapi.php',
headers:{
'content-type':'application/x-www-form-urlencoded'
},
data:{
username:'koo',
age:33,
sex:'man'
}
}).then(res=>{
console.log(res)
})
</script>
</body>
</html>
}

P44 axios在生产环境的应用.mp4

import axios from 'axios'
axios.request(config)
axios. get(url, config])
axios. delete(urlL configl)
axios. head(url, config])
axios. post(url, datal, configl) axios. put(url, datal, configll)
axios. patch(urlL, datal, configl)

header('Access Control Allow Origin:*');

npm init -y
npm i axios -S
npm i webpack webpack-cli -D
npm i html-webpack-plugin -D

"html-webpack-plugin": "^5.5.0" 不再报错

报错 重新打开终端
报错 node使用lts长期版本 14.18.1

 

{
const HtmlWebpackPlugin=require('html-webpack-plugin')

module.exports={
entry:'./src/index.js',
plugins:[
new HtmlWebpackPlugin({
template: "./src/index.html"
})
],
mode:'development',
}
}

{
import axios from "axios";

// axios.get('http://localhost/es61/getapi.php?username=abc',{params:{id:1}}).then(res=>{
// console.log(res)
// })

axios.get('http://localhost/es61/getapi.php?username=abc',"name=test&url=eduwork").then(res=>{
console.log(res)
})
}

<?php
header('Access Control Allow Origin:*');
echo json_encode($_GET);
//echo json_encode($_POST);

P45 axios的并发请求处理.mp4

ajax请求过多对页面性能可能会有影响,以及代码不美观,代码过于臃肿,所以我们可以使用axios的并发请求axios.all()
axios.all()和promise.all()方法是一个道理
axios.all()这个方法在axios的构造函数是没有的,没在实例对象上。

{
import axios from "axios";

// axios.get('http://localhost/es61/getapi.php?username=abc',{params:{id:1}}).then(res=>{
// console.log(res)
// })

// axios.get('http://localhost/es61/getapi.php?username=abc',"name=test&url=eduwork").then(res=>{
// console.log(res)
// })

// axios.all([
// axios.get('http://localhost/es61/getapi.php?id=1'),
// axios.get('http://localhost/es61/getapi.php?id=2'),
// axios.get('http://localhost/es61/getapi.php?id=3')
// ]).then(res=>{
// // console.log(res)
// console.log(res[0]);
// console.log(res[1]);
// console.log(res[2]);
// }).catch(err=>{
// console.log('-----error-----')
// console.log(err);
// })

axios.all([
axios.get('http://localhost/es61/getapi.php?id=1'),
axios.get('http://localhost/es61/getapi.php?id=2'),
axios.get('http://localhost/es61/getapi.php?id=3')
]).then(
//拆开
axios.spread((res1,res2,res3)=>{
console.log(res1)
console.log(res2);
console.log(res3);
})
).catch(err=>{
console.log('-----error-----')
console.log(err);
})
}


P46 axios的全局配置.mp4
axios.defaults.baseURL='http://localhost/es61/getapi.php'
axios.defaults.timeout=5000;
axios.defaults.headers.post['content-type']='application/x-www-form-urlencoded'
//整理数据
axios.defaults.transformRequest=function(data){
data=JSON.stringify(data)
return data
}
axios.get('?name=22').then(res=>{
console.log(res);
}).catch(err=>{
console.log(err);
})

P47 axios的实例封装.mp4
51
baseURL:请求的域名基本地址
timeout:后端定义的超时时长(默认是1000ms)
url:请求的路径(如:/datajson)
method:请求方法(get,post.)
headers:设置请求头
params:请求的参数拼接在url中
data:请求的参数放在request body中

{
axios.defaults.baseURL='http://localhost/es61/getapi.php'
axios.defaults.timeout=3000;
//先走下面的 axios实例方式
let eduwork=axios.create({
baseURL:'http://localhost/es61/getapi.php',
timeout:5000
})

eduwork.get('link?id=1').then(res=>{
console.log(res)
}).catch(err=>{
console.log(err)
})
eduwork({
url:'link?username=hello'
}).then(res=>{
console.log(res)
})
}

P48 axios的拦截器的应用.mp4
为每个请求都带上的参数,比如token,时间戳等。
对返回的状态进行判断,比如token是否过期

{
//先走下面的 axios实例方式
let eduwork=axios.create({
baseURL:'http://localhost/es61/getapi.php',
timeout:5000
})

//拦截器
eduwork.interceptors.request.use(config=>{
console.log('请求的拦截成功,处理一下,放行!');
return config;
},err=>{
console.log(err);
})

eduwork.interceptors.response.use(config=>{
console.log('从服务器将数据带回来了,处理,放行!');
return config.data;
},err=>{
console.log(err);
})

eduwork.get('link?id=1').then(res=>{
console.log(res)
}).catch(err=>{
console.log(err)
})
}

P49总结和作业.mp4

P50 Vue3框架课程内容介绍.mp4
Vue全家桶
认识VUE3
VUE开发 初体验
VUE CLI脚手架
VUE 基础语法
网络封装
组件化开发

VUE路由应用
Vuex详解
VueзB新特性
项目实战
Nuxt.js框架应用
基于Nuxt的SSR项目实战

P51认识一下Vue.mp4

P52 Vue3的CDN方式安装和基本开发功能体验
56
一、数据绑定,数据响应式
二、属性动态绑定的提示信息
三、样式的动态绑定
四、基本的事件操作
五、循环遍历输出数组中的值


json {h:h} => {h} key和value相同可以简写

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

<div id="app">
{{message}}
<div :style="{'color':color}">
<ul>
<li v-for="item in arr.slice(0,5)" :title="item.content">{{item.title}}</li>
</ul>
</div>
</div>
<!--最新版本-->
<!--<script src="https://unpkg.com/vue@next"></script>-->
<script src="vue.global.js"></script>
<script>
//vue2
/*const app=new vue({
el:#app,
data:{
message:'this is a test'
}
})*/

//vue3
const app=Vue.createApp({
data(){
return {
color:'red',
message:'this is a test',
arr:[
{title:'title2222',content:'content1'},
{title:'title2222',content:'content2'},
{title:'title2222',content:'content3'}
]
}
},
methods:{}
}).mount('#app')
app.message='hello vuejs'
</script>

</body>
</html>
}


P53 vue-cli手架安装与项目创建
Vue-CLI(Command Line Interface)
Vue-CLI是Vue官方提供的脚手架工具
默认已经帮我们搭建好了一套利用Webpack管理vue的项目结构
命令安装:npm install -g@vue/cli
检查版本:vue --version
创建项目:vue create 项目名称
配置文件详细
应用代码演示


P54通过vue-cli体验vue开发并扩展配置
cli.vuejs.org/config/

vue.config.js
{
/*
const path=require('path')
module.exports={
output:{
path:path.resolve(__dirname,'build')
}
}*/
const webpack=require('webpack')
module.exports={
outputDir:'build',
//使用原生webpack
configureWebpack:{
plugins:[
new webpack.BannerPlugin({
banner:'学习黎地-ww.1monkey.com-成就自己的只需一套精品'
})
]
}
}
}

eslint修复语法
webstrom 设置 搜索 eslint --右点击 fix---xxx

P55 options基础定义和MVVM模式
MVVM模式(Model-View-ViewModel)

Vue实主要是封装了视图操作,包括有
数据读写
事件绑定
DOM更新
options是vue实例参数,意思是构造选项

options的五类属性
数据:data,prop,propsData,contputed methods,watch
DOM:el template,render,renderError
生命周期钩子:beforeCreate,created beforeMount,mounted,beforeUpdate,updated.
activated,deactivated,beforeDestroy,destroyed errorCaptured
资源:directives,filters,components
组合:parent,mixins,extends,provide,inject
其他:先不看


public目录下文件会原封不动输出

{
<template>
<div>
{{msg}}
</div>
</template>

<script>
const data={
msg:'this is a test'
}
export default {
name: "App",
data(){
return data;
},
methods:{}
}
</script>

<style scoped>

</style>
}

P56模板基础语法#插值和指令.mp4

Vue模板中基本语法
插值操作
绑定属性
计算属性
事件监听
条件判断
循环遍历
其它语法

插值:{{}}
指令:V-

v-pre 不解析内容 原封不动输出
<pre></pre>

P57 Vue模板基础语法v-bind应用.mp4
61
插值(0)只能用在模板内容中,用于动态内容绑定如果希望元素的属性也可以动态绑定,需要通过v-bind指令
"v-bind"缩写":"(语法糖)
绑定有意义元素中的属性
绑定class属性,四种用法(字符串,数组,对象,方法)
绑定style属性

<div :class="[one,two]">box</div>
<div :class="['one']">box</div>
<div :class="{one}">box</div>


P58 Vue模板基础语法计算属性computed

计算属性关键词:computed.
计算属性在处理一些复杂逻辑时是很有用的。

<h2>{{getTitle()}}</h2>

按键Delete 反向删

{
<template>
<div>
<h2>{{getTitle()}}</h2>
<h2>{{title}}</h2>
</div>
</template>

<script>
export default {
name: "App",
data(){
return {
name:'koo',
age:'27'
}
},
computed:{
title:{
set(values){
let arr=values.split('-')
this.name=arr[0]
this.age=arr[1]
},
get(){
//多个打印一次
console.log('222')
return this.name+'-'+this.age
}
}
},
methods:{
getTitle(){
//多个打印多次
console.log('222')
this.title='koo - age'
return this.name+'-'+this.age
}
}
}
</script>

<style scoped>

</style>
}


P59 Vue模板基础语法事件监听v-on
在前端开发中,需要经常和用户交互
绑定事件监听器指令:v-on
缩写:@(语法糖)
参数:$event
v-on事件修饰符号
.stop 阻止事件冒泡
.self当事件在该元素本身触发时才触发事件
.capture添加事件侦听器是,使用事件捕获模式
.prevent 阻止默认事件
.once 事件只触发一次

@click.self.stop

{
<template>
<div>
<button v-on:click="num--">-</button>
<input type="text" size="2" v-model="num">
<button @click="num++">+</button>
<br>
<button v-on:click="sub()">-</button>
<input type="text" size="2" v-model="num">
<button @click="add(100,$event)">+</button>
</div>
</template>

<script>
export default {
name: "App",
data(){
return {
num:0
}
},
computed:{

},
methods:{
sub(){
this.num--
},
add(n,e){
console.log(n,e)
this.num++
}
}
}
</script>

<style scoped>

</style>
}

P60 Vue模板基础语法条件分支v-if和v-show

v-if v-else-if v-else
v-show


P61 Vue模板基础语法循环這历v-for

{
<template>
<div>
<ul>
<li v-for="(item,key,index) in obj" :key="index">
{{index}}.{{key}}:{{item}}
</li>
</ul>
</div>
</template>

<script>
export default {
name: "App",
data(){
return {
obj:{
name:'koo',
url:'http://baidu.com',
age:27
}
}
}
}
</script>

<style scoped>

</style>
}

P62 v-for中的key的绑定mp4

eslint package ellint语法检查 false关闭

P63 Vue模板语法v-model详解.mp4
67
v-model的修饰符号:
.lazy懒加 载修饰符
.number修饰符让其转换为number类型
.trim修饰符可以自动过滤掉输入框的首尾空格

{
<template>
<div>
<!-- <input type="text" :value="msg" @input="inchange">-->
<!-- <input type="text" :value="msg" @input="msg=$event.target.value">-->
<!-- <input type="text" v-model.lazy="msg">-->
<!-- <input type="text" v-model.number="msg">-->
<input type="text" v-model.trim="msg">
<br>
{{typeof(msg)}}--{{msg}}
</div>
</template>

<script>
export default {
name: "App",
data(){
return {
msg:0
}
},
methods:{
//自己办法实现双向数据绑定
inchange(event){
this.msg=event.target.value;
}
}
}
</script>

<style scoped>

</style>
}

P64 Vue模板语法综合应用-购物车案例
{
<template>
<div>
<div v-if="cartlist.length<=0">你没有选择的商品,购物车为空,去购物</div>
<table v-else>
<caption><h1>购物车</h1></caption>
<tr>
<th> </th>
<th>编号</th>
<th>商品名称</th>
<th>商品价格</th>
<th>购买数量</th>
<th>操作</th>
</tr>

<tr v-for="(item,index) in cartlist" :key="item.id">
<td><input type="checkbox" v-model="item.checkbox"></td>
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td><small>¥</small>{{item.price.toFixed(2)}}</td>
<td>
<button @click="item.count--" :disabled="item.count<=1">-</button>
{{item.count}}
<button @click="item.count++">+</button>
</td>
<td><a href="#" @click.prevent="del(index)">删除</a></td>
</tr>
<tr>
<td colspan="3" align="right">总价</td>
<td colspan="3"><small>¥</small>{{totalPrice.toFixed(2)}}</td>
</tr>
</table>
</div>
</template>

<script>
export default {
name: "App",
data(){
return {
cartlist:[
{id:1,checkbox:true,name:'细说PHP',price:10,count:1},
{id:2,checkbox:true,name:'细说网页制作',price:10,count:1},
{id:3,checkbox:true,name:'细说Javascript语言',price:10,count:1},
{id:4,checkbox:true,name:'细说DOM和BOM',price:10,count:1},
{id:5,checkbox:true,name:'细说Ajax与JQuery',price:10,count:1},
{id:6,checkbox:true,name:'细说HTML5高级API',price:10,count:1},
]
}
},
computed:{
totalPrice:{
get(){
let sum=0;
for(let book of this.cartlist){
if (book.checkbox){
sum+=book.price*book.count;
}
}
return sum;
// return '¥'+sum.toFixed(2);
}
}
},
methods:{
del(index){
this.cartlist.splice(index,1)
}
}
}
</script>

<style scoped>
table{
width: 600px;
border: 1px solid #888888;
border-collapse: collapse;
}
th{
background: #ccc;
}
td,th{
border: 1px solid #888888;
padding: 10px;
}
</style>
}


P65 Vue组件化开发思想介绍.mp4

P66创建Vue组件和组件语法结构.mp4

P67组件化开发思想.mp4
71
P68父传子props(组件之间通信)

<my-main :article="article" :title="msg" msg="hello"></my-main>

{
<template>
<my-conn :article="article"></my-conn>
<my-conn></my-conn>
{{msg}}
{{show()}}
<br>
<h2>{{title}}</h2>
<br>
<span v-for="item in article">{{item}}</span>
</template>

<script>
import MyConn from "./childsComp/MyConn";
export default {
name: "MyMain",
//props:['name','name',...]
props:{
msg:{
type:String,
default:'没有传值默认出来'
},
title:{
type:String,
//必须传值的
required:true
},
article:{
type:Array
}
},
data(){
return {

}
},
components:{
MyConn
},
methods:{
show(){
return this.msg+this.msg
}
}
}
</script>

<style scoped>

</style>
}

P69子传父$emit(组件之间通信)
{
<template>
<div class="myconn">
<button @click="changenum(2)">+</button>
{{mess}}
<br>
<span v-for="item in article">{{item}}</span>
</div>
</template>

<script>
export default {
name: "MyConn",
data(){
return{
mess:'this is main test'
}
},
props:{
article:{
type:Array
}
},
methods:{
changenum(num){
this.$emit('mycountevent',num)
}
}
}
</script>

<style scoped>
.myconn{
width: 60%;
height: 100px;
background: #34ffff;
margin: 10px;
}
</style>
}

{
<template>
<div style="width: 100px;height: 50px;background: yellow">{{count}}</div>
<my-conn :article="article"></my-conn>
<my-conn @mycountevent="mydemo"></my-conn>
{{msg}}
{{show()}}
<br>
<h2>{{title}}</h2>
<br>
<span v-for="item in article">{{item}}</span>
</template>

<script>
import MyConn from "./childsComp/MyConn";
export default {
name: "MyMain",
//props:['name','name',...]
props:{
msg:{
type:String,
default:'没有传值默认出来'
},
title:{
type:String,
//必须传值的
required:true
},
article:{
type:Array
}
},
data(){
return {
count:0
}
},
components:{
MyConn
},
methods:{
show(){
return this.msg+this.msg
},
mydemo(data){
this.count+=data;
}
}
}
</script>

<style scoped>

</style>
}


P70父子组件之间的相互访问方式
子组件调用父组件的方法:$parent或$root
父组件调用子组件的方法:$children或$refs

{
<template>
<div style="width: 100px;height: 50px;background: yellow">{{count}}</div>
<my-conn ref="twoa" :article="article"></my-conn>
<my-conn @mycountevent="mydemo"></my-conn>
{{msg}}
{{show()}}
<br>
<button @click="two">+</button>
<br>
<h2>{{title}}</h2>
<br>
<span v-for="item in article">{{item}}</span>
</template>

<script>
import MyConn from "./childsComp/MyConn";
export default {
name: "MyMain",
//props:['name','name',...]
props:{
msg:{
type:String,
default:'没有传值默认出来'
},
title:{
type:String,
//必须传值的
required:true
},
article:{
type:Array
}
},
data(){
return {
count:0
}
},
components:{
MyConn
},
methods:{
show(){
return this.msg+this.msg
},
mydemo(data){
this.count+=data;
},
changen(){
this.count++
},
two(){
// console.log(this.$children)
this.$refs.twoa.two()
}
}
}
</script>

<style scoped>

</style>
}


{
<template>
<div class="myconn">
<button @click="changenum(2)">+</button>
{{mess}}
<br>
{{num}}-----
<br>
<button @click="one">+</button>
<br>
<span v-for="item in article">{{item}}</span>
</div>
</template>

<script>
export default {
name: "MyConn",
data(){
return{
mess:'this is main test',
num:0
}
},
props:{
article:{
type:Array
}
},
methods:{
changenum(num){
this.$emit('mycountevent',num)
},
one(){
// console.log(this.$parent.count)
this.$parent.changen()
// console.log(this.$parent.$parent.msg)
//或 孙子 调用 父组件方法 属性
console.log(this.$root.msg)
},
two(){
this.num++
}
}
}
</script>

<style scoped>
.myconn{
width: 60%;
height: 100px;
background: #34ffff;
margin: 10px;
}
</style>
}

P71 Vue插槽slot的应用详解.mp4
children
<slot>default</slot>
parent
<my>xxxxx</my>


<my-bar>
<button slot="one">提交</button>
<a href="" slot="two">连接</a>
</my-bar>

<slot name="one">default11111</slot>
<slot name="two">default</slot>

{
<template>
<my-bar>
<template v-slot:one>
<button>提交</button>
<a href="" @click.prevent="demo">连接</a>
</template>
<template #:one>
<button>提交</button>
<a href="" @click.prevent="demo">连接</a>
</template>
<template v-slot:default="subdata">
<a href="">{{subdata.user.name}}</a>
</template>
</my-bar>
<my-bar>
<button slot="one">提交</button>
<a href="" slot="two">连接</a>
</my-bar>
<my-bar></my-bar>
</template>

<script>
import MyBar from "./childsComp/MyBar";
export default {
name: "MySideBar",
components:{
MyBar
}
}
</script>

<style scoped>

</style>
}

{
<template>
<div class="mybar">
<slot name="one">default11111</slot>
<slot name="two">default</slot>
<slot :user="user">trwee</slot>
</div>
</template>

<script>
export default {
name: "MyBar",
data(){
return {
user:{name:'koo'}
}
}
}
</script>

<style scoped>
.mybar{
width: 200px;
height: 70px;
margin: 10px;
background: yellow;
}
</style>
}

P72 Vue3中组件的生命周期函数.mp4
beforCreate 创建实例之间自动调用
created 实例创建完成
beforMount 模板编译之前
mounted 模版编译完成
beforUpdate 模板更新之前
updated 模板内容更新完成
activated, 通过keep-alive缓存之前调用
deactivated, keep-alive缓存数据恢复调用
beforUnmount 实例在销毁之前调用
unmounted 实例销毁完成

this.$nextTick(()=>{})
this.SnextTik()将可调延迟到下次DOM更新循环之后执行。在修改数据之后立即使用它,然后等待DOM更新.

v-if销毁

activated
deactivated
<keep-alive>xxx</keep-alive>

P73在Vue中使用axios请求服务器

npm i axios -S -S打包也用到运行时 -D生产时

axios.post(url,data,config,header)

{
<template>
<div class="footer">
<ul>
<li v-for="item in links"><a href="item.url">{{item.name}}</a></li>
</ul>
</div>
</template>

<script>
import axios from 'axios'
export default {
name: "MyFooter",
data(){
return {
links:[]
}
},
mounted(){
axios.get('http://api.eduwork.cn/admin/link')
.then(res=>{
console.log(res.data);
this.links=res.data
}).catch(err=>{
console.log(err);
})
}
}
</script>

<style scoped lang="scss">
.footer{
float: left;
margin-top: 20px;
width: 100%;
height: 100px;
background: #f0fff0;
}
ul{
list-style: none;
margin: 10px;
padding: 0px;
li{
display: inline-block;
margin: 10px;
}
}
</style>
}

P74封装网络请求.mp4
78
import {get} from '../network/request';
get('/link',{id:1}).then(res=>{
this.links=res.data
}).catch(err=>{
console.log(err);
})

request.js
{
import axios from 'axios';

const instance=axios.create({
baseURL:'http://api.eduwork.cn/admin',
timeout:5000
})

//请求拦截
instance.interceptors.request.use(
config=>{
// config.headers.token='123456'
return config;//放行
},
error => {
return Promise.reject(error)
}
)

instance.interceptors.response.use(
response=>{
console.log(response);//查看响应信息
return response;
},
error => {
return Promise.reject(error)
}
)

export function get(url, params) {
return instance.get(url,{params})
}

export function post(url, params) {
return instance.post(url,params,{
transformRequest:[
function (data) {
let str='';
for(let key in data){
str+=encodeURIComponent(key)+
'='
+encodeURIComponent(data[key])+'&'
}
console.log(str)
return str;
}
],
headers:{
'Content-Type':'application/x-www-form-urlencoded'
}
})
}

export function del(url) {
return instance.delete(url)
}
}

P75认识Vue的路由.mp4

P76 VueRouter路由应用体验.mp4
components 小组件
views 大组件
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')


P77 Router模式切换和懒加载.mp4
import About from '../views/About.vue'导入打包时js全部在一起 加载慢
component: () => import( '../views/About.vue')

延迟加载动态导入和路由模式解析
路由是由多个URL组成的,使用不同的URL可以相应的导航到不同的位置
Vue-Router在切换页面时是没有重新进行请求的,使用起来就好像页面是有状态的一样
借助了浏览器的History APl来实现的,这样可以使得页面跳转而不刷新,页面的状态就被维持在浏览器中
vue-router中默认使用的是hash模式,也就是会出现如URL:O locilhost 01/URL中带有#号

有三种模式
Hash:使用URL的hash值来作为路由,用来指导浏览器动作的,对服务器端完全无用,支持所有浏览器。
History:以来HTML5 History APl和服务器配置。
Abstract:支持所有javascript运行模式。如果发现没有浏览器的API,路由会自动强制进入这个模式。

P78 自定义router-link和使用命名视图
active-class
!important

vue2
tag='button'

<router-link v-slot="{nav}">
<button @click="nav">About Us</button>
</router-link>

{{ / /注释}}

{
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
import About from "../views/About";
import User from "../views/User";

const routes = [
{
path: '/',
name: 'Home',
// component: Home
components:{
default:Home,
About,
User
}
},
{
path: '/about',
name: 'About',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
},
{
path:'/user',
name:'User',
component:User
}
]

const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
})

export default router

}

{
<button @click="$router.push('/user')">User</button>
<button @click="$router.go(-1)">返回</button>
<!-- {{$router.path}}-->
{{$route.path}}
</div>
<router-view name="User" class="one"></router-view>
<router-view class="two"></router-view>
<router-view name="About" class="three"></router-view>
}

P79嵌套路由(子路由).mp4
221
<div class="menu">
<ul>
<li><router-link to="/user/order">我的订单</router-link></li>
<li><router-link to="/user/setting">个人设置</router-link></li>
</ul>
</div>
<div class="content">
<router-view></router-view>
</div>

{
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
import About from "../views/About";
import User from "../views/User";
// import MyOrder from "../views/MyOrder";

const MyOrder=()=>import('../views/MyOrder.vue')
const MySetting=()=>import('../views/MySetting.vue')
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
},
{
path:'/user',
name:'User',
component:User,
children:[
{
path:'',
component:MySetting
},
{
path: 'order',
component: MyOrder
},
{
path: 'setting',
component:MySetting
}
]
}
]

const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
})

export default router

}

P80动态路由和参数传递.mp4
传递参数主要有两种类型:params和query
params的类型:
配置路由格式:/user/:id(动态路由)
传递的方式:在path后面对应值:to="/user/+uid"
传递后形成的路径:/user/9,/user/zs
接收参数:$route.params.id
query的类型:配置路由格式:/user,正常配置

传递的方式:对象中使用query的key作为传递方式:to={path:'/',query:{id:1,name:abc}}
传递后形成的路径:/user?id=9,/user?id=zs
接收参数:$route.query.name

{
path:'page/:id',
component:MyPage
},
{
path:'article',
component:MyArticle
},

{
<template>
<div>User</div>
<br>
<div class="menu">
<ul>
<li><router-link to="/user/order">我的订单</router-link></li>
<li><router-link to="/user/setting">个人设置</router-link></li>
<li><router-link to="/user/page/1">单页一</router-link></li>
</ul>
<ul>
<li v-for="item in article"><router-link :to="'/user/page/'+item.id">{{item.title}}</router-link></li>
</ul>

<li><router-link to="/user/article?name=111&age=22">文章一</router-link></li>
<li><router-link :to="{path:'/user/article',query:{name:'koo',age:100}}">文章一</router-link></li>

<button @click="$router.push({path:'/user/article',query:{name:'joo',age:100}})">跳转</button>
</div>
<div class="content">
<router-view></router-view>
</div>
</template>

<script>
export default {
name: "User",
data(){
return {
article:[
{id:10,title:'这是文章一'},
{id:11,title:'这是文章一'},
{id:12,title:'这是文章一'},
{id:13,title:'这是文章一'},
{id:14,title:'这是文章一'},
{id:15,title:'这是文章一'},
]
}
}
}
</script>

<style scoped>
.menu{
width: 30%;
height: 300px;
background: #f0fff0;
float: left;
}
.content{
width: 70%;
height: 300%;
background: white;
float: right;
}
</style>
}


{{$route.query.name}}

{
<template>
<h2>这是文章的模板</h2>
文章ID:{{this.$route.params.id}}
<br>
<h1>{{pageid}}</h1>
</template>

<script>
export default {
name: "MyPage",
computed:{
pageid(){
return this.$route.params.id
}
/*pageid:{
get(){

}
}*/
}
}
</script>

<style scoped>

</style>
}

P81重定向和别名.mp4

{
path:'/home',
name:'Home',
redirect:'/',
component:Home
},

{
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
import About from "../views/About";
import User from "../views/User";
// import MyOrder from "../views/MyOrder";

const MyOrder=()=>import('../views/MyOrder.vue')
const MySetting=()=>import('../views/MySetting.vue')
const MyPage=()=>import('../views/MyPage.vue')
const MyArticle=()=>import('../views/MyArticle.vue')
const routes = [
{
path: '/',
name: 'Homeroot',
component: Home
},
{
path:'/home',
name:'Home',
// redirect:'/',
redirect:{name:'Homeroot'},//用名字跳转
component:Home
},
{
path: '/about',
name: 'About',
alias:['/a','/b','/c'],//多个别名 一个直接'/a'
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
},
{
path:'/user',
name:'User',
component:User,
children:[
{
path:'',
component:MySetting
},
{
path: 'order',
component: MyOrder
},
{
path: 'setting',
component:MySetting
},
{
path:'page/:id',
component:MyPage,
alias:['p/:id','x/:id'],
//$route=to
/*redirect:to=>{
return {path:'article',query:{name:'koo',age:to.params.id}}
}*/
},
{
path:'article',
component:MyArticle
},
]
}
]

const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
})

export default router

}

P82导航守卫介绍及应用.mp4
导航守卫主要用来通过跳转或取消的方式守卫导航。
前置守卫
//to:Route:即将要进入的目标路由对象,from:Route:当前导航正要离开的路由
router.beforeEach((to,from)=>{
return false
})
后置钩子
router.afterEach((to,from)=>{
})

有多种机会植入路由导航过程中:全局的,单个路由独享的,或者组件级的。
全局导航守卫
路由独享的守卫
组件内的守卫

document.title='这是首页'

{
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
import About from "../views/About";
import User from "../views/User";
// import MyOrder from "../views/MyOrder";

const MyOrder=()=>import('../views/MyOrder.vue')
const MySetting=()=>import('../views/MySetting.vue')
const MyPage=()=>import('../views/MyPage.vue')
const MyArticle=()=>import('../views/MyArticle.vue')
const routes = [
{
path: '/',
name: 'Homeroot',
component: Home,
meta:{
title:'1111111111'
}
},
{
path:'/home',
name:'Home',
// redirect:'/',
redirect:{name:'Homeroot'},//用名字跳转
component:Home,
meta:{
title:'222222222'
}
},
{
path: '/about',
name: 'About',
meta:{
title:'333333'
},
alias:['/a','/b','/c'],//多个别名 一个直接'/a'
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
},
{
path:'/user',
name:'User',
component:User,
children:[
{
path:'',
component:MySetting
},
{
path: 'order',
component: MyOrder
},
{
path: 'setting',
component:MySetting
},
{
path:'page/:id',
component:MyPage,
alias:['p/:id','x/:id'],
//$route=to
/*redirect:to=>{
return {path:'article',query:{name:'koo',age:to.params.id}}
}*/
meta:{
title:'444444444'
}
},
{
path:'article',
component:MyArticle
},
]
}
]

const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
})

//全局导航守卫to,from,next 2.x
//to:Route:即将要进入的目标路由对象,from:Route:当前导航正要离开的路由
router.beforeEach((to,from)=>{
console.log(to.fullPath);
console.log(from.fullPath);
document.title=to.meta.title;
})
router.afterEach((to,from)=>{
console.log(to.fullPath);
console.log(from.fullPath);
})
export default router

}


P83 keep-alive和vue-router结合使用

keep-alive是Vue内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。
include:正则表达式exclude:正则表达式

router-view是vue-router内置组件,如果直接包含在keep-alive里面,所有路径匹配到的组件都会被缓存。

<!-- vue2.x-->
<!-- <keep-alive>-->
<!-- <router-view></router-view>-->
<!-- </keep-alive>-->

<!-- vue3-->
<router-view v-slot="{Component}">
<transition>
<keep-alive>
<component :is="Component"/>
</keep-alive>
</transition>
</router-view>
</template>

{
<template>
<div>About</div>
</template>

<script>
export default {
name: "About",
data(){
return {
path:'/about'
}
},
created(){
document.title='关于我们'
console.log('About组件被创建');
},
unmounted(){
console.log('About组件被销毁');
},
activated(){
console.log('keep-alive缓存的组件激话时调用');
this.$router.push(this.path)
},
deactivated(){
console.log('keep-alive缓存的组件停用时调用');
},
//路由钩子
beforeRouteLeave(to,from){
// console.log(from.fullPath);
this.path=from.fullPath;
}
}
</script>

<style scoped>

</style>
}

<router-view v-slot="{Component}">
<transition>
<keep-alive exclude="About,User">排除 组件创建销毁
<component :is="Component"/>
</keep-alive>
</transition>
</router-view>

P84 Vuex状态管理应用概述.mp4

Vuex是一个专为Vue.js应用程序开发的状态管理模式。
就是一个加强版的data!在单页应用中会有一个data函数,管理当前应用的状态,处理大量的需要在组件间传递的数据,直接定义一个全局的data属性保存就行了.
如果我们的页面比较简单,切记千万不要没事找事引入Vuex,我们使用Vuex是因为项目变得复杂之后,有很多数据需要在父组件、子组件和孙组件之间传递,处理起来很繁琐,于是就需要Vuex这样一个可以对这一部分数据进行统一管理的东西
也是响应式

什么情况需要使用Vuex管理状态在多个组件间共享?
大型项目中组件很多,多个组件中共用的数据
例如:用户的登录状态、用户名称、头像、地理位置信息等
例如:商品的收藏、购物车中的物品。


1,超全局交量
2.响应式的

P85安装和体验Vuex状态管理.mp4
dart-sass

目录store vuex配置文件
props: {
count:Number
}
{
<template>
<div class="home">
home:{{count}}
<br>
<button @click="count++">+</button>
<button @click="count--">-</button>
<hr>
超全局:{{$store.state.num}}
<button @click="$store.state.num++">+</button>
<button @click="$store.state.num--">-</button>
<HelloWorld :count="count"/>
</div>
</template>

<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'

export default {
name: 'Home',
data(){
return {
count:0
}
},
components: {
HelloWorld
}
}
</script>

}

src/store/index.js
{
import { createStore } from 'vuex'

export default createStore({
state: {
num:5
},
mutations: {
},
actions: {
},
modules: {
}
})

}

P86使用devtools工具查看状态管理
https://www.crx4chrome.com/crx/107268/

{
import { createStore } from 'vuex'

export default createStore({
state: {
num:5,
dnum:0
},
mutations: {
sub(state){
state.dnum--
},
add(state){
state.dnum++
}
},
actions: {
},
modules: {
}
})

}

{
<template>
<div class="home">
home:{{count}}
<br>
<button @click="count++">+</button>
<button @click="count--">-</button>
<hr>
超全局:{{$store.state.num}}
<button @click="$store.state.num++">+</button>
<button @click="$store.state.num--">-</button>
<hr>
dnum超全局:{{$store.state.dnum}}
<button @click="$store.commit('add')">+</button>
<button @click="$store.commit('sub')">-</button>
<HelloWorld :count="count"/>
</div>
</template>

<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'

export default {
name: 'Home',
data(){
return {
count:0
}
},
components: {
HelloWorld
}
}
</script>

}

P87 Mutations传参问题.mp4
只能带一个参数过去 推荐声明为对象
{
import { createStore } from 'vuex'

export default createStore({
state: {
num:5,
dnum:0
},
mutations: {
sub(state){
state.dnum--
},
add(state){
state.dnum++
},
sub1(state,count){
state.dnum-=count
},
add1(state,count){
state.dnum+=count
},
sub2(state,payload){
state.dnum-=(payload.count+payload.num)
},
add2(state,payload){
state.dnum+=(payload.count+payload.num)
},
sub3(state,p){
state.dnum-=(p.payload.count+p.payload.num)
},
add3(state,p){
state.dnum+=(p.payload.count+p.payload.num)
},
},
actions: {
},
modules: {
}
})

}

{
<template>
<div class="home">
home:{{count}}
<br>
<button @click="count++">+</button>
<button @click="count--">-</button>
<hr>
超全局:{{$store.state.num}}
<button @click="$store.state.num++">+</button>
<button @click="$store.state.num--">-</button>
<hr>
dnum超全局:{{$store.state.dnum}}
<button @click="$store.commit('add')">+</button>
<button @click="$store.commit('sub')">-</button>
<hr>
Mutations带一个参数:{{$store.state.dnum}}
<button @click="$store.commit('add1',2)">+</button>
<button @click="$store.commit('sub1',2)">-</button>
<hr>
Mutations带多个参数:{{$store.state.dnum}}
<button @click="$store.commit('add2',{count:2,num:1})">+</button>
<button @click="$store.commit('sub2',{count:2,num:1})">-</button>
<hr>
另一个Mutations带多个参数:{{$store.state.dnum}}
<button @click="$store.commit({type:'add3',payload:{count:2,num:1}})">+</button>
<button @click="$store.commit({type:'sub3',payload:{count:2,num:1}})">-</button>
<HelloWorld :count="count"/>
</div>
</template>

<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'

export default {
name: 'Home',
data(){
return {
count:0
}
},
components: {
HelloWorld
}
}
</script>

}

P88 Vuex中的计算属性getters应用

nums.reduce((s,n)=>s+n,0)

getters:{ 第二个参数是整个getters
num(state,getters){

}
}

带参数的
getters:{ 第二个参数是整个getters
num(state,getters){
return funciton(price){}
}
}
this.$store.getters.num(50)

{
<template>
<div class="home">
home:{{count}}
<br>
mypow:{{mypow}}
<br>
vuexpow:{{vuexpow}}
<br>
getters计算属性:{{this.$store.getters.vxnum}}
<br>
<button @click="count++">+</button>
<button @click="count--">-</button>
<hr>
超全局:{{$store.state.num}}
<button @click="$store.state.num++">+</button>
<button @click="$store.state.num--">-</button>
<hr>
dnum超全局:{{$store.state.dnum}}
<button @click="$store.commit('add')">+</button>
<button @click="$store.commit('sub')">-</button>
<hr>
Mutations带一个参数:{{$store.state.dnum}}
<button @click="$store.commit('add1',2)">+</button>
<button @click="$store.commit('sub1',2)">-</button>
<hr>
Mutations带多个参数:{{$store.state.dnum}}
<button @click="$store.commit('add2',{count:2,num:1})">+</button>
<button @click="$store.commit('sub2',{count:2,num:1})">-</button>
<hr>
另一个Mutations带多个参数:{{$store.state.dnum}}
<button @click="$store.commit({type:'add3',payload:{count:2,num:1}})">+</button>
<button @click="$store.commit({type:'sub3',payload:{count:2,num:1}})">-</button>
<HelloWorld :count="count"/>
</div>
</template>

<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'

export default {
name: 'Home',
data(){
return {
count:0
}
},
computed:{
/*mypow:{
get(){
} 简写
}*/
mypow(){
return this.count*this.count
},
//这vuex计算属性 再其他页面就不可用
vuexpow(){
return this.$store.state.num*this.$store.state.num
},
},
components: {
HelloWorld
}
}
</script>

}

{
import { createStore } from 'vuex'

export default createStore({
state: {
num:5,
dnum:0
},
getters:{//vuex计算属性
vxnum(state){
return state.num*state.num
}
},
mutations: {
sub(state){
state.dnum--
},
add(state){
state.dnum++
},
sub1(state,count){
state.dnum-=count
},
add1(state,count){
state.dnum+=count
},
sub2(state,payload){
state.dnum-=(payload.count+payload.num)
},
add2(state,payload){
state.dnum+=(payload.count+payload.num)
},
sub3(state,p){
state.dnum-=(p.payload.count+p.payload.num)
},
add3(state,p){
state.dnum+=(p.payload.count+p.payload.num)
},
},
actions: {
},
modules: {
}
})

}

P89 Actions异步处理操作mp4
context 上下文
包含state commit getters...
commit提交-------mutations
dispatch-------actions

{
import { createStore } from 'vuex'

export default createStore({
state: {
num:5,
dnum:0
},
getters:{//vuex计算属性
vxnum(state){
return state.num*state.num
}
},
mutations: {
sub(state){
state.num--
},
add(state){
state.num++
},
sub1(state,count){
state.dnum-=count
},
add1(state,count){
state.dnum+=count
},
sub2(state,payload){
state.dnum-=(payload.count+payload.num)
},
add2(state,payload){
state.dnum+=(payload.count+payload.num)
},
sub3(state,p){
state.dnum-=(p.payload.count+p.payload.num)
},
add3(state,p){
state.dnum+=(p.payload.count+p.payload.num)
},
},
actions: {
demo(context,payload){
setTimeout(()=>{
// context.state.num=99 //state
context.commit('add') //mutations
console.log(payload.name);
},300)
},
fun(context){
const {state,commit,getters}=context;//解构赋值
},
fun1({state,commit,getters}){}
},
modules: {
}
})

}

{
<template>
<div class="about">
<h1>This is an about page</h1>
{{$store.state.num}}
<br>
<button @click="$store.dispatch('demo',{count:22,name:'koo'})">click</button>
</div>
</template>

}

P90 Moduls模块划分和文件拆分.mp4
{
import { createStore } from 'vuex'

const user={
//user.state放到state里面 先访问state
state:()=>({
name:'koo',
age:22
}),
getters:{
full(state){
return state.name+state.age
},
full2(state,getters){
return getters.full+'11111111'
},
full3(state,getters,rootState){
return getters.full2+rootState.num
}
},
mutations:{
//先在mutations找 找不到 找user.mutations 直接commit
//俩个地方 方法名同样 一块执行 用命名空间隔开
setName(state,payload){
state.name=payload
}
},
actions:{
dosome(context){
console.log(context)//state getters commit rootState rootGetters
setTimeout(()=>{
context.commit('setName','hello vuex')
},2000)
}
}
}

export default createStore({
state: {
num:5,
dnum:0
},
getters:{//vuex计算属性
vxnum(state){
return state.num*state.num
}
},
mutations: {
sub(state){
state.num--
},
add(state){
state.num++
},
sub1(state,count){
state.dnum-=count
},
add1(state,count){
state.dnum+=count
},
sub2(state,payload){
state.dnum-=(payload.count+payload.num)
},
add2(state,payload){
state.dnum+=(payload.count+payload.num)
},
sub3(state,p){
state.dnum-=(p.payload.count+p.payload.num)
},
add3(state,p){
state.dnum+=(p.payload.count+p.payload.num)
},
},
actions: {
demo(context,payload){
setTimeout(()=>{
// context.state.num=99 //state
context.commit('add') //mutations
console.log(payload.name);
},300)
},
fun(context){
const {state,commit,getters}=context;//解构赋值
},
fun1({state,commit,getters}){}
},
modules: {
/*user:{
state:{},
getters:{},
mutations:{},
actions:{}
}*/
user:user
}
})

}

{
<template>
<div class="about">
{{$store.state.num}}
<br>
<button @click="$store.dispatch('demo',{count:22,name:'koo'})">click</button>
<br>
name:{{$store.state.user.name}}
<br>
<button @click="$store.commit('setName','john')">setName</button>
<br>
full:{{$store.getters.full}}
<br>
full2:{{$store.getters.full2}}
<br>
full3:{{$store.getters.full3}}
<br>
<button @click="$store.dispatch('dosome')">dosomeActions</button>
</div>
</template>

}

P91 CompositionAPI组合API介绍和体验
vue3 新增
组合式API(Composition API)
使用传统的option配置方法写组件的时候问题,随着业务复杂度越来越高,
代码量会不断的加大;由于相关业务的代码需要遵循option的配置写到特定的区域,
导致后续维护非常的复杂,同时代码可复用性不高,
而composition-api就是为了解决这个问题而生的。

Composition API字面意思是组合API,它是为了实现基于函数的逻辑复用机制而产生的。
主要思想是,我们将它们定义为从新的setup函数返回的JavaScript变量,
而不是将组件的功能(例如state method,computed等)定义为对象属性。

{
<template>
<div class="home">
data:{{data.count}}
<br>
double:{{data.double}}
<br>
<button @click="add">add</button>
</div>
</template>

<script>
import {reactive,computed} from 'vue'
export default {
setup(){
const data=reactive({
count:0,
double:computed(()=>data.count*2)
})
function add(){
data.count++
}
return {
data,
add
}
}
}
</script>

}

P92组合API入口方法setup详解.mp4
setup()方法应用

setup0)函数是vue3中专门新增的方法,可以理解为Composition Api的入口.
执行时机在beforecreate之后,create之前执行

setup函数在创建组件之前被调用,所以在setup被执行时,组件实例并没有被创建。
因此在setup函数中,我们将没有办法获取到this

{
<template>
1111111111
<slot>222222222</slot>
</template>

<script>
export default {
name: "SubComp",
props:{
one:{
type:String
}
},
// props是传过来的属性
// context是上下文
setup(props,context){
console.log(props.one)
//在创建组作之间调用的,没有this
console.log(this)
console.log(context.attrs.desc);//没有在props声明的
console.log(context.slots)
context.emit('myadd','向父组件传数据')
}

}
</script>

<style scoped>

</style>
}

{
<template>
SetUp
<sub-comp @myadd="add" desc="55555555" one="111111">
<h2>888888888888</h2>
</sub-comp>
</template>

<script>
import SubComp from "../components/SubComp";
export default {
name: "SetUp",
components:{
SubComp
},
methods:{
add(str){
console.log(str)
}
}
}
</script>

<style scoped>

</style>
}

context.attrs
context.slots
context.parent
context.root
context.emit
context.refs

P93 Composition中常用的API应用
97
ref()函数用来给定的值创建一个响应式的数据对象,ref0的返回值是一个对象,这个对象上只包含一个.value属性.
reactive是用来创建一个响应式对象
将ref响应式数据挂载到reactive中,当把ref()创建出来值直接挂载到reactive()中时,会自动把响应式数据对象的展开为原始的值,不需要通过.value就可以直接访问到
双向绑定
toRefs()解构响应式对象
readonly将响应式数据变回原使数据

{
<template>
<div>
API
<br>
原生的:{{num}}
<br>
调用方法:{{fun()}}
<br>
Ref的变量:{{num2}}
<button @click="fun2(55)">add</button>
<br>
<!-- reactive的对象:{{user.name}}-&#45;&#45;{{user.age}}-->
toRefs:{{name}}---{{age}}<br>
name: <input type="text" v-model="name"><br>
age: <input type="text" v-model="age"><br>
</div>
</template>

<script>
import {ref,reactive,toRefs,readonly,isRef} from 'vue'
export default {
name: "ComApi",
setup(){
let num=1;
let fun=()=>{
num++;
console.log(num)
}
let num2=ref(1)
let fun2=(newvalue)=>{
num2.value=newvalue
}
let user=reactive({
name:'koo',
age:22
})
//响应式to原生
let user2=readonly(user)
//isRef判断是否响应式
let num3=isRef(num2)?num2.value=44:num2=55;
return {
num,
fun,
num2,
fun2,
// ...user
...toRefs(user)
}
}
}
</script>

<style scoped>

</style>
}

ref reactive toRefs isRef readonly

P94 Composition中的computed计算属性API

{
<template>
<h2>计算属性</h2>
firstname: <input type="text" v-model="firstname"><br>
lastname: <input type="text" v-model="lastname"><br>
{{firstname+' '+lastname}} <br>
{{fullname}}
</template>

<script>
import {reactive,toRefs,computed} from 'vue'
export default {
name: "ComputedDemo",
setup(){
let user=reactive({
firstname:'koo',
lastname:'john',
fullname:computed(()=>{
//木有this
return user.firstname+' '+user.lastname
})
})
return {
...toRefs(user)
}
}
}
</script>

<style scoped>

</style>
}

computed()用来创建计算属性,返回值是一个ref的实例。

ref reactive toRefs isRef readonly computed

P95 CompositionAPI侦听器watch.mp4
watch()函数用来监视某些数据项的变化,从而触发某些特定的操作
watchEffect立即执行传入的一个函数,并响应式追踪其依赖,并在其依赖变更时重新运行该函数。

第三个参数immediate:其值是true或false:确认是否以当前的初始值执行handler的函数。

{
<template>
<div>
<h2>Watch</h2>
<button @click="a++">a:{{a}}</button>
<button @click="b++">b:{{b}}</button>
</div>
</template>

<script>
import {ref,reactive,toRefs,watch,watchEffect} from 'vue'
export default {
name: "WatchDemo",
setup(){
let user=reactive({
a:1,
b:2
})

watch([()=>user.a,()=>user.b],([newA,newB],[oldA,oldB])=>{
console.log(newA+'-------'+oldA);
console.log(newB+'-------'+oldB);
})

// watch(user,()=>{
// console.log('111111111')
// })

return {
...toRefs(user)
}
}

/*setup(){
let a=ref(1)
let b=ref(2)

// watch(()=>{
// console.log(a.value+'------'+b.value)
// })

watch([a,b],([newA,newB],[oldA,oldB])=>{
console.log(newA+'-------'+oldA);
console.log(newB+'-------'+oldB);
},{immediate:true})

// watch(a,(newA,oldA)=>{
// console.log(newA+'-------'+oldA);
// },{immediate:true})
//第三个参数immediate:其值是true或false:确认是否以当前的初始值执行handler的函数。

// watchEffect(()=>{
// console.log(a.value+'------'+b.value)
// })

return {
a,
b,
}
}*/
}
</script>

<style scoped>

</style>
}

ref reactive toRefs isRef readonly computed watch watchEffect

P96 Composition中的生命期API
生命周期与Composition之间的映射关系
在新版的生命周期函数,可以按需导入到组件中,且只能在setup()函数中使用.
beforCreate->use setup() x
created->use setup() x
beforeMount->onBeforeMount
mounted->onMounted
beforeUpdate->onBeforeUpdate
updated->onUpdated
beforeUnmonut->onBeforeUnmount
unmounted->onUnmounted

多个on

是api 需要引入

<template>

</template>

<script>
import {onMounted} from 'vue'
export default {
name: "LifeHook",
setup(){
onMounted(()=>{
console.log('onMounted.......');
})
}
}
</script>

<style scoped>

</style>

P97在组合API中provide和inject使用
父子组件:通过props,$emit,【$root,$parent,$children】
非父子组件:Vuex实现,父子层层传递、$ref

provide/inject这对选项允许一个祖先组件向其所有子孙后代组件注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。
provide就相当于加强版父组件prop,可以跨越中间组件,inject就相当于加强版子组件的props

provide提供
inject注入


{
<template>
<div>
Root
<br>
{{title}}
<br>
<input type="text" v-model="title">
<hr>
<two-comp></two-comp>
</div>
</template>

<script>
import TwoComp from "../components/TwoComp";
import {ref,provide,reactive,toRefs} from 'vue'
export default {
name: "RootApp",
components:{
TwoComp
},
// data(){
// return {
// title:'这是根组件提供的数据'
// }
// },
setup(){
let title=ref('这是根组件提供的数据')
let obj=reactive({
name:'koo',
age:22
})
provide('title',title)
provide('user',obj)
return {
title,
...toRefs(obj)
}
},
// provide:{
// title:'abc'
// }
// provide(){//子 孙 组件不响应式
// return {
// title:this.title
// }
// }
}
</script>

<style scoped>

</style>
}


{
<template>
Two
<three-comp></three-comp>
</template>

<script>
import ThreeComp from "./ThreeComp";
export default {
name: "TwoComp",
components:{
ThreeComp
}
}
</script>

<style scoped>

</style>
}


{
<template>
<h2>Three</h2>
{{title}}
<br>
<input type="text" v-model="title">
<br>
{{user.name}}---{{user.age}}
</template>

<script>
import {inject} from 'vue'
export default {
name: "ThreeComp",
// inject:['title']
setup(){
let title=inject('title')
return {
title,
user:inject('user')
}
}
}
</script>

<style scoped>

</style>
}

ref reactive toRefs isRef readonly computed life watch watchEffect provide inject

P98 Composition APl结合路由器使用

学习手册:https://vue3js.cn/vue-composition-api

{
<template>
MyPage
<br>
<h3>{{$route.params.id}}</h3>
<h3>{{pid}}</h3>
<h2>id:{{id}}</h2>
</template>

<script>
import {useRoute,useRouter,onBeforeRouteLeave,onBeforeRouteUpdate} from 'vue-router'
import {watch,ref} from 'vue'
export default {
name: "MyPage",
setup(){
const route=useRoute();
const router=useRouter();
let id=ref(0)
watch(()=>route.params,(newid)=>{
console.log(newid.id)
id.value=newid.id
//异步请求服务器API查找用户信息。
})
//router离开
onBeforeRouteLeave((to,from)=>{
let answer= window.confirm(`你确定要从${from.fullPath}到${to.fullPath}`)
if(!answer)return false;
})
//router更新
onBeforeRouteUpdate()

/*setTimeout(()=>{
router.push({path:'/routerapi/article',query:{name:'888888',keyword:'hello'}})
},2000)*/
return {id}
},
computed:{
pid(){
return this.$route.params.id;
}
}
}
</script>

<style scoped>

</style>
}

{
<template>
<div>
<div id="menu">
<h5 v-for="item in pages">
<router-link :to="'/routerapi/page/'+item.id"> {{item.title}} </router-link>
</h5>
<h5><router-link :to="{path:'/routerapi/article',query:{name:'abc',keyword:'hello'}}">文章一</router-link></h5>
<h5><button @click="$router.push({path:'/routerapi/article',query:{name:'koo',keyword:'world'}})">文章二</button></h5>
</div>
<div id="content">
<router-view></router-view>
</div>
</div>
</template>

<script>
export default {
name: "RouterApi",
data(){
return {
pages:[
{id:1,title:'11111'},
{id:2,title:'11222'},
{id:3,title:'11333'},
{id:4,title:'11444'},
{id:5,title:'15555'},
]
}
}
}
</script>

<style scoped lang="scss">
#menu{
width: 30%;
background: #f0fff0;
height: 300px;
float: left;
}
#content{
width: 70%;
background: #cccccc;
height: 300px;
float: right;
}
a {
font-weight: bold;
color: #2c3e50;

&.router-link-exact-active {
color: #42b983;
}
}
</style>
}

{
<template>
MyArticle
<br>
{{$route.query.name}}<br>
{{$route.query.keyword}}
</template>

<script>
export default {
name: "MyArticle"
}
</script>

<style scoped>

</style>
}

P99 Composition API结合Vuex使用
103
{
<template>
<div>
<h2>Vuex API useStore</h2>
num1:{{num1}}
</div>
</template>

<script>
import {useStore} from 'vuex'
import {computed} from 'vue'
export default {
name: "VuexApi",
setup(){
const store=useStore();
return {
num1:computed(()=>store.state.num1*2)
}
}
}
</script>

<style scoped>

</style>
}

vuex
store/index.js
{
import { createStore } from 'vuex'

export default createStore({
state: {
num1:11
},
mutations: {
},
actions: {
},
modules: {
}
})

}


P100 Vue3.x总结和作业安排mp4
P101 Vue3.x项目说明和开发目标
VUE 3.x项目介绍(EWShop)
项目说明
后台开发:PHP+Laravel+MySQL + Redis + Restrestful api接口规范
前台模板:Vue3.x+ Composition APl + Vant组件库
后台管理:React
接口文档:https://www.showdoc.com.cn/1207745568269674

P102项目的需求分析和接口文档说明

P103使用vue脚手架创建ewshop项目
>vue create ewshop
创建目录

P104初使化项目设置目录别名.mp4
import HelloWorld from '@/components/HelloWorld.vue'
import HelloWorld from '../components/HelloWorld.vue'
@别名 ==
<img src="@/assets/images/1.jpg" alt="">

data(){
return{
imgsrc:require('../assets/images/2.jpg')
}
},

vue.config.js
{
module.exports={
configureWebpack:{
resolve:{
alias:{
'assets':'@/assets' //起别名
}
}
},
publicPath:'./' //打包到
}
}

重启

使用
script
imgsrc:require('assets/images/2.jpg')
import HelloWorld from 'components/HelloWorld.vue'
template
<img src="~assets/images/1.jpg" alt="">

style
#demo{
background: url("~assets/images/3.jpg") no-repeat;
width: 100px;
height: 100px;
}

P105初使化项目的全局样式内容.mp4
https://gitee.com/qscgu23/normalize.css?_from=gitee_search

base.css{
@import './normalize.css';
:root{
--color-text:#666;
--color-high-text:#42b8aa;
--color-tint:#42b983;
--color-background:#FFFFFF;
--font-size:14px;
--line-height:1.5;
}
*,*::before,*::after{
margin: 0;
padding: 0;
box-sizing: border-box;
}
body{
user-select: none;/*禁止用户选择中文件或图片*/
background: var(--color-background);
color: var(--color-text);
width: 100vw;
}
a{
color: var(--color-text);
text-decoration: none;
}
.left{
float: left;
}
.right{
float: right;
}
}

P106初使化项目封装网络请求.mp4

P107项目的导航菜单制作mp4
111
icon下载
https://www.iconfont.cn/search/index?searchType=icon&q=%E8%B4%AD%E7%89%A9%E8%BD%A6

P108项目标题栏的设计开发.mp4

路由导航守卫
router.beforeEach

P109设计和开发首页推荐商品组件

P110设计和开发首页选项卡组件.mp4
position: sticky;//css3新加固定

P111商品列表组件设计和开发.mp4
115
z-index 显示位置顺序
flex布局+

P112商品列表绑定接口数据.mp4

选项卡 计算属性

P113开发上拉加戴更多数据.mp4
BetterScroll是什么
BetterScroll是一款重点解决移动端(已支持PC)各种滚动场景需求的插件
>npm i better-scroll -S

height:100vh 沾满整个屏幕

nextTick() dom下次刷新

P114处理上拉加载数据和导航条固定

P115回到顶部组件和keep-alife使用
keep-alive
vue3
<router-view v-slot="{Component}">
<transition>
<keep-alive>
<component :is="Component"/>
</keep-alive>
</transition>
</router-view>

P116安装和使用vant组件库(swiper)
vant 看说明文档使用
UI
>npm i vant@next -S
插件plugins
npm i babel-plugin-import -D

babel.config.js
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
],
plugins: [
['import',{
libraryName:'vant',
libraryDirectory:'es',
style:true
},'vant']
]
}
img{
width: 100%;
height: auto !important;
}

P117 Vant组件库的使用图片懒加载和徽章
121
crx用多少找多少 jdg

P118分类页面布局和菜单.mp4

P119编写分类的页面的交互模式.mp4

P120从接口中获取分类数据.mp4

P121处理上拉加载更多数据 better-scroll

P122 获取商品详情信息.mp4
126

P123渲染商品数据到模板中.mp4
!important强制

P124用户注册的组件开发.mp4

P125完成用户注册和验证mp4
vant官网
https://vant-contrib.gitee.io/vant/#/zh-CN/home

P126用户登录开发过程.mp4

P127用户登录授权方案处理.mp4
131
P128添加购物车.mp4

P129获取购物车列表和数量改变操作

P130改变购物车选中的状态mp4

P131删除购物车商品和计算总价.mp4

P132个人中心的功能设计和开发.mp4
136

P133封装地址的网络请求方法.mp4

P134添加地址信息.mp4

P135遍历地址列表信息mp4
isDefault:!!item.is_default 变成boolean 俩个!

P136编辑地址信息mp4

P137 封装订单网络请求模块.mp4
141

P138编写订单预览.mp4

P139创建订单.mp4

P140订单支付流程编写.mp4

P141订单详情处理(上).mp4

P142订单详情处理(下).mp4
146
scss{
$color:red;
@mixin fn($color:red){

}
.a{
color:red;
}
.b{
@extend .a;
}
}

P143处理订单列表数据.mp4

P144处理订单列表下拉加载更多.mp4

P145项目安装上线运行.mp4

 

posted @ 2024-12-14 13:54  KooTeam  阅读(66)  评论(0)    收藏  举报