VUE2从入门到精通(一)

****************************************************************************************************************************************************************************

1、课程概述
【1】前置储备:HTML+CSS+JS、WebAPI、Ajax、Node.js
【2】1天:前端工程化+Webpack。2天:vue的使用步骤、指令、调试工具。3天:过滤器、监听器、计算属性、axios、vue-cli。
4天:组件与生命周期。5天:ref+购物车案例。6天:vue组件的高级用法、动态组件、插槽的使用。7天:路由。8天:黑马头条.

****************************************************************************************************************************************************************************

2、前端工程化
【1】模块化、组件化、规范化、自动化。
【2】前端工程化:在企业级的前端项目开发中,把前端相关的技术规划化、标准化。
【3】主流的工程化方案:webpack 网址:https://www.webpackjs.com

****************************************************************************************************************************************************************************

3、webpack的基本使用
【1】它提供了友好的前端开发支持,以及代码混淆、处理浏览器js的兼容性、性能优化等强大功能。
【2】程序员放心的写高级代码,webpack负责转换成低版本浏览器也能跑,就完事了。

****************************************************************************************************************************************************************************

4、webpack正式使用
【1】列表隔行变色需求的实现。
npm init -y
******************************************
新建src文件+index.html+index.js
******************************************
npm install jquery -S   (-S 就是记录参数到package.json里去 就是--save的缩写,开发和上线都需要的包)
******************************************
通过es6导入jQuery
【2】Uncaught SyntaxError: Cannot use import statement outside a module   语法错误
【3】报错的解决
npm install webpack@5.42.1 webpack-cli@4.7.2 -D   (-D是说明记录到package.json,但是它是记录到devDependencies节点,只在开发阶段会用到的包,
上线不需要--save-dev的简写)
******************************************安装后配置
在项目跟目录下,创建webpack.config.js文件。并初始化基本配置:
module.exports = {
    mode: 'development'  // 用来指定构建模式
}
******************************************在package.json的scripts节点,新增dev脚本
"scripts":{
    "dev": "webpack"  // 通过npm run dev运行的就是这个脚本webpack
}
******************************************终端运行命令
npm run dev
******************************************然后在dist下面生成了main.js文件,这个文件就是对index.js的兼容性升级,引入后
最后访问index.html就能成功使用了!!!!!!!!!!!!!
【4】大小压缩
// 使用nodejs导出一个webpack对象
module.exports = {
    mode: 'production' // production(小,慢,上线的时候用)  development(大,快,开发的时候用)
}
*******************************************
asset main.js 88.5 KiB  大小变小了4倍多。

****************************************************************************************************************************************************************************

8、webpack.config.js执行过程
【1】在执行npm run dev之前就会被读取,然后根据配置运行webpack
【2】默认约定是打包src下面的index.js,输出是dist下面的main.js
【3】通过个性化配置可以改变输出路径。entry指定打包的路径,output可以指定打包输出路径。
【4】每次修改index.js 都需要重新打包webpack,再访问才能生效...
【5】通过插件来解决,使用webpack-dev-server        npm i webpack-cli -D(注意版本之间的兼容性)
npm install webpack-dev-server@3.11.2 -D
******************************************修改脚本命令内容
"scripts":{
    "dev": "webpack serve"
}
******************************************执行命令
npm run dev
******************************************访问发现可以访问,但是修改代码颜色没有变化
webpack output is served from /  根据这个提示改配置。
<!--这里使用的是内存里的main.js-->
<script src="/main.js"></script>
******************************************就解决了修改代码,颜色不变化的问题
牛批呀!!!!!!!!!!!!!

****************************************************************************************************************************************************************************

11、安装配置html-webpack
【1】优化不点击src就能看到index的页面
【2】安装html-webpack-plugin
npm i html-webpack-plugin@5.3.2 -D
【3】配置
// 使用nodejs导出一个webpack对象
// 1.导入html-webpack-plugin
const HtmlPlugin = require("html-webpack-plugin");
// 2.new构造函数,创建实例对象
const htmlPlugin = new HtmlPlugin({
    template: './src/index.html', // 被复制文件路径
    filename: './index.html' // 复制的文件路径
});

module.exports = {
    mode: 'development', // production  development
    // 插件的数组 webpack在运行时会加载并调用这些插件
    plugins: [htmlPlugin]
}
【4】重新运行,npm run dev 访问localhost:8080就会访问复制出来的index.html 它是存在内存中的。
【5】而且html-webpack-plugin会自动加载内存中的main.js,不用写加载代码也可以。
【6】自动打开浏览器访问,并指定端口号
module.exports = {
    mode: 'development', // production  development
    // 插件的数组 webpack在运行时会加载并调用这些插件
    plugins: [htmlPlugin],
    devServer: {
        open: true, // 自动打开浏览器
        port: 80
    }
}

****************************************************************************************************************************************************************************

14、webpack里的loader
【1】如果不是.js文件,需要loader加载器进行正常的打包。
【2】比如不要li前面的点,需要引入css文件,如果用loader来处理?
npm i style-loader -D
****************************************安装处理器
npm i css-loader -D
****************************************执行
npm run dev
【3】这样就成功实现了加载css文件的loader处理。
【4】会先转交给后一个loader,然后再给style-loader,再把处理结果转给webpack,webpack把处理结果合并到main.js
module.exports = {
    mode: 'development', // production  development
    // 插件的数组 webpack在运行时会加载并调用这些插件
    plugins: [htmlPlugin],
    devServer: {
        open: true, // 自动打开浏览器
        port: 80
    },
    module: {
        rules: [
            // 定义了不同模块对应的loader
            {test: /.css$/, use: ['style-loader', 'css-loader']}
        ]
    }
}
【5】打包less功能
npm i less-loader less -D
****************************************安装处理器
module.exports = {
    mode: 'development', // production  development
    // 插件的数组 webpack在运行时会加载并调用这些插件
    plugins: [htmlPlugin],
    devServer: {
        open: true, // 自动打开浏览器
        port: 80
    },
    module: {
        rules: [
            // 定义了不同模块对应的loader
            {test: /.less$/, use: ['style-loader', 'css-loader', 'less-loader']},
            {test: /.css$/, use: ['style-loader', 'css-loader']}
        ]
    }
}

****************************************************************************************************************************************************************************

17、webpack打包图片
【1】图片转成base64后展示,但是体积转换后可能变大点。所以大图片就不建议转了。
【2】用webpack打包图片的路径。
npm i url-loader file-loader -D
**********************************************index.js
import "./css/index.less"
// 导入样式   在webpack中一切皆模块,都可以通过es6进行导入和使用
import "./css/index.css"  // 就需要合适的loader来处理

// 1.导入图片
import logo from "./res/1.jpg"

console.log(logo);
// 2. 给img标签的src动态赋值
$(".box").attr("src", logo)

// 使用es6导入语法 导入jquery
import $ from 'jquery'
// 定义jquery的入口函数
$(function () {
    // 实现行变色效果
    $('li:odd').css('background-color', 'red');
    $('li:even').css('background-color', 'yellow');
})
************************************************webpack.config.js
// 使用nodejs导出一个webpack对象
// 1.导入html-webpack-plugin
const HtmlPlugin = require("html-webpack-plugin");
// 2.new构造函数,创建实例对象
const htmlPlugin = new HtmlPlugin({
    template: './src/index.html', // 被复制文件路径
    filename: './index.html' // 复制的文件路径
});

module.exports = {
    mode: 'development', // production  development
    // 插件的数组 webpack在运行时会加载并调用这些插件
    plugins: [htmlPlugin],
    devServer: {
        open: true, // 自动打开浏览器
        port: 80
    },
    module: {
        rules: [
            // 定义了不同模块对应的loader
            {test: /.less$/, use: ['style-loader', 'css-loader', 'less-loader']},
            {test: /.css$/, use: ['style-loader', 'css-loader']},
            {test: /.jpg|png|gif$/, use: 'url-loader?limit=22229'}
        ]
    }
}

****************************************************************************************************************************************************************************

20、是否需要接收
【1】如果接收到的对象为undefined,这import .. from 的from就不用接收了,直接import就可以了。
【2】?limit=22229 文件的大小上限,不能大于22229字节,就是2.2M左右。

****************************************************************************************************************************************************************************

22、webpack如果打包高级语法
【1】就是如何打包一些架构的高级代码语法?
npm i babel-loader @babel/core @babel/plugin-proposal-decorators -D
*************************************************************************************安装装饰器
 {test: /.js$/, use: 'babel-loader', exclude: /node_modules/} // 一定要排除node_modules,因为第三方包不需要你管
【2】在项目根目录下,创建名字为babel.config.js配置文件,定义配置如下:
module.exports={
    plugins:[['@babel/plugin-proposal-decorators',{legacy:true}]]
}

****************************************************************************************************************************************************************************

23、发布上线
【1】加一个命令如下:
"scripts": {
    "dev": "webpack serve",
    "build": "webpack --mode production"  // 这里使用production发布,覆盖serve里那个development
  },
*****************************************************************
dist下就会生成对应的打包发布后的文件。

****************************************************************************************************************************************************************************

24、发布的资源分类存储
【1】js文件放到js文件夹下面,完整配置如下
// 使用nodejs导出一个webpack对象
const path = require("path"); // 首先我们在webpack.config.js中引入path模块
// 1.导入html-webpack-plugin
const HtmlPlugin = require("html-webpack-plugin");
// 2.new构造函数,创建实例对象
const htmlPlugin = new HtmlPlugin({
    template: './src/index.html', // 被复制文件路径
    filename: './index.html' // 复制的文件路径
});

module.exports = {
    mode: 'development', // production  development
    // 插件的数组 webpack在运行时会加载并调用这些插件
    output: {
        path: path.join(__dirname, 'dist'),
        filename: "js/main.js"
    },
    plugins: [htmlPlugin],
    devServer: {
        open: true, // 自动打开浏览器
        port: 80
    },
    module: {
        rules: [
            // 定义了不同模块对应的loader
            {test: /.less$/, use: ['style-loader', 'css-loader', 'less-loader']},
            {test: /.css$/, use: ['style-loader', 'css-loader']},
            {test: /.jpg|png|gif$/, use: 'url-loader?limit=22229&outputPath=images'},
            // 处理高级语法
            // {test: /.js$/, use: 'babel-loader', exclude: /node_modules/}
        ]
    }
}
【2】图片放到images文件下面
*********************************************************
  module: {
        rules: [
            // 定义了不同模块对应的loader
            {test: /.less$/, use: ['style-loader', 'css-loader', 'less-loader']},
            {test: /.css$/, use: ['style-loader', 'css-loader']},
            {test: /.jpg|png|gif$/, use: 'url-loader?limit=22229&outputPath=images'},
            // 处理高级语法
            // {test: /.js$/, use: 'babel-loader', exclude: /node_modules/}
        ]
    }

****************************************************************************************************************************************************************************

25、每次打包发布自动删除原有文件
【1】安装插件
npm i clean-webpack-plugin -D
【2】新的配置
// 使用nodejs导出一个webpack对象
const path = require("path"); // 首先我们在webpack.config.js中引入path模块
// 1.导入html-webpack-plugin
const HtmlPlugin = require("html-webpack-plugin");
// 2.new构造函数,创建实例对象
const htmlPlugin = new HtmlPlugin({
    template: './src/index.html', // 被复制文件路径
    filename: './index.html' // 复制的文件路径
});
const {CleanWebpackPlugin} = require("clean-webpack-plugin"); //!!!!!!!!!!!!!!!!!!!!!!!!! 解构赋值

module.exports = {
    mode: 'development', // production  development
    // 插件的数组 webpack在运行时会加载并调用这些插件
    output: {
        path: path.join(__dirname, 'dist'),
        filename: "js/main.js"
    },
    plugins: [htmlPlugin, new CleanWebpackPlugin()], //!!!!!!!!!!!!!!!!!!!!!!!!!
    devServer: {
        open: true, // 自动打开浏览器
        port: 80
    },
    module: {
        rules: [
            // 定义了不同模块对应的loader
            {test: /.less$/, use: ['style-loader', 'css-loader', 'less-loader']},
            {test: /.css$/, use: ['style-loader', 'css-loader']},
            {test: /.jpg|png|gif$/, use: 'url-loader?limit=22229&outputPath=images'},
            // 处理高级语法
            // {test: /.js$/, use: 'babel-loader', exclude: /node_modules/}
        ]
    }
}

****************************************************************************************************************************************************************************

27、Source Map
【1】记录原来的行号,方便程序员快速定位报错的行。
// 使用nodejs导出一个webpack对象
const path = require("path"); // 首先我们在webpack.config.js中引入path模块
// 1.导入html-webpack-plugin
const HtmlPlugin = require("html-webpack-plugin");
// 2.new构造函数,创建实例对象
const htmlPlugin = new HtmlPlugin({
    template: './src/index.html', // 被复制文件路径
    filename: './index.html' // 复制的文件路径
});
const {CleanWebpackPlugin} = require("clean-webpack-plugin");

module.exports = {
    mode: 'development', // production  development
    devtool: 'eval-source-map', // 看这里!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    // 插件的数组 webpack在运行时会加载并调用这些插件
    output: {
        path: path.join(__dirname, 'dist'),
        filename: "js/main.js"
    },
    plugins: [htmlPlugin, new CleanWebpackPlugin()],
    devServer: {
        open: true, // 自动打开浏览器
        port: 80
    },
    module: {
        rules: [
            // 定义了不同模块对应的loader
            {test: /.less$/, use: ['style-loader', 'css-loader', 'less-loader']},
            {test: /.css$/, use: ['style-loader', 'css-loader']},
            {test: /.jpg|png|gif$/, use: 'url-loader?limit=22229&outputPath=images'},
            // 处理高级语法
            // {test: /.js$/, use: 'babel-loader', exclude: /node_modules/}
        ]
    }
}
【2】生产环境需要注释掉devtool选项,这样才更安全!!!!!!!!!!!!!!
【3】或者生产环境只暴露行号,nosources-source-map使用这个值。这个非常好!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// 使用nodejs导出一个webpack对象
const path = require("path"); // 首先我们在webpack.config.js中引入path模块
// 1.导入html-webpack-plugin
const HtmlPlugin = require("html-webpack-plugin");
// 2.new构造函数,创建实例对象
const htmlPlugin = new HtmlPlugin({
    template: './src/index.html', // 被复制文件路径
    filename: './index.html' // 复制的文件路径
});
const {CleanWebpackPlugin} = require("clean-webpack-plugin");

module.exports = {
    mode: 'development', // production  development
    devtool: 'nosources-source-map',
    // 插件的数组 webpack在运行时会加载并调用这些插件
    output: {
        path: path.join(__dirname, 'dist'),
        filename: "js/main.js"
    },
    plugins: [htmlPlugin, new CleanWebpackPlugin()],
    devServer: {
        open: true, // 自动打开浏览器
        port: 80
    },
    module: {
        rules: [
            // 定义了不同模块对应的loader
            {test: /.less$/, use: ['style-loader', 'css-loader', 'less-loader']},
            {test: /.css$/, use: ['style-loader', 'css-loader']},
            {test: /.jpg|png|gif$/, use: 'url-loader?limit=22229&outputPath=images'},
            // 处理高级语法
            // {test: /.js$/, use: 'babel-loader', exclude: /node_modules/}
        ]
    }
}

****************************************************************************************************************************************************************************

30、实际开发中需要自己配置webpack吗?
【1】不需要,都是默认配置好的...
【2】../../这种层级太多不方便理解,建议使用@表示src源代码目录,从外往里找,不要使用../从里往外找
// 使用nodejs导出一个webpack对象
const path = require("path"); // 首先我们在webpack.config.js中引入path模块
// 1.导入html-webpack-plugin
const HtmlPlugin = require("html-webpack-plugin");
// 2.new构造函数,创建实例对象
const htmlPlugin = new HtmlPlugin({
    template: './src/index.html', // 被复制文件路径
    filename: './index.html' // 复制的文件路径
});
const {CleanWebpackPlugin} = require("clean-webpack-plugin");

module.exports = {
    mode: 'development', // production  development
    devtool: 'nosources-source-map',
    // 插件的数组 webpack在运行时会加载并调用这些插件
    output: {
        path: path.join(__dirname, 'dist'),
        filename: "js/main.js"
    },
    plugins: [htmlPlugin, new CleanWebpackPlugin()],
    devServer: {
        open: true, // 自动打开浏览器
        port: 80
    },
    module: {
        rules: [
            // 定义了不同模块对应的loader
            {test: /.less$/, use: ['style-loader', 'css-loader', 'less-loader']},
            {test: /.css$/, use: ['style-loader', 'css-loader']},
            {test: /.jpg|png|gif$/, use: 'url-loader?limit=22229&outputPath=images'},
            // 处理高级语法
            // {test: /.js$/, use: 'babel-loader', exclude: /node_modules/}
        ]
    },
    resolve: {
        alias: {
            // 告诉webpack @表示src这一层目录 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            '@': path.join(__dirname, './src/')
        }
    }
}

****************************************************************************************************************************************************************************

32、vue概述(第2天的内容了)
【1】vue一套用于构建 用户界面 的前端 框架
【2】学习vue就是学习框架中规定的用法
【3】指令、组件、路由、Vuex,只有掌握所有内容,才有开发vue的能力
【4】数据驱动视图、双向数据绑定。
页面结构——(自动渲染)——vue监听数据变化——(变化)——页面所依赖的数据
******************************************
数据驱动视图,页面自动渲染。程序员只管数据就行了,不用操作dom了!!!
******************************************
双向数据绑定,form表单采集数据,ajax负责提交数据。页面上表达采集的数据发生变化时,会被vue获取到,并更新到js数据中
******************************************
M V VM 核心原理。Model(页面渲染时用的数据源) View(当前页面的DOM结构) ViewModel(vue的实例,它是m v vm的核心)
View——(自动渲染)——ViewModel(vue)——(变化)——Model
【5】vue的版本 vue1被淘汰了,vue2 vue3两个版本在用。

****************************************************************************************************************************************************************************

35、基本使用
【1】基础项目
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>主页</title>
</head>
<body>
<div id="app">
    {{name}}
</div>
</body>
<!--1.导入vue.js-->
<script src="./src/lib/vue.js"></script>
<!--2.创建vue实例-->
<script>
    const vm = new Vue({
        el: '#app',
        data: {
            name: '陈翔'
        }
    })
</script>
</html>

****************************************************************************************************************************************************************************

37、内容渲染指令
【1】指令就是模板语法,辅助开发者渲染页面基本结构的。最常用、最基础、最简单的知识。
【2】六大类:内容渲染、属性绑定、事件绑定、双向绑定、条件渲染、列表渲染六大指令。
【3】v-text会覆盖元素内容原有的内容,用的不多。 {{}}胡子语法,解决内容覆盖问题的,使用频率高。 v-html,如果想保留富文本数据的格式。
<div id="app">
    <p v-text="name"></p>
    <p>性别:{{age}}</p>
    <p v-html="info"></p>
</div>
*****************************************************************************
 const vm = new Vue({
        el: '#app',
        data: {
            name: '陈翔',
            age: 21,
            info: '<h1> 搞笑</h1>'
        }
    })
*****************************************************************************

****************************************************************************************************************************************************************************

39、属性绑定指令
【1】v-bind:属性,可以简写为:属性。对元素的属性进行动态绑定,用的非常多,非常多!!!所以建议简写为:属性。
<div id="app">
    <input :placeholder="tips"/>
</div>
******************************************************
  const vm = new Vue({
        el: '#app',
        data: {
            name: '陈翔',
            age: 21,
            tips: '请输入用户名称'
        }
    });

****************************************************************************************************************************************************************************

40、胡子函数与属性绑定可以写简单的运算
【1】{{age+2}}、反转运算等也可以
【2】:id="'list-'+id"

****************************************************************************************************************************************************************************

41、事件绑定
【1】v-on:click="addAge",简写为@click="addAge"
<div id="app">
    年龄:{{age}}
    <br/><br/>
    <button v-on:click="addAge">过年+1</button>
    <button v-on:click="backAge">回忆-1</button>
</div>
****************************************************************************
    const vm = new Vue({
        el: '#app',
        data: {
            name: '陈翔',
            age: 21,
        },
        methods: {
            addAge() {
                this.age = this.age + 1;
            },
            backAge() {
                this.age = this.age - 1;
            }
        }
    });

****************************************************************************************************************************************************************************

44、绑定函数并传参
【1】传参需要加个小括号
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>主页</title>
</head>
<body>
<div id="app">
    年龄:{{age}}
    <br/><br/>
    <button v-on:click="addAge(2)">过年+2</button>
    <button v-on:click="backAge(3)">回忆-3</button>
</div>
</body>
<!--1.导入vue.js-->
<script src="./src/lib/vue.js"></script>
<!--2.创建vue实例-->
<script>
    const vm = new Vue({
        el: '#app',
        data: {
            name: '陈翔',
            age: 21,
        },
        methods: {
            addAge(m) {
                this.age = this.age + m;
            },
            backAge(n) {
                this.age = this.age - n;
            }
        }
    });
</script>
</html>
【2】@click @input @keyup监听其他事件

****************************************************************************************************************************************************************************

46、事件绑定$event
【1】这个就是解决传参时获取原生事件而使用的。$event是固定写法
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>主页</title>
</head>
<body>
<div id="app">
    年龄:{{age}}
    <br/><br/>
    <button v-on:click="addAge(2)">过年+2</button>
    <button v-on:click="backAge(3,$event)">回忆-3</button>
</div>
</body>
<!--1.导入vue.js-->
<script src="./src/lib/vue.js"></script>
<!--2.创建vue实例-->
<script>
    const vm = new Vue({
        el: '#app',
        data: {
            name: '陈翔',
            age: 21,
        },
        methods: {
            addAge(m) {
                this.age = this.age + m;
            },
            backAge(n, e) {
                this.age = this.age - n;
                // 判断this.age的值是否为偶数
                let button = e.target;
                if (this.age % 2 == 0) {
                    button.style.backgroundColor = 'red';
                } else {
                    button.style.backgroundColor = 'green';
                }
            }
        }
    });
</script>
</html>

****************************************************************************************************************************************************************************

47、事件修饰符
【1】阻止默认跳转,@click.stop阻止事件冒泡
<a href="https://www.baidu.com" @click.prevent="jump">跳转到百度首页</a>
methods: {
            jump() {
                console.log("点击了a链接")
            }
        }
**************************************
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>主页</title>
</head>
<body>
<div id="app">
    <a href="https://www.baidu.com" @click="jump">跳转到百度首页</a>
</div>
</body>
<!--1.导入vue.js-->
<script src="./src/lib/vue.js"></script>
<!--2.创建vue实例-->
<script>
    const vm = new Vue({
        el: '#app',
        data: {
            name: '陈翔',
            age: 21,
        },
        methods: {
            jump(e) {
                e.preventDefault();
                console.log("点击了a链接")
            }
        }
    });
</script>
</html>

****************************************************************************************************************************************************************************

49、事件绑定-按键修饰符
【1】@keyup.enter="submit"  @keyup.esc="clear"
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>主页</title>
</head>
<body>
<div id="app">
    <input type="text" @keyup.esc="clear"/>
</div>
</body>
<!--1.导入vue.js-->
<script src="./src/lib/vue.js"></script>
<!--2.创建vue实例-->
<script>
    const vm = new Vue({
        el: '#app',
        data: {
            name: '陈翔',
            age: 21,
        },
        methods: {
            clear(e) {
                let input = e.target;
                input.value = "";
            }
        }
    });
</script>
</html>

****************************************************************************************************************************************************************************

50、双向绑定-v-model
【1】不操作dom的前提下,拿到表单提交的数据 :value="name"是单向绑定。而v-model="name"则是双向绑定了!!!!!!!!!
【2】只有表单元素使用v-model才有意义,不然其他的使用了就相当于:value,因为不能输入所以还是单向的。
【3】常见使用元素:input textarea select
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>主页</title>
</head>
<body>
<div id="app">
    <input type="text" v-model="name"/>
    <hr/>
    {{name}}
    <input type="text" :value="name"/>
</div>
</body>
<!--1.导入vue.js-->
<script src="./src/lib/vue.js"></script>
<!--2.创建vue实例-->
<script>
    const vm = new Vue({
        el: '#app',
        data: {
            name: '陈翔',
            age: 21,
        }
    });
</script>
</html>

****************************************************************************************************************************************************************************

51、v-model修饰符
【1】v-model.number。修饰符就是简单的过滤器。v-model.trim自动过滤用户输入的首尾空格字符。v-model.lazy 比如删除5个字符,只有在最后删除才同步。
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>主页</title>
</head>
<body>
<div id="app">
    <input type="text" v-model.number="dog"/>+ <input type="text" v-model.number="cat"/>=<span>{{dog+cat}}</span>
</div>
</body>
<!--1.导入vue.js-->
<script src="./src/lib/vue.js"></script>
<!--2.创建vue实例-->
<script>
    const vm = new Vue({
        el: '#app',
        data: {
            name: '陈翔',
            dog: 2,
            cat: 1
        }
    });
</script>
</html>

****************************************************************************************************************************************************************************

52、条件渲染指令
【1】v-if每次都是真的删除或创建。 v-show是切换样式的(如果频繁的切换用这个)
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>主页</title>
</head>
<body>
<div id="app">
    <span v-if="flag">v-if</span>
    <hr/>
    <span v-show="flag">v-show</span>
    <hr/>
    <button @click="flag=!flag">点击我换一下</button>
</div>
</body>
<!--1.导入vue.js-->
<script src="./src/lib/vue.js"></script>
<!--2.创建vue实例-->
<script>
    const vm = new Vue({
        el: '#app',
        data: {
            name: '陈翔',
            age: 20,
            flag: true
        }
    });
</script>
</html>

****************************************************************************************************************************************************************************

53、v-if配套指令
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>主页</title>
</head>
<body>
<div id="app">
    <h1 v-if="flag">Vue is awesome!</h1>
    <h1 v-else>Oh no!!!</h1>
    <hr/>
    <button @click="flag=!flag">点我</button>
</div>
</body>
<!--1.导入vue.js-->
<script src="./src/lib/vue.js"></script>
<!--2.创建vue实例-->
<script>
    const vm = new Vue({
        el: '#app',
        data: {
            name: '陈翔',
            age: 20,
            flag: false
        }
    });
</script>
</html>

****************************************************************************************************************************************************************************

54、v-for基本用法
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>主页</title>
</head>
<body>
<div id="app">
    <table class="table table-bordered table-hover table-striped">
        <thead>
        <tr>
            <td>索引</td>
            <td>ID</td>
            <td>姓名</td>
        </tr>
        </thead>
        <tbody>
        <tr v-for="(temp,index) in list">
            <td>{{index}}</td>
            <td>{{temp.id}}</td>
            <td>{{temp.name}}</td>
        </tr>
        </tbody>
    </table>

</div>
</body>
<link rel="stylesheet" href="./src/lib/bootstrap.css">
<!--1.导入vue.js-->
<script src="./src/lib/vue.js"></script>
<!--2.创建vue实例-->
<script>
    const vm = new Vue({
            el: '#app',
            data: {
                list: [
                    {id: 1, name: '陈翔'},
                    {id: 2, name: '球球'},
                    {id: 3, name: '米线'},
                ]
            }
        })
    ;
</script>
</html>

****************************************************************************************************************************************************************************

55、v-for循环中key
【1】用到了v-for,就要绑定一个:key,而且建议用id绑定。最好使用数值类型的。提升性能,又防止列表乱序。index当key没有意义,因为index会不断变化。
 <tr v-for="(temp,index) in list" :key="temp.id">

****************************************************************************************************************************************************************************

57、练习案例
【1】启用、停用
<input text="checkbox" v-model="temp.status">
<lable v-if="flag">已启用</lable>
<lable v-else>已禁用</lable>
【2】属性绑定
【3】删除单个商品
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>主页</title>
</head>
<body>
<div id="app">
    <table class="table table-bordered table-hover table-striped">
        <thead>
        <tr>
            <td>索引</td>
            <td>ID</td>
            <td>姓名</td>
            <td>操作</td>
        </tr>
        </thead>
        <tbody>
        <tr v-for="(temp,index) in list" :key="temp.id">
            <td>{{index}}</td>
            <td>{{temp.id}}</td>
            <td>{{temp.name}}</td>
            <td><a href="#" @click="remove(temp.id)">删除</a></td>
        </tr>
        </tbody>
    </table>

</div>
</body>
<link rel="stylesheet" href="./src/lib/bootstrap.css">
<!--1.导入vue.js-->
<script src="./src/lib/vue.js"></script>
<!--2.创建vue实例-->
<script>
    const vm = new Vue({
        el: '#app',
        data: {
            list: [
                {id: 1, name: '陈翔'},
                {id: 2, name: '球球'},
                {id: 3, name: '米线'},
            ]
        },
        methods: {
            remove(id) {
                this.list = this.list.filter(item => item.id !== id)
            }
        }
    });
</script>
</html>
【4】添加的功能
<input type="text" v-model.trim="inputName" />
***********************************************************************完整代码
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>主页</title>
</head>
<body>
<div id="app">
    <table class="table table-bordered table-hover table-striped">
        <thead>
        <tr>
            <td>索引</td>
            <td>ID</td>
            <td>姓名</td>
            <td>操作 <a href="#" @click="add('新的')">新增</a></td>
        </tr>
        </thead>
        <tbody>
        <tr v-for="(temp,index) in list" :key="temp.id">
            <td>{{index}}</td>
            <td>{{temp.id}}</td>
            <td>{{temp.name}}</td>
            <td><a href="#" @click="remove(temp.id)">删除</a></td>
        </tr>
        </tbody>
    </table>

</div>
</body>
<link rel="stylesheet" href="./src/lib/bootstrap.css">
<!--1.导入vue.js-->
<script src="./src/lib/vue.js"></script>
<!--2.创建vue实例-->
<script>
    const vm = new Vue({
        el: '#app',
        data: {
            nextId: 4,
            list: [
                {id: 1, name: '陈翔'},
                {id: 2, name: '球球'},
                {id: 3, name: '米线'},
            ]
        },
        methods: {
            remove(id) {
                this.list = this.list.filter(item => item.id !== id)
            },
            add(name) {
                // 如果是空字符串则return出去
                if (name === "") {
                    console.log("品牌名称为空");
                    return
                }
                // 执行添加
                let temp = {id: this.nextId, name: name};
                this.list.push(temp);
                this.nextId++;
            }
        }
    });
</script>
</html>

****************************************************************************************************************************************************************************

64、过滤器在vue3就不能用了
【1】简单了解即可。场景胡子表达式、v-bind属性绑定。
【2】管道符 |就能调用,过滤器本质上是一个函数。
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>主页</title>
</head>
<body>
<div id="app">
    <p>{{dog | myFilter}}</p>
</div>
</body>
<link rel="stylesheet" href="./src/lib/bootstrap.css">
<!--1.导入vue.js-->
<script src="./src/lib/vue.js"></script>
<!--2.创建vue实例-->
<script>
    const vm = new Vue({
        el: '#app',
        data: {
            name: "陈翔",
            dog: "see"
        },
        filters: {
            myFilter(val) {
                // 强调 过滤器中一定要有返回值   val是 | 前面的值
                let tempChar = val.charAt(0).toUpperCase();
                return val.replace(val.charAt(0), tempChar) + 'abc'
            }
        },
        methods: {}
    });
</script>
</html>

****************************************************************************************************************************************************************************

65、全局过滤器filter
【1】一般都是用全局过滤器
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>主页</title>
</head>
<body>
<div id="app">
    <p>{{dog | myFilter}}</p>
</div>
</body>
<link rel="stylesheet" href="./src/lib/bootstrap.css">
<!--1.导入vue.js-->
<script src="./src/lib/vue.js"></script>
<!--2.创建vue实例-->
<script>
    // 这里!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    Vue.filter('myFilter', (str) => {
        // 强调 过滤器中一定要有返回值   val是 | 前面的值
        let tempChar = str.charAt(0).toUpperCase();
        return str.replace(str.charAt(0), tempChar) + 'abc'
    })
    const vm = new Vue({
        el: '#app',
        data: {
            name: "陈翔",
            dog: "see"
        }
    });
</script>
</html>

****************************************************************************************************************************************************************************

67、过滤器的其他用法
【1】可以调用多个过滤器。{{name | myFilter1 | myFilter2 | myFilter3}}
【2】调用过滤器也可以传参{{name | myFilter1(arg1,arg2)}}。过滤器本质就是函数

****************************************************************************************************************************************************************************

68、vue侦听器watch
【1】监视数据变化的。监听谁,就把谁当做watch里的方法名。
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>主页</title>
</head>
<body>
<div id="app">
    <input type="text" v-model="name"/>
</div>
</body>
<!--1.导入vue.js-->
<script src="./src/lib/vue.js"></script>
<!--2.创建vue实例-->
<script>
    const vm = new Vue({
        el: '#app',
        data: {
            name: "陈翔",
            age: 21
        },
        watch: {
            name(newV, oldV) { // 方法名和属性名保持一致需要
                console.log(newV, oldV)
            }
        }
    });
</script>
</html>

****************************************************************************************************************************************************************************

69、判断用户名是否被占用
【1】主要是属性变化时,和当前值进行比较。
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>主页</title>
</head>
<body>
<div id="app">
    <input type="text" v-model="name"/>
</div>
</body>
<!--1.导入vue.js-->
<script src="./src/lib/vue.js"></script>
<!--2.创建vue实例-->
<script>
    const vm = new Vue({
        el: '#app',
        data: {
            name: "陈翔",
            age: 21
        },
        watch: {
            name(newV, oldV) { // 方法名和属性名保持一致需要
                console.log(newV, oldV)
                let list = ['陈翔', '球球', '蘑菇头'];
                list = list.filter(item => item === newV)
                if (list.length > 0) {
                    console.log("用户名已存在");
                }
            }
        }
    });
</script>
</html>

****************************************************************************************************************************************************************************

70、侦听器immediate选项
【1】函数形式的侦听器,刚进来不会被触发????
【2】对象格式的侦听器。可以通过immediate自动触发一次。
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>主页</title>
</head>
<body>
<div id="app">
    <input type="text" v-model="name"/>
</div>
</body>
<!--1.导入vue.js-->
<script src="./src/lib/vue.js"></script>
<!--2.创建vue实例-->
<script>
    const vm = new Vue({
        el: '#app',
        data: {
            name: "陈翔",
            age: 21
        },
        watch: {
            name: { // 对象形式的
                handler(newV, oldV) {
                    console.log(newV, oldV)
                    let list = ['陈翔', '球球', '蘑菇头'];
                    list = list.filter(item => item === newV)
                    if (list.length > 0) {
                        console.log("用户名已存在");
                    }
                },
                immediate: true
            }
        }
    });
</script>
</html>

****************************************************************************************************************************************************************************

71、侦听器 deep
【1】如果监听的是对象,对象里面的属性不会被监听。可以通过deep选项,让监听器深度监听。
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>主页</title>
</head>
<body>
<div id="app">
    <input type="text" v-model="info.name"/>
</div>
</body>
<!--1.导入vue.js-->
<script src="./src/lib/vue.js"></script>
<!--2.创建vue实例-->
<script>
    const vm = new Vue({
        el: '#app',
        data: {
            info: {
                name: "陈翔"
            }
        },
        watch: {
            info: { // 对象形式的
                handler(newV, oldV) {
                    console.log(newV, oldV)
                    let list = ['陈翔', '球球', '蘑菇头'];
                    list = list.filter(item => item === newV.name)
                    if (list.length > 0) {
                        console.log("用户名已存在");
                    }
                },
                immediate: true,
                deep: true // 深度监视
            }
        }
    });
</script>
</html>

****************************************************************************************************************************************************************************

73、计算属性!!!!
【1】很重要。通过一些列运算之后,得到的一个属性值。这个属性值可以在模板或者methods中使用。
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>主页</title>
</head>
<body>
<div id="app">
    R: <input type="text" v-model="r"/><br/>
    G: <input type="text" v-model="g"/><br/>
    B: <input type="text" v-model="b"/>
    <hr/>
    <div :style="{backgroundColor:`rgb(${r},${g},${b})`}">
        {{`rgb(${r},${g},${b})`}}
    </div>
    <button @click="">随机获取颜色</button>
</div>
</body>
<link rel="stylesheet" href="./src/lib/bootstrap.css">
<!--1.导入vue.js-->
<script src="./src/lib/vue.js"></script>
<!--2.创建vue实例-->
<script>
    const vm = new Vue({
        el: '#app',
        data: {
            r: 0,
            g: 0,
            b: 0
        }
    });
</script>
</html>
【2】每次动态拼接值,很麻烦,怎么解决呢???

****************************************************************************************************************************************************************************

74、计算属性的使用
【1】定义的时候是普通方法。使用的时候当成普通属性使用。实现代码复用。自动求值(只要依赖的数据源变化,计算属性会自动重新求值)
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>主页</title>
</head>
<body>
<div id="app">
    R: <input type="text" v-model="r"/><br/>
    G: <input type="text" v-model="g"/><br/>
    B: <input type="text" v-model="b"/>
    <hr/>
    <div :style="{backgroundColor:rgb}">
        {{rgb}}   <!--这里是当做属性用-->
    </div>
</div>
</body>
<link rel="stylesheet" href="./src/lib/bootstrap.css">
<!--1.导入vue.js-->
<script src="./src/lib/vue.js"></script>
<!--2.创建vue实例-->
<script>
    const vm = new Vue({
        el: '#app',
        data: {
            r: 0,
            g: 0,
            b: 0
        },
        // 计算属性,定义到这个节点下面
        computed: {
            rgb() { // 返回的是rgb属性
                return `rgb(${this.r},${this.g},${this.b})` // es6语法
            }
        }
    });
</script>
</html>

****************************************************************************************************************************************************************************

75、axios使用
【1】专注于网络请求的库。无论vue还是react都是用axios发送网络请求。
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>主页</title>
</head>
<body>
<div id="app">
    <button @click="myRequest">发送axios请求</button>
</div>
</body>
<link rel="stylesheet" href="./src/lib/bootstrap.css">
<!--1.导入vue.js-->
<script src="./src/lib/vue.js"></script>
<script src="./src/lib/axios.js"></script>
<!--2.创建vue实例-->
<script>
    const vm = new Vue({
        el: '#app',
        data: {
            name: "陈翔"
        },
        methods: {
            myRequest() {
                const result = axios({
                    method: "POST",
                    url: "http://localhost:8002/user/login",
                    // URL中查询参数
                    params: {},
                    // 请求体
                    data: {
                        "name": "admin",
                        "password": "123456"
                    }
                })
                result.then(res => {
                    console.log(res);
                })
            }
        }
    });
</script>
</html>

****************************************************************************************************************************************************************************

76、结合async与await调用
【1】只要某个方法的返回值是Promise实例,则前面可以添加async...await。这时候就不用使用then了
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>主页</title>
</head>
<body>
<div id="app">
    <button @click="myRequest">发送axios请求</button>
</div>
</body>
<link rel="stylesheet" href="./src/lib/bootstrap.css">
<!--1.导入vue.js-->
<script src="./src/lib/vue.js"></script>
<script src="./src/lib/axios.js"></script>
<!--2.创建vue实例-->
<script>
    const vm = new Vue({
        el: '#app',
        data: {
            name: "陈翔"
        },
        methods: {
            async myRequest() {
                const result = await axios({
                    method: "POST",
                    url: "http://localhost:8002/user/login",
                    // 请求体
                    data: {
                        "name": "admin",
                        "password": "123456"
                    }
                })
                console.log(result)
            }
        }
    });
</script>
</html>
【2】解构与赋值
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>主页</title>
</head>
<body>
<div id="app">
    <button @click="myRequest">发送axios请求</button>
</div>
</body>
<link rel="stylesheet" href="./src/lib/bootstrap.css">
<!--1.导入vue.js-->
<script src="./src/lib/vue.js"></script>
<script src="./src/lib/axios.js"></script>
<!--2.创建vue实例-->
<script>
    const vm = new Vue({
        el: '#app',
        data: {
            name: "陈翔"
        },
        methods: {
            async myRequest() {
                const {data} = await axios({  //!!!!!!!!!!!!!!!!!!!!!!!!!!!
                    method: "POST",
                    url: "http://localhost:8002/user/login",
                    // 请求体
                    data: {
                        "name": "admin",
                        "password": "123456"
                    }
                })
                console.log(data)
            }
        }
    });
</script>
</html>

****************************************************************************************************************************************************************************

78、axios.get与axios.post
【1】主流post请求使用
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>主页</title>
</head>
<body>
<div id="app">
    <button @click="myRequest">发送axios请求</button>
</div>
</body>
<link rel="stylesheet" href="./src/lib/bootstrap.css">
<!--1.导入vue.js-->
<script src="./src/lib/vue.js"></script>
<script src="./src/lib/axios.js"></script>
<!--2.创建vue实例-->
<script>
    const vm = new Vue({
        el: '#app',
        data: {
            name: "陈翔"
        },
        methods: {
            myRequest() {
                axios.post("http://localhost:8002/user/login", {
                    name: "admin",
                    password: "123456"
                }).then(res => {
                    console.log(res.data);
                })
            }
        }
    });
</script>
</html>

****************************************************************************************************************************************************************************

79、vue-cli概述与安装
【1】单页面应用程序。麻雀虽小,五脏俱全。
【2】vue-cli是vue.js开发的标准工具。简化了程序员基于webpack创建工程化Vue项目的过程。程序员只需要专注写应用,而不必花几天去纠结webpack配置。
【3】安装和使用
npm i -g @vue/cli -force
**************************************************
vue -V 查看是否安装成功
**************************************************
vue create day_app
**************************************************
Manually select features选择这个
**************************************************
CSS Pre-processors通过空格选中
**************************************************
2.x版本先选择
**************************************************
less选择后回车
**************************************************
In dedicated config files选择
**************************************************
y选择
**************************************************
HIT-2023

****************************************************************************************************************************************************************************

81、vue-cli创建项目的启动效果
【1】npm run serve
【2】访问localhost:8080

****************************************************************************************************************************************************************************

82、项目目录概述
【1】node_modules 第三方包。src源代码目录。
【2】assets静态资源。components 组件的集合,程序员封装的可复用的组件都要放在这下面。
【3】main.js是项目的入口文件。相当于index.js文件
【4】App.vue是项目的根组件

****************************************************************************************************************************************************************************

84、vue项目的运行过程
【1】很单纯,就是通过main.js把App.vue渲染到index.html的指定区域中。
*****************************************************
import Vue from 'vue'
// 导入App.vue组件,将来要把App.vue中的结构渲染到HTML页面中
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
    // 通过render函数指定组件,渲染到HTML页面中
    render: h => h(App),
}).$mount('#app')
【2】$mount('#app') 就相当于 el:"#app"

****************************************************************************************************************************************************************************

86、vue组件的三个组成部分
【1】组件化就是对UI结构的封装与复用。
【2】组件的后缀名都是.vue。App组件。
【3】template 组件的模板结构。script 组件的js行为。style组件的样式。
<!--第1部分-->
<template>
    <h1 class="box">App.vue组件---{{name}}</h1>
</template>

<!--第2部分-->
<script>
    export default {
        data() { // 组件里的data不能指向对象,必须要写成方法
            return {
                name: '陈翔',
            }
        },
    }
</script>

<!--第3部分-->
<style>
    .box {
        background-color: pink;
    }
</style>

****************************************************************************************************************************************************************************

87、vue组件中定义方法
【1】属性只能以方法的形式定义。
<!--第1部分-->
<template>
    <div>
        <h1 class="box">App.vue组件---{{name}}</h1>
        <button @click="changeName">修改姓名</button>
    </div>
</template>

<!--第2部分-->
<script>
    export default {
        data() { // 组件里的data不能指向对象,必须要写成方法
            return {
                name: '陈翔',
            }
        },
        methods: {
            changeName() {
                this.name = "球球"
            }
        },
        watch: {},
        computed: {},
        filters: {}
    }
</script>

<!--第3部分-->
<style>
    .box {
        background-color: pink;
    }
</style>

****************************************************************************************************************************************************************************

88、启用less语法以及唯一根节点
【1】template下面只能放一个唯一的div,外面必须有个最大的div
【2】<style>
<!--第1部分-->
<template>
    <div>
        <h1>App.vue组件---{{name}}</h1>
        <button @click="changeName">修改姓名</button>
    </div>
</template>

<!--第2部分-->
<script>
    export default {
        data() { // 组件里的data不能指向对象,必须要写成方法
            return {
                name: '陈翔',
            }
        },
        methods: {
            changeName() {
                this.name = "球球"
            }
        },
        watch: {},
        computed: {},
        filters: {}
    }
</script>

<!--第3部分!!!!!!!!!!!!!!!!!!!!!!-->
<style>
    .box {
        background-color: pink;

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

****************************************************************************************************************************************************************************

90、使用组件的三个步骤
【1】父子关系。组件封装好之后是彼此独立的。
【2】当App.vue使用了Left.vue与Right.vue之后,才形成了父子关系。
【3】分为下面三个步骤使用。
步骤1:import语法导入需要的组件
import Left from "@/components/Left";
*******************************************************************
步骤2:使用components节点注册组件
  components: {
            Left,
            Right
        },
        data() { // 组件里的data不能指向对象,必须要写成方法
            return {
                name: '陈翔',
            }
        },
*******************************************************************
步骤3:以标签的形式使用注册后的组件
<Left></Left>
<Right></Right>
*******************************************************************
<!--第1部分-->
<template>
    <div>
        <h1>App.vue组件---{{name}}</h1>
        <button @click="changeName">修改姓名</button>
        <Left></Left>
        <Right></Right>
    </div>
</template>

<!--第2部分-->
<script>
    // 导入需要使用的组件
    import Left from "@/components/Left";
    import Right from "@/components/Right";

    export default {
        components: {
            Left,
            Right
        },
        data() { // 组件里的data不能指向对象,必须要写成方法
            return {
                name: '陈翔',
            }
        },
        methods: {
            changeName() {
                this.name = "球球"
            }
        },
        watch: {},
        computed: {},
        filters: {}
    }
</script>

<!--第3部分-->
<style>
    .box {
        background-color: pink;

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

****************************************************************************************************************************************************************************

93、Vue.components的使用
【1】通过components注册的是私有子组件。如果在A的components注册了F,F只能在A中使用,不能用于其他组件。如果其他组件要使用,F也要在对应组件注册。
【2】如果某个组件被频繁的使用,则该组件可以注册为全局组件。在main.js注册为全局的组件。
// 导入App.vue组件,将来要把App.vue中的结构渲染到HTML页面中
import App from './App.vue'
import Vue from 'vue'
import Count from "@/components/Count"; // !!!!!!!!!!!!

Vue.config.productionTip = false
Vue.component("Count", Count) // !!!!!!!!!!!!

new Vue({
    // 通过render函数指定组件,渲染到HTML页面中
    render: h => h(App),
}).$mount('#app')

****************************************************************************************************************************************************************************

95、组件里的props
【1】如果两个组件都分别使用了Count.vue组件,如何给Count指定属性赋初始值。props就可以解决这个问题,极大的提高了组件的复用性。
<template>
    <div>
        我是Count.vue组件
        <p>count的值是{{init}}</p>
        <button @click="init=init+1">点击+1</button>
    </div>
</template>

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

<style scoped>
    .box {
        background-color: gray;
    }
</style>
***************************************************************************
<template>
    <div>
        我是Left.vue组件
        <Count :init="1"></Count>
    </div>
</template>

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

<style scoped>
    .box {
        background-color: yellow;
    }
</style>
*****************************************************************************
<template>
    <div>
        我是Right.vue组件
        <Count :init="20"></Count>
    </div>
</template>

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

<style scoped>
    .box {
        background-color: green;
    }
</style>

****************************************************************************************************************************************************************************

97、props是只读的。
【1】比如直接修改init在控制台console中会报错Avoid mutating a prop directly since the value will be overwritten whenever
the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "init"
【2】说明props是只读的。所以初始值赋给count,然后count=count+1
<template>
    <div>
        我是Count.vue组件
        <p>count的值是{{count}}</p>
        <button @click="count=count+1">点击+1</button>
    </div>
</template>

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

<style scoped>
    .box {
        background-color: gray;
    }
</style>

****************************************************************************************************************************************************************************

98、props给默认值
【1】如果用户不传给默认值0。
   props: {
            init: {
                default: 0
            }
    },
    data() {
        return {
            count: this.init
        }
    }
【2】type值类型,这样直接传就行了,不用额外加:init就能接收到数值类型。
  props: {
            init: {
                default: 0,
                type: Number // !!!!!!!!! String Boolean
            }
        }

****************************************************************************************************************************************************************************

100、props-required必填项
【1】不传就会报错!!!!!!!!
  props: {
            init: {
                default: 0,
                type: Number,
                required: true
            }
        }
**************************************************************************
vue.runtime.esm.js?c320:4605 [Vue warn]: Missing required prop: "init"

****************************************************************************************************************************************************************************

101、组件间的样式冲突
【1】就是父组件的样式,不应该覆盖子组件的样式。scoped
<style scoped>
    .box {
        background-color: yellow;
    }
</style>

****************************************************************************************************************************************************************************

102、样式穿透
【1】使用第三方组件库的时候,如果需要修改组件默认样式,需要用到/deep/ 来修改

****************************************************************************************************************************************************************************

103、vue组件的实例对象
【1】<Count :init="0"></Count>用标签的形式使用组件,该组件就被实例化了。Count使用的时候就被实例化了。

****************************************************************************************************************************************************************************

104、生命周期
【1】一个组件(比如Count.vue)从创建-运行-销毁的整个阶段,强调的是时间段。
【2】创建阶段:beforeCreate、created、beforeMount、mounted
【3】组件运行阶段:beforeUpdate、updated
【4】组件销毁阶段beforeDestroy、destroyed

****************************************************************************************************************************************************************************

105、组件创建
【1】main.js-App.vue-Left.vue/Right.vue-Count.vue
【2】注册组件Test到App中使用。
<template>
    <div>
        <h3>Test.vue组件</h3>
    </div>
</template>

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

<style scoped>
    .box {
        background-color: pink;
        height: 200px;
    }
</style>

****************************************************************************************************************************************************************************

106、beforeCreated、created
【1】beforeCreated这个函数不重要,因为很多东西还做不了。下面做了演示。
<template>
    <div>
        <h3>Test.vue组件</h3>
    </div>
</template>

<script>
    export default {
        name: "Test",
        props: ['info'],
        data() {
            return {
                name: "陈翔"
            }
        },
        methods: {
            show() {
                console.log("Test组件的show方法")
            }
        },
        beforeCreate() {
            //console.log(this.info);
            //console.log(this.name);
            this.show();
        }
    }
</script>

<style scoped>
    .box {
        background-color: pink;
        height: 200px;
    }
</style>
【2】created用的多,props data methods都初始化完毕了。这个函数很重要,这个阶段可以发起axios请求去拿数据。

****************************************************************************************************************************************************************************

107、beforeMount、mounted
【1】created阶段不能操作dom。因为一些模板结构还没有生成。
【2】beforeMount只是在内存中有结构,页面上还没有dom结构。这个函数没有什么意义
【3】mounted这个阶段是真正的dom渲染阶段。所以ed的用的还是很多的。这个函数也非常重要!!!!!!!!!!!
  mounted() {
            let div = document.getElementsByClassName('box');
            console.log(div);
        }

****************************************************************************************************************************************************************************

108、组件运行阶段生命周期
【1】beforeUpdate、updated
【2】数据改变时,才会触发beforeUpdate。 <button @click="change">追加后缀+</button>。dom结构还没重新渲染。
<template>
    <div>
        <h3>Test.vue组件-{{name}}</h3>
        <button @click="change">追加后缀+</button>
    </div>
</template>

<script>
    export default {
        name: "Test",
        props: ['info'],
        data() {
            return {
                name: "陈翔"
            }
        },
        methods: {
            show() {
                console.log("Test组件的show方法")
            },
            change() {
                this.name = this.name + "六点半";
            }
        },
        beforeCreate() {
            //console.log(this.info);
            //console.log(this.name);
            // this.show();
        },
        created() {
            console.log(this.info);
            console.log(this.name);
            this.show();
        },
        mounted() {
            let div = document.getElementsByClassName('box');
            console.log(div);
        },
        beforeUpdate() {
            console.log("beforeUpdate")
        }
    }
</script>

<style scoped>
    .box {
        background-color: pink;
        height: 200px;
    }
</style>
【3】updated代表dom已经重新渲染完毕了。

****************************************************************************************************************************************************************************

109、销毁阶段的生命周期函数
【1】这个阶段极少用。了解下就行了。
<!--第1部分-->
<template>
    <div>
        <h1>App.vue组件---{{name}}</h1>
        <button @click="changeName">修改姓名</button>
        <Left></Left>
        <Right></Right>
        <Test info="您好" v-if="flag"></Test>
        <button @click="flag=!flag">换下Test.vue的展示</button>
    </div>
</template>

<!--第2部分-->
<script>
    // 导入需要使用的组件
    import Left from "@/components/Left";
    import Right from "@/components/Right";
    import Test from "@/components/Test";

    export default {
        components: {
            Left,
            Right,
            Test
        },
        data() { // 组件里的data不能指向对象,必须要写成方法
            return {
                name: '陈翔',
                flag: true
            }
        },
        methods: {
            changeName() {
                this.name = "球球"
            }
        },
        watch: {},
        computed: {},
        filters: {}
    }
</script>

<!--第3部分-->
<style>
    .box {
        background-color: pink;
        border: 3px solid black;

        h1 {
            color: red;
        }
    }
</style>
****************************************************************
<template>
    <div>
        <h3>Test.vue组件-{{name}}</h3>
        <button @click="change">追加后缀+</button>
    </div>
</template>

<script>
    export default {
        name: "Test",
        props: ['info'],
        data() {
            return {
                name: "陈翔"
            }
        },
        methods: {
            show() {
                console.log("Test组件的show方法")
            },
            change() {
                this.name = this.name + "六点半";
            }
        },
        beforeCreate() {
            //console.log(this.info);
            //console.log(this.name);
            // this.show();
        },
        created() {
            console.log(this.info);
            console.log(this.name);
            this.show();
        },
        mounted() {
            let div = document.getElementsByClassName('box');
            console.log(div);
        },
        beforeUpdate() {
            console.log("beforeUpdate")
        },
        destroyed() {
            console.log("Test.vue组件被销毁了");
        }
    }
</script>

<style scoped>
    .box {
        background-color: pink;
        height: 200px;
    }
</style>
【2】重要的函数都是以ed结尾的重要!!!

****************************************************************************************************************************************************************************

110、组件之间的数据共享
【1】组件之间最常见的关系是父子关系+兄弟关系。
【2】父->子传数据。App.vue 把  name: '陈翔'  传给Left.vue使用
  <Left :name="name" :dog="dog"></Left>
  **************************************************************************
   props: ['name', 'dog']
**************************************************************************
父组件传过来的人名:{{name}}
父组件传过来的狗子:姓名{{dog.name}} 年龄:{{dog.age}}

****************************************************************************************************************************************************************************

111、父向子传值-演示
【1】父组件App.vue
<!--第1部分-->
<template>
    <div>
        <h1>App.vue组件</h1>
        <Left :group="group" :userInfo="userInfo"></Left>
    </div>
</template>

<!--第2部分-->
<script>
    // 导入需要使用的组件
    import Left from "@/components/Left";

    export default {
        components: {
            Left,
        },
        data() { // 组件里的data不能指向对象,必须要写成方法
            return {
                group: '万达',
                userInfo: {
                    name: "王思聪",
                    age: 18
                }
            }
        },
    }
</script>

<!--第3部分-->
<style>
    .box {
        background-color: pink;
        border: 3px solid black;

        h1 {
            color: red;
        }
    }
</style>
【2】子组件Left.vue
<template>
    <div>
        我是Left.vue组件
        父组件传过来的group值是{{group}}
        父组件传过来的userInfo值是{{userInfo}}
    </div>
</template>

<script>
    export default {
        name: "Left",
        props: ['group', 'userInfo']
    }
</script>

<style scoped>
    .box {
        background-color: yellow;
    }
</style>
【3】实际开发中不要修改父组件传给子组件的值。属性需要子组件中用props:['name','list']声明。

****************************************************************************************************************************************************************************

113、子向父传值
【2】子-父组件。子组件向父组件传值,需要使用自定义事件。
<template>
    <div>
        我是Left.vue子组件{{count}}<br/>
        <button @click="add">点击+1</button>
    </div>
</template>

<script>
    export default {
        name: "Left",
        data() {
            return {
                count: 0
            }
        },
        methods: {
            add() {
                this.count = this.count + 1
                // 自定义事件 传值给父组件
                this.$emit('giveValueToFather', this.count) // !!!!!!!!!!!
            }
        }
    }
</script>

<style scoped>
    .box {
        background-color: yellow;
    }
</style>
【3】父组件接收
<!--第1部分-->
<template>
    <div>
        <h1>App.vue父组件---{{countFromSon}}</h1>
        <Left @giveValueToFather="fatherGetMethod"></Left>  <!--!!!!!!!!!!!!!!!!!!!!-->
    </div>
</template>

<!--第2部分-->
<script>
    // 导入需要使用的组件
    import Left from "@/components/Left";

    export default {
        components: {
            Left,
        },
        data() {
            return {
                // 定义从子组件传值的属性
                countFromSon: 0
            }
        },
        methods: {
            fatherGetMethod(newVal) { // !!!!!!!!!!!!!!!!!!!!!!
                this.countFromSon = newVal;
            }
        }
    }
</script>

<!--第3部分-->
<style>
    .box {
        background-color: pink;
        border: 3px solid black;

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

****************************************************************************************************************************************************************************

114、兄弟组件之间的数据共享
【1】共享方案是EventBus。eventBus.js
import Vue from 'vue'

export default new Vue()
【2】 Left.vue
<template>
    <div class="box">
        我是Left.vue子组件(兄弟A)<br/>
        <button @click="sendMsg">发送数据</button>
    </div>
</template>

<script>

    import eventBus from "@/components/eventBus"; // !!!!!!!!!!!

    export default {
        name: "Left",
        data() {
            return {
                msg: '黑云压城城欲摧,甲光向日金鳞开'
            }
        },
        methods: {
            sendMsg() {
                // 通过eventBus发送数据
                eventBus.$emit("sendMsgToBrotherRight", this.msg)// !!!!!!!!!!!
            }
        }
    }
</script>

<style scoped>
    .box {
        background-color: yellow;
    }
</style>
【3】Right.vue
<template>
    <div class="box">
        我是Right.vue子组件(兄弟B)---{{msgFromBrotherLeft}}<br/>
    </div>
</template>

<script>
    import eventBus from "@/components/eventBus";

    export default {
        name: "Right",
        data() {
            return {
                msgFromBrotherLeft: ''
            }
        },
        created() {
            eventBus.$on('sendMsgToBrotherRight', getVal => {   // !!!!!!!!!!!
                this.msgFromBrotherLeft = getVal
            })
        }
    }
</script>

<style scoped>
    .box {
        background-color: deepskyblue;
    }
</style>
【4】其实这个也可以用于父子传,卧槽!!!!

****************************************************************************************************************************************************************************

117、组件之间的数据共享
【1】父-子传值:自定义属性。父组件绑定属性。子组件生命props接收,这种最简单。
【2】子-父传值:自定义事件。子组件定义属性,子组件this.$emit('giveValueToFather',this.属性)。父组件使用@giveValueToFather="getNewVal" 来更新数据到父组件属性
【3】兄弟组件之间的数据传递:eventBus.js 。  eventBus.$emit("sendMsgToBrotherRight", this.msg)。
***************************************************************************
 eventBus.$on('sendMsgToBrotherRight', getVal => {
                this.msgFromBrotherLeft = getVal
            })

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JeeSite框架安装部署

下载JeeSite框架。 依次执行两个sql文件。 如果是mysql8.0&#xff0c;则create_user.sql需要改成下面的内容&#xff1a; -- 打开 my.ini 给 [mysqld] 增加如下配置&#xff1a; -- sql_modeONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREAT…

YOLOv8核心原理深度解析

YOLOv8源码地址: https://github.com/ultralytics/ultralytics 一、简介: 根据官方描述,Yolov8是一个SOTA模型,它建立在Yolo系列历史版本的基础上,并引入了新的功能和改进点,以进一步提升性能和灵活性,使其成为实现目标检测、图像分割、姿态估计等任务的最佳选择。其具体…

代码随想录——双指针与滑动窗口(四)

一.1423. 可获得的最大点数 题目详情 解题思路 这里我们每次只能取最左或最右边的卡牌,第一反应其实是使用双指针&#xff0c;通过局部贪心来解决&#xff0c;但是如果两边相等的话用局部贪心无法来判断到底取哪一边&#xff0c;那我们不妨换一个思路&#xff1a; 我们首先任…

DICOM 测试工具

一个DICOM测试工具。 引用了 fo-dicom 。fo-dicom 算是比较好用的&#xff0c;我的另外一个项目也是用了它。 using System; using System.Collections.Generic; using System.Data; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; …

Go语言map

map 概念 在Go语言中&#xff0c;map 是一种内建的数据结构&#xff0c;它提供了一种关联式的存储机制&#xff0c;允许你以键值对的形式存储数据。每个键都是唯一的&#xff0c;并且与一个值相关联。你可以通过键来查找、添加、更新和删除值&#xff0c;这类似于其他编程语言…

Spring Boot的热部署工具“AND”Swagger测试工具

Spring Boot的热部署&Swagger测试页面的使用 热部署指的是在项目无需重启的情况下&#xff0c;只需要刷新页面&#xff0c;即可获得已经修改的样式或功能。要注意该工具一般用于开发环境&#xff0c;在生产环境中最好不要添加这个工具。 对于无需重启便可刷新这么方便的工…

小剧场短剧影视小程序源码_后端PHP

项目运行截图 源码贡献 https://githubs.xyz/boot?app42 部署说明 linux/win任选 PHP版本&#xff1a;7.3/7.2&#xff08;测试时我用的7.2要安装sg扩展 &#xff09; 批量替换域名http://video.owoii.com更换为你的 批量替换域名http://120.79.77.163:1更换为你的 这两个…

交通运输智慧监管平台---强化物流安全与效率的新举措

一、建设背景 随着社会对于交通安全和环境保护的要求不断提高&#xff0c;对卡车运输的监管和合规性要求也逐渐加强。为了满足快速发展的物流需求&#xff0c;提高供应链协同和可追溯性、解决安全问题、提高运输效率和降低成本&#xff0c;我们利用现代技术和信息化手段着力建设…

Spark SQL编程初级实践

参考链接 Spark编程: Spark SQL基本操作 2020.11.01_df.agg("age"->"avg")-CSDN博客 RDD编程初级实践-CSDN博客 Spark和Hadoop的安装-CSDN博客 1. Spark SQL基本操作 { "id":1 , "name":" Ella" , "age":…

数字电路-5路呼叫显示和8路抢答器

本内容涉及两个电路&#xff0c;分别为5路呼叫显示电路和8路抢答器电路&#xff0c;包含Multisim仿真原文件&#xff0c;为掌握FPGA做个铺垫。紫色文字是超链接&#xff0c;点击自动跳转至相关博文。持续更新&#xff0c;原创不易&#xff01; 目录&#xff1a; 一、5路呼叫显…

每日OJ题_DFS爆搜深搜回溯剪枝②_力扣526. 优美的排列

目录 力扣526. 优美的排列 解析代码 力扣526. 优美的排列 526. 优美的排列 难度 中等 假设有从 1 到 n 的 n 个整数。用这些整数构造一个数组 perm&#xff08;下标从 1 开始&#xff09;&#xff0c;只要满足下述条件 之一 &#xff0c;该数组就是一个 优美的排列 &#…

nginx缓存清理

背景 昨天打开我的gpt镜像网站&#xff0c;意外发现静态图片资源全都无法获取了 CoCo-AI 一番排查下来&#xff0c;发现是引用的cdn链接失效了 且cdn源是属于七牛云的&#xff0c;且不再维护&#xff0c;于是果断切换到cloudflare export function getEmojiUrl(unified: str…

JavaScript中的Object方法、Array方法、String方法

个人主页&#xff1a;学习前端的小z 个人专栏&#xff1a;JavaScript 精粹 本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结&#xff0c;欢迎大家在评论区交流讨论&#xff01; 文章目录 &#x1f525;Object方法&#x1f31e;1 Object.is()&#x1f31e;2 Object.…

区块链 | 由外部实体导致的 NFT 安全问题

&#x1f98a;原文&#xff1a; Understanding Security Issues in the NFT Ecosystem &#x1f98a;警告&#xff1a; 本文只记录了原文的第 6 节。 1 问题描述 NFT 所指向的数字资产&#xff08;图片、视频等&#xff09;必须是可以访问的&#xff0c;这样 NFT 才具有意义…

iA Writer for Mac:简洁强大的写作软件

在追求高效写作的今天&#xff0c;iA Writer for Mac凭借其简洁而强大的功能&#xff0c;成为了许多作家、记者和学生的首选工具。这款专为Mac用户打造的写作软件&#xff0c;以其独特的设计理念和实用功能&#xff0c;助你轻松打造高质量的文章。 iA Writer for Mac v7.1.2中文…

数据挖掘之基于Lightgbm等多模型消融实验的信用欺诈检测实现

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景 在当前的金融环境中&#xff0c;信用欺诈行为日益增多&#xff0c;给金融机构和消费者带来了巨大的损…

ThingsBoard PE专业版解决方案技术文档——温度湿度

1、项目总览 2、设备接入 3、设备告警 3.1 高温告警 创建一个Flag作为标杆&#xff0c;作为开启告警的开关。 3.2 低湿度告警 创建一个Flag作为标杆&#xff0c;作为开启告警的开关。 4、部件仪表 4.1 Entities table 部件预览&#xff1a; 标题样式&#xff1a; {"…

nuxt3项目服务端bulid后在本地浏览的3种方式(nuxi preview、Node.js Server、PM2)

你也许会问有了开发调试本地浏览&#xff0c;为什么还要服务端构建之后在本地浏览&#xff1f; 举个简单例子 在 Nuxt 3 服务端打包中&#xff0c;由于运行环境不同&#xff0c;无法直接访问 process 对象。服务端打包通常是在 Node.js 环境中进行的&#xff0c;而 process 对象…

Linux 手动部署JDK21 环境

1、下载包&#xff08;我下载的是tar) https://www.oracle.com/cn/java/technologies/downloads/#java21 完成后进行上传 2、检查已有JDK&#xff0c;并删除&#xff08;我原有是jdk8&#xff09; rpm -qa | grep -i java | xargs -n1 rpm -e --nodeps3、清理掉 profile中的j…

vue3 安装-使用之第一篇

首先需要node版本高于V16.14.1 安装 执行 npm create vitelatest 具体选择按照自己实际需要的来 Project name:项目名称 Select a framework:选择用哪种框架 &#xff08;我选择vue&#xff09; Select a variant: 选择用JS还是TS&#xff08;我选择JS&#xff09;找到项目&…
最新文章