赞
踩
感谢原创作者:SZnA1 为大家提供这么好的学习资源
vue 基本概念
作者: 尤雨溪
渐进式 的 自底向上增量开发的 mvvm框架
渐进式 可以和多种框架进行合并 vue是一个渐进式的框架(vue只会按照程序员的需要来进行功能的实现 不会影响到项目中没有用到vue框架的区域)只会做职责以内的事情
自底向上增量开发:先完成最基本的页面 然后再使用vue进行数据的绑定 一步步完成整个项目
- MVVM
-
- M model 模型----》就是存储变量数据的地方
- V view 视图----》页面 html所写的那些东西
- VM viewModel 视图模型----》就是页面与数据之前桥梁
helloword
1、获取vue库文件(使用npm(包管理工具)来进行获取)
(1)在你要写项目的文件夹 上打开cmd
(2)初始化 npm init -y
(3) 下载 npm install --save xxx (默认最新版 指定版本 npm install --save xxx@你的版本)
如果太慢 可以切换成淘宝镜像
安装:npm i -g cnpm --registry=https://registry.npm.taobao.org
(4)开始编写vue的helloword
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- <!-- 1引用vue -->
- <script src="./node_modules/vue/dist/vue.js"></script>
- </head>
- <body>
- <!--
- MVVM
-
- M model 模型----》就是存储变量数据的地方
- V view 视图----》页面 html所写的那些东西
- VM viewModel 视图模型----》就是页面与数据之前桥梁
-
-
- -->
-
- <!-- 2.创建 v层 -->
- <div id="demoDiv">
- <h1>{{text}}</h1>
- <h1>{{obj.name}}</h1>
- </div>
- <script>
- // 3。vm层创建(就是vue实例)
- new Vue({
- // 4.创建m层数据
- data:{
- text:"你好",
- num:18,
- bool:true,
- arr:[111,223,444,555,6,6,7,7],
- obj:{
- name:"xixi",
- age:18
- }
- },
- // 5.关联视图层
- el:"#demoDiv"
- })
-
- </script>
-
- </body>
- </html>
el:创建的vue实例
就是把模型数据插入到视图中
语法:
{{表达式}}
表达式: 通过计算返回结果的公式
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- <script src="node_modules/vue/dist/vue.js"> </script>
- </head>
- <body>
- <div id="demoDiv">
- <h1>{{}}中不建议复杂的内容</h1>
- {{num+demo}}
- <h1>{{bool?"你好":"你坏"}}</h1>
- <h1>{{text}}</h1>
- <h1>{{text.toUpperCase()}}</h1>
-
- </div>
- <script>
- new Vue({
- el:"#demoDiv",
- data:{
- num:2,
- demo:3,
- bool:false,
- text:"abcdefghijk"
- }
- })
-
- </script>
- </body>
- </html>
我们只需要告诉程序你要干什么 他就会自动完成
在js中我们使用的所有变量的插入页面的过程 就是命令式 我们需要指挥程序一步步干什么
传统的css就属于命令式渲染,效率较低
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- </head>
- <body>
- <h1 id="demoh"></h1>
- <script>
- let text="你好"
- document.getElementById("demoh").innerHTML=text
- </script>
- </body>
- </html>
数据驱动
vue就是一个js框架 作用就是把数据用更加简单的方式插入到页面中 vue可以根据数据的改变让页面也随之发生改变
指令
基本概念
在vue中带有v-前缀的html特殊属性
指令的作用:是给html添加特殊的功能
语法:写在html的开标签中 v-指令=“指令值”
v-model
作用: 给表单元素进行数据绑定的
语法:v-model=“变量”
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- <script src="node_modules/vue/dist/vue.js"> </script>
- </head>
- <body>
- <div id="demoDiv">
- <h1>v-model</h1>
- <!-- 1.v-model可以吧一个变量绑定到表单元素之上 当表单元素的值
- 改变了 那么这个变量也会随之改变
- v层视图层 改变了数据 m层模型层也随之改变了 (视图变 模型变) -->
-
- <input type="text" v-model="text"/>
- <!-- 模型变了视图也会随之发生改变 -->
- <em>{{text}}</em>
-
- <!--
- 双向绑定 就是 数据在模型中改变 视图也会改变 反之
- 视图变了 模型也会改变 -->
-
- </div>
- <script>
- new Vue({
- el:"#demoDiv",
- data:{
- text:"你好"
- }
- })
-
- </script>
- </body>
- </html>
双向绑定的原理
原理:数据劫持与发布者订阅者模式
数据劫持:数据拦截 vue中使用Object.defineProerty() 就是可以监听着我们data中的模型数据 当数据改变的时候 Object.defineProerty() 就会触发 模型改变 他会通知视图改变 视图改变 就会通知模型进行改变 会监听着改变 与修改。
发布者订阅者模式:就是一个一对多的关系 发布者变了 所有的订阅者都会随之发生改变
v-show
作用: 就是控制元素的显示和隐藏
语法:v-show=“布尔值” true显示 false隐藏
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- <script src="node_modules/vue/dist/vue.js"> </script>
- </head>
- <body>
- <div id="demoDiv">
- <h1>v-show</h1>
- <h1 v-show="bool">控制我的显示和隐藏</h1>
- </div>
- <script>
- new Vue({
- el:"#demoDiv",
- data:{
- bool:false
- }
- })
-
- </script>
- </body>
- </html>
v-on/@
作用:就是给dom元素绑定事件
语法: v-on:事件(不加on)=“函数” v-on:click=“fun()” v-on:change=“fun()”
简写语法: @事件=“函数”
函数写在那?
函数写在与el data 同级的位置 使用methods进行包裹
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- <script src="node_modules/vue/dist/vue.js"> </script>
- </head>
- <body>
- <div id="demoDiv">
- <h1>v-on</h1>
- <button v-on:click="fun()">点我打印内容</button>
- <button @click="funb()">简写</button>
-
- </div>
- <script>
- new Vue({
- el:"#demoDiv",
- data:{
-
- },
- methods:{
- fun(){
- console.log("你好")
- },
- funb(){
- console.error("你坏")
- }
- }
- })
-
- </script>
- </body>
- </html>
作用:遍历data中的数据
语法:v-for="(遍历的值,遍历的下标) in 要遍历的数据名字"
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- <script src="./node_modules/vue/dist/vue.js"></script>
- </head>
- <body>
- <div id="demoDiv">
- <h1>v-for</h1>
- <ul>
- <li v-for="(v,i) in arr">
- {{v}}------{{i}}
- </li>
- </ul>
-
- </div>
-
- <script>
- new Vue({
- el:"#demoDiv",
- data:{
- arr:["EZ","MF","NOC","VN"]
- },
- methods:{
-
- }
- })
-
-
- </script>
- </body>
- </html>
遍历复杂数据
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- <script src="./node_modules/vue/dist/vue.js"></script>
- </head>
- <body>
- <div id="demoDiv">
- <h1>v-for</h1>
- <ul>
- <li v-for="(v,i) in arr">
- {{v}}------{{i}}
- </li>
- </ul>
- <hr/>
-
- <table border="1">
- <tr v-for="(v,i) in obj">
- <td>{{v.name}}</td>
- <td>{{v.age}}</td>
-
- </tr>
- </table>
-
- </div>
-
- <script>
- new Vue({
- el:"#demoDiv",
- data:{
- arr:["EZ","MF","NOC","VN"],
- obj:[
- {name:"huanghuang",age:27},
- {name:"bilin",age:29},
- {name:"xixi",age:26}
- ]
- },
- methods:{
-
- }
- })
-
-
- </script>
- </body>
- </
作用: 给html的标签属性插入变量
语法: v-bind:html的属性=“变量” 简写 :html的属性=“变量”
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- <script src="./node_modules/vue/dist/vue.js"></script>
- </head>
- <body>
- <div id="demoDiv">
- <h1>v-bind</h1>
- <a v-bind:href="ahref">{{text}}</a>
- <a :href="ahref">{{text}}</a>
-
- </div>
-
- <script>
- new Vue({
- el:"#demoDiv",
- data:{
- text:"点我去百度",
- ahref:"http://www.baidu.com"
- },
- methods:{
-
- }
- })
-
-
- </script>
- </body>
- </html>
作用:判断dom是否加载
语法: v-if=“布尔值” true加载 false不加载
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- <script src="./node_modules/vue/dist/vue.js"></script>
- </head>
- <body>
- <div id="demoDiv">
- <h1>v-if</h1>
-
- <input type="checkbox" v-model="bool">
- <h1 v-if="bool">我是测试v-if的</h1>
- <h1 v-show="bool">我是测试v-show的</h1>
-
- </div>
-
- <script>
- new Vue({
- el:"#demoDiv",
- data:{
- bool:true
- },
- methods:{
-
- }
- })
-
-
- </script>
- </body>
- </html>
v-if与v-show的区别
v-if 是对dom元素进行添加和移除 v-if 在加载的时候对性能损耗低 v-if在元素频繁切换的时候性能损耗高
v-show 是对dom元素使用css进行显示和隐藏 v-show 在加载的时候对性能损耗高 v-if在元素频繁切换的时候性能损耗低
v-else
作用: v-if不符合的时候执行else
语法:必须配合v-if来进行时候用 不能单独使用
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- <script src="./node_modules/vue/dist/vue.js"></script>
- </head>
- <body>
- <div id="demoDiv">
- <h1>v-else</h1>
-
- <input type="checkbox" v-model="bool">
- <h1 v-if="bool">你好</h1>
- <h1 v-else>你坏</h1>
-
-
- </div>
-
- <script>
- new Vue({
- el:"#demoDiv",
- data:{
- bool:true
- },
- methods:{
-
- }
- })
-
-
-
-
- </script>
- </body>
- </html>
作用 可以对多个内容进行dom添加的判断
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- <script src="./node_modules/vue/dist/vue.js"></script>
- </head>
- <body>
- <div id="demoDiv">
- <h1 v-if="num==1">吃</h1>
- <h1 v-else-if="num==2">睡</h1>
- <h1 v-else-if="num==3">上厕所</h1>
- <h1 v-else-if="num==4">在睡</h1>
- <h1 v-else>什么也没有干</h1>
-
- </div>
-
- <script>
- new Vue({
- el:"#demoDiv",
- data:{
- num:8
- },
- methods:{
-
- }
- })
-
-
- </script>
- </body>
- </html>
作用:在网页中展示纯文本内容 同{{}}类似的功能
语法: v-text=“变量”
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- <script src="./node_modules/vue/dist/vue.js"></script>
- </head>
- <body>
- <div id="demoDiv">
- <h1>v-text</h1>
- <h1>{{demo}}</h1>
- <h1 v-text="demo"></h1>
-
- </div>
-
- <script>
- new Vue({
- el:"#demoDiv",
- data:{
- demo:"我是文本"
- },
- methods:{
-
- }
- })
-
-
- </script>
- </body>
- </html>
相同点: 都可以向页面中插入内容
不同点:{{}}模板插值的语法 而v-text是指令
v-text可以解决屏幕闪烁问题
屏幕闪烁
当用户网络很慢的时候 由于js没有加载 可能会导致页面出现{{}} 问题 然后js加载成功之后 {{}}消失变成正常的数据展示 可能会在成用户体验不好
解决:
1.使用v-text
2.使用v-cloak指令来解决 当前这个指令的作用是保持元素上直到关联vue实例之后 在进行编译
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- <script src="./node_modules/vue/dist/vue.js"></script>
- <style>
- [v-cloak]{
- display: none; //解决屏幕闪烁问题
- }
- </style>
- </head>
- <body>
- <div id="demoDiv" v-cloak>
- <h1>v-text</h1>
- <h1>{{demo}}</h1>
- <h1 v-text="demob"></h1>
-
- </div>
-
- <script>
- new Vue({
- el:"#demoDiv",
- data:{
- demo:"我是文本1",
- demob:"我是text"
- },
- methods:{
-
- }
- })
-
-
- </script>
- </body>
- </html>
作用:把字符串标签插入页面进行展示
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- <script src="./node_modules/vue/dist/vue.js"></script>
- </head>
- <body>
- <div id="demoDiv">
- <div>
- {{text}}
- </div>
- <div v-text="text">
-
- </div>
- <!-- 使用v-html -->
- <div v-html="text"></div>
-
- </div>
-
- <script>
- new Vue({
- el:"#demoDiv",
- data:{
- text:"<em>我是斜体</em>"
- },
- methods:{
-
- }
- })
-
-
- </script>
- </body>
- </html>
作用:一次性插值
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- <script src="./node_modules/vue/dist/vue.js"></script>
- </head>
- <body>
- <div id="demoDiv">
- <input type="text" v-model="text">
- <h1>{{text}}</h1>
- <h1 v-once>{{text}}</h1>
- <h1>{{text}}</h1>
-
- </div>
-
- <script>
- new Vue({
- el:"#demoDiv",
- data:{
- text:"你好么么哒"
- },
- methods:{
-
- }
- })
-
-
- </script>
- </body>
- </html>
watch监听
监听data中的数据,如果数据改变了,watch就会收到通知,调用一个函数。(我们就可以在这个函数中完成指定的逻辑)
语法:whtch写在与 el data methods同级
watch:{
要监听的数据名(新数据名,旧数据名){
函数(需要做的事情) }
}
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- <script src="./node_modules/vue/dist/vue.js"></script>
- </head>
- <body>
- <div id="demoDiv">
- <input type="text" v-model="inputval">
- </div>
- <script>
- new Vue({
- el:"#demoDiv",
- data:{
- inputval:""
- },
- methods:{
-
- },
- // 监听
- watch:{
- inputval(newval,oldval){
- console.log(newval+"----"+oldval)
- }
- }
- })
- </script>
- </body>
- </html>
首次加载不会触发
首次加载执行函数需通过其immediate 属性进行配置,默认为false
监听数组值变化需通过其deep属性进行配置,默认为false
- watch:{
- "aaa":{
- immediate:true, // 首次加载的时候执行函数
- deep:true, // 深入观察,监听数组值,对象属性值的变化
- handler:function(){
- }
- }
vue-cil脚手架
安装4x(脚手架版本)
1.必须有node
2.切换淘宝镜像 npm i -g cnpm --registry=https://registry.npm.taobao.org
3.全局下载脚手架 npm install -g @vue/cli (只需要下载一次)
4.查看版本 vue --version
5.创建项目
5.1 在项目所在路径打开cmd
5.2 在打开的cmd里输入 vue create 项目名 (选择第三个 手动选择)
6.启动项目
6.1 cmd里cd到项目所在路径
6.2 cmd里输入 npm run serve
第三方项目如何启动
1.查看项目文件夹中是否存在 node_modules?如果没有,在cmd里cd到当前项目路径 使用 npm install 重新下载依赖
2.在项目目录下找到package.json文件,在文件中查看scripts节点
所有的命令都需要使用npm run 配置项 (有一个特例 npm start)
下载空项目后需要做的
1.删除src下commponents文件夹的helloworld.vue文件
2.删除src下app.vue的内容
- <div id="app">
- <!-- 删除 -->
- <!-- <img alt="Vue logo" src="./assets/logo.png"> -->
- <!-- 删除 -->
- <!-- <HelloWorld msg="Welcome to Your Vue.js App"/> -->
- </div>
- </template>
-
- <script>
- // 删除
- // import HelloWorld from './components/HelloWorld.vue'
-
- export default {
- name: 'App',
- components: {
- // 删除
- // HelloWorld
- }
- }
- </script>
-
- <style>
- /* 删除 */
- /* #app {
- font-family: Avenir, Helvetica, Arial, sans-serif;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
- text-align: center;
- color: #2c3e50;
- margin-top: 60px;
- } */
- </style>
3.VSCode里下载插件:vetur
4.在src下的commponents中新建.vue文件
5.在app.vue中引用自己创建的.vue文件
- <template>
- <div id="app">
-
- <!-- 3.使用 -->
- <Home />
- </div>
- </template>
-
- <script>
- // 1.引用 建议首字母大写
- import Home from './components/home.vue'
-
- export default {
- name: 'App',
- components: {
- // 2.调用
- Home
- }
- }
- </script>
-
- <style>
- //写css样式
- </style>
.vue文件有三部分
- template部分 就是今后写html的地方
- <template>
- <div>
- 你好
- </div>
- </template>
-
- <script>
- script部分 JS的代码
- export default {
-
- }
- </script>
- //style部分 CSS
-
- <style>
-
- </style>
- <template>
- <div>
- <h1>{{text}}</h1>
- </div>
- </template>
-
- <script>
- export default {
- // 创建模型数据
- data(){
- return {
- text:"么么哒!!!!!"
- }
- }
- }
- </script>
-
- <style>
-
- </style>
vue组件的data为什么是一个函数而不是一个对象?
JavaScript中的对象是引用类型的数据,当多个事例引用同一个对象时,一个实例对这个对象进行操作,其他实例中的数据也会发生变化
在vue中,为了使每个组件都有自己的数据空间,不干扰其他组件的运行,就把他写成函数的形式,数据以函数返回值的形式定义,当我们每次复用组件的时候,就会返回一个新的data。
methods
与本地模式写法相同
- <template>
- <div>
- <h1>{{text}}</h1>
- <button @click="fun()">点我修改text</button>
- </div>
- </template>
-
- <script>
- export default {
- // 创建模型数据
- data(){
- return {
- text:"么么哒!!!!!"
- }
- },
- methods:{
- fun(){
- this.text="你坏!!!!!"
- }
- }
-
- }
- </script>
-
- <style>
-
- </style>
与本地模式写法相同
- <template>
- <div>
- <h1>{{text}}</h1>
- <button @click="fun()">点我修改text</button>
- </div>
- </template>
-
- <script>
- export default {
- // 创建模型数据
- data(){
- return {
- text:"么么哒!!!!!"
- }
- },
- methods:{
- fun(){
- this.text="你坏!!!!!"
- }
- },
- watch:{
- text(newval){
- console.log("text被改变了",newval)
- }
- }
-
- }
- </script>
-
- <style>
-
- </style>
谁触发这个事件 事件对象就是谁
- <template>
- <div>
- <h1>事件对象</h1>
- <button @click="fun($event)">点我触发事件对象</button>
- </div>
- </template>
-
- <script>
- export default {
- methods:{
- fun(xiaoming){
- console.log(xiaoming.target)
- }
- }
- }
- </script>
-
- <style>
-
- </style>
修饰符
vue中对于事件上面添加了一个新的内容修饰符,通过修饰符可以对当前这个事件来设置更多辅佐性的功能
语法:v-on: 或@事件.修饰符="函数"
1.按键修饰符
对键盘上面的按键进行指定
.up .down .left .right .ctrl .enter .space
- <template>
- <div>
-
- <h1>使用修饰符来完成对于指定按键的设置</h1>
- <input type="text" @keydown.space="func()">
- </div>
- </template>
-
- <script>
- export default {
- methods:{
-
- func(){
- console.log("空格被按下了")
- }
- }
- }
- </script>
-
- <style>
-
- </style>
阻止冒泡 | .stop |
---|---|
阻止默认行为 | .prevent |
设置捕获(与事件冒泡相反) | .capture |
只触发一次 | .once |
只触发自己范围内的事件,不包含子元素的 | .self |
修饰符同时可以串联
- <!-- 修饰符可以串联 -->
- <div class="zi" @click.stop.once="zi()"></div>
- <template>
- <div>
-
- <h1>阻止冒泡</h1>
- <div class="fu" @click="fu()">
- <div class="zi" @click.stop="zi()"></div>
- </div>
- </div>
- </template>
-
- <script>
- export default {
-
- methods:{
- fu(){
- console.log("ffufufufufufufu")
- },
- zi(){
- console.log("zizziziziziziz")
- },
-
- }
- }
- </script>
-
- <style>
- .fu{
- background-color: pink;
- width: 500px;
- height: 500px;
- }
- .zi{
- background-color: gray;
- width: 200px;
- height: 200px;
- }
- </style>
计算属性——computed
vue的属性 这个属性是有计算功能的(对data数据进行计算展示)
语法:写在与data methods等同级位置
一条数据 在多个位置 以不同形态展示的时候 可以使用计算属性computed
一个变量 在显示之前 进行数据处理 也可以使用计算属性computed
computed:{
计算出的结果变量(){
return 计算内容
}
}
- <template>
- <div>
- <h1>正常展示:{{text}}</h1>
- <h1>大写展示:{{textUpper}}</h1>
- <h1>大写加截取展示:{{textSub}}</h1>
- </div>
-
- </template>
-
- <script>
- export default {
- data(){
- return {
- text:"abcdefghijk"
- }
- },
- computed:{
- textUpper(){
- return this.text.toUpperCase()
- },
- textSub(){
- return this.text.toUpperCase().substr(1,5)
- }
- }
- }
- </script>
-
- <style>
-
- </style>
-
- <template>
- <div>
- 你好
- <h1>{{newarr}}</h1>
- <h1>{{fun()}}</h1>
- </div>
- </template>
-
- <script>
- export default {
- data(){
- return {
- arr:[111,2222,3333,4444,555,666,777,888]
- }
- },
- computed:{
- newarr(){
- console.log("计算属性")
- return this.arr.slice(0,4)
- }
- },
- methods:{
- fun(){
- return this.arr.slice(0,4)
- }
- }
- }
- </script>
-
- <style>
-
- </style>
计算属性与方法最大的区别是
计算属性走缓存,只要计算属性处理过数据之后,数据在没有改变的时候,无论在页面调用多少次,它都只执行一次,剩下的调用都是从缓存中进行读取的,节省资源。
函数(方法)只要被调用就会执行,调用多少次就会执行多少次,比较消耗资源
计算属性(computed)与监听(watch)的区别
计算属性与监听都是对data的数据进行相关的操作
计算属性是依赖data的数据,并且对data的数据进行处理并把处理后的结果返回
监听仅仅是监听,当data的数据改变时它会触发一个函数,来完成一些逻辑
浏览器的安全机制,不同源(不同端口 不同协议 不同域名)就会造成跨域
- 1.jsonp(面试会问,工作不用)
-
- 2.代理跨域
- devServe代理跨域
- nginx反向代理
- 3.cors
代理跨域:
devServe代理跨域
方式:
1.需要在vue项目的根目录下创建一个vue.config.js
文件
2.在vue.config.js
文件中写以下内容:
- module.exports={
- devServer:{
- proxy:{
- "/api":{
- target:"http://www.weather.com.cn/",
- changeOrigin:true,
- pathRewrite:{
- "^/api":""
- }
-
- }
- }
- }
- }
-
-
-
3.【重要】修改项目的请求路径为/api
4.因为上一步修改了配置文件,项目必须重启(重新npm run serve)
拦截器
在发送请求的时候,在项目中 每次请求都要携带一些参数数据的时候,可以使用拦截器,把每次发送请求时需要携带的数据,使用拦截器先拦截下来 添加要携带的参数,再发送出去,减少代码重复编写。
拦截器分为两种:
1.请求拦截
2.响应拦截(404或其他拦截错误时给用户作出相应提示)
使用:
1.在项目的src文件夹下新建两个文件夹 :
api===存储数据请求封装
util===存储工具库的
2.创建拦截器 在util文件夹下新建service.js文件,写以下内容:
- import axios from "axios"
- // 创建axios实例
- let service=axios.create()
-
- // 设置拦截器
- // 添加请求拦截器
- service.interceptors.request.use(function (config) {
- // 在发送请求之前做些什么
- return config;
- }, function (error) {
- // 对请求错误做些什么
- return Promise.reject(error);
- });
-
- // 添加响应拦截器
- service.interceptors.response.use(function (response) {
- // 对响应数据做点什么
- return response;
- }, function (error) {
- // 对响应错误做点什么
- return Promise.reject(error);
- });
-
- export default service
- import axios from "axios"
- // 创建axios实例
- let service=axios.create()
-
- // 设置拦截器
- // 添加请求拦截器
- service.interceptors.request.use(function (config) {
- // 在发送请求之前做些什么
- return config;
- }, function (error) {
- // 对请求错误做些什么
- return Promise.reject(error);
- });
-
- // 添加响应拦截器
- service.interceptors.response.use(function (response) {
- // 对响应数据做点什么 当相应成功正确的时候你所写的地方
- return response;
- }, function (error) {
- console.log("http状态吗",error.response.status)
-
- switch (error.response.status) {
- case 404:
- alert("哎呀网络连接超时!!!!")
- break;
- case 500:
- alert("当前服务器正在维护请您稍后再试")
- break;
-
- default:
- alert("您的错误反馈后台技术已经接收 请您稍后在次访问此页面!")
- break;
- }
-
-
- // 对响应错误做点什么
- return Promise.reject(error);
- });
-
- export default service
就是在发送请求的时候 会先经过他 可以在请求拦截里面添加每次发送请求都要携带的参数
1.在src/api文件夹
下创建一个getapi.js文件
封装数据请求
- import service from "@/util/service.js"
-
- // 开始封装数据请求
- function getlink(url){
- return new Promise((resolve,reject)=>{
- // 开始写你的数据请求
- service.request({
- url,
- method:"GET"
- }).then((ok)=>{
- resolve(ok)
- }).catch((err)=>{
- reject(err)
- })
- })
- }
-
-
- export default getlink
2.调用数据请求
模拟数据===mockjs
1.下载 npm install --save mockjs
2.在src文件夹下创建一个mock文件夹(用来存放模拟数据的文件夹)
3.编写模拟数据json与mock配置
3.1在src/mock文件夹下创建.json文件用来编写模拟数据
3.2配置模拟数据==在mock文件夹里新建index.js文件
- // 1.引用mockjs
- let Mock=require("mockjs")
- // 2.配置
- // Mock.mock("模拟数据地址","方式get/post",require("你的json数据"))
- Mock.mock("/data/list/xiaoming","get",require("./data.json"))
4.在main.js
里使main.js和mockjs建立关联
- import Vue from 'vue'
- import App from './App.vue'
-
- // 1.引用组件
- import Ceshi from "./components/ceshi.vue"
- // 2.配置成为全局组件
- // Vue.component(给你引用的组件起个调用名,你引用的组件)
- Vue.component("Ceshi",Ceshi)
-
-
- // 建立mock与项目的关系
- // 因为如果我们只写了文件夹的地址 那么他会自动找到这个文件夹的index
- // .js
- require("./mock")
-
- Vue.config.productionTip = false
-
- new Vue({
- render: h => h(App),
- }).$mount('#app')
get请求 发送数据使用params发送
使用data
发送数据需要进行转换
post发送数据需要进行转换URLSearchParams( )之后 后台才能正常接收到数据
- fun(){
- // 发送post需要使用
- let usp= new URLSearchParams()
- // 每条数据都需要使用append进行绑定
- // usp.append(你要发送数据的key,val)
- usp.append("uname",this.inputaval)
- usp.append("upwd",this.inputbval)
- link("/api/niubi_userlist/user/denglu","post",{},usp).then((ok)=>{
- console.log(ok)
- })
- }
- }
1.根目录下新建vue.config.js文件
- moudle.exports={
- devServer:{
- // 自动开启
- open:true,
- port:8888//修改端口号 手动指定端口号
- }
- }
在项目的根目录下vue.config.js文件中
- module.exports={
- devServer:{
- open:true
- },
-
- // 配置引用别名
- configureWebpack:{
- resolve:{
- alias:{
- // 别名:真实路径
- "niubi":"@/utils"
- }
- }
- }
- }
组件
基本概念
组件自定义控件(通过组件可以把一个页面拆分成一个个小UI模块,然后把它们拼装到一块形成一个完整的页面)
通过组件,创建出可复用的UI代码块
组件的本质:自定义标签(单标签,双标签均可)
组建的分类
1.局部组件===components
只能在部分地方使用
1.在src下的components文件夹中创建对应的组件.vue文件并且编写内容
2.显示组件【在APP.vue中进行】(默认情况下 只创建组件 是不会在页面显示的)
(1)引用(import from)
(2)调用(components+组件名)
在data、methods的同级位置 创建components:{调用的组件}
(3)使用
- <template>
- <div id="app">
- <!-- 3.使用 -->
- <Id/>
- <Swiper></Swiper>
- <Link></Link>
- <Ms></Ms>
- </div>
- </template>
-
- <script>
- // 1.引用
- import Id from "@/components/inputdemo.vue"
- import Link from "@/components/link.vue"
- import Ms from "@/components/miaosha.vue"
- import Swiper from "@/components/swiper.vue"
-
- export default {
- name: 'App',
- // 2.调用
- components:{
- Id,Link,Ms,Swiper
- }
-
- }
- </script>
-
- <style>
-
- </style>
可以在项目的任何地方使用(想过想在多个地方使用某组件,可以把这个组件变成全局组件)除非前期设计好组件的使用,否则建议少用全局组件(全局组件名会造成项目的污染)
1.在main.js
中进行引用和配置
- import Vue from 'vue'
- import App from './App.vue'
-
- // 1.引用组件
- import Ceshi from "./components/ceshi.vue"
- // 2.配置成为全局组件
- // Vue.component(给你引用的组件起个调用名,你引用的组件)
- Vue.component("Ceshi",Ceshi)
-
- Vue.config.productionTip = false
-
- new Vue({
- render: h => h(App),
- }).$mount('#app')
2.在想使用全局组件的地方直接用
比如想在a.vue组件中使用,在页面如下位置引入
- <template>
-
- <div>
- <h1>
- 链接栏
- <Test/>
- </h1>
- </div>
- </template>
各组件之间样式互不干扰
使用scoped后,当前样式仅对当前组件生效
- <style scoped>
- h1{
- background-color: red;
- }
- </style>
父子组件
组件与组件之间是可以相互嵌套的,这种嵌套关系就是父子组件
组件的作用域
组件与组件之间的数据可以相互使用吗?
父组件的数据子组件不能直接用
子组件的数据父组件不能直接用
组件与组件之间是一个完整的独立的个体,数据与数据之间默认是不能相互直接使用的
组件传值
父子组件传值===正向传值(父>子)===props
props是一个属性
普通传值
1.在子页面中 data methods同级使用 props:[接收父组件传值的变量1,接收父组件传值的变量2,接收父组件传值的变量3,接收父组件传值的变量.......]
- <template>
- <div>
- zizizizziizz
- </div>
- </template>
-
- <script>
- export default {
- // 1.在子组件设置接受变量
- props:["zitext"]
- }
- </script>
2.在子组件中进行使用
- <template>
- <div>
- <!-- 2.在子组件中使用这个接受变量 -->
- zizizizziizz----{{zitext}}
- </div>
- </template>
-
- <script>
- export default {
- // 1.在子组件设置接受变量
- props:["zitext"]
- }
- </script>
3.父组件传值
- <template>
- <div>
- <!-- 3.父组件给子组件传递数据 -->
- <Zi :zitext="futext"/>
- ===变量加v-bind(:),字符串不加v-bind,直接 zitext="字符串内容"===
- </div>
- </template>
传值验证
props验证,在传统的props验证的写法中,我们可以给子组件传递任何数据类型的数据
但是在一些特殊情况下这样可能会出问题(如果子组件拿到数据需要对数据进行操作的时候,可能不同的数据类型所展示的结果就会出现偏差)
props验证如果不成功,不会影响页面的展示,只会在控制台给出一个警告提示
语法:
1.在data methods等同级位置
- export default {
- props:{
- 要接收的变量:数据类型//Number 数字类型、String 字符串类型、 Boolean 布尔类型
- }
- }
- <template>
- <div>
- zizizziziziziziziz---{{title+6}}
- </div>
- </template>
-
- <script>
- export default {
- // props:["title"]
- // 验证的写法
- props:{
- // title:Number //我要接受的title必须是数字类型
- // title:[Number,Boolean] // 既可以传递number又想传递布尔
- // 既想验证数据类型 又想验证不能为空
- title:{
- type:Number,// 验证数据类型
- required:true//不能为空
-
- }
- }
- }
- </script>
-
- <style>
-
- </style>
2.使用
3.传递
同基本写法
逆向传值默认不允许,想进行逆向传值的话,必须通过事件来触发传递
1.在子组件中创建一个事件触发一个函数,进行逆向传值的准备
- <template>
- <div>
- zizizizizzi
- <button @click="fun()">点我逆向传值</button>
- </div>
- </template>
-
- <script>
- export default {
- methods:{
- fun(){
-
- }
- }
- }
- </script>
-
- <style>
-
- </style>
-
2.在子组件中抛出子组件要传递的数据===把数据绑定到自定义事件之上
自定义事件: this.$emit(“自定义事件的名字”,“数据”)
- <template>
- <div>
- zizizizizzi
- <button @click="fun()">点我逆向传值</button>
- </div>
- </template>
-
- <script>
- export default {
- data(){
- return {
- zitext:"我是子组件的数据"
- }
- },
- methods:{
- fun(){
- // 使用自定义事件抛出子组件的数据
- this.$emit("xiaoming",this.zitext)
- }
- }
- }
- </script>
-
- <style>
-
- </style>
3.父组件接收子组件抛出的数据===接收自定义事件使用数据
- <template>
- <div>
- fyufufufff
- <!--
- 父组件接受子组件抛出的自定义事件
- 父组件接受的这个函数不加()
- -->
- <Zi @xiaoming="demo"/>
- </div>
- </template>
-
- <script>
- import Zi from "./zi.vue"
- export default {
- components:{Zi},
- // 创建函数
- methods:{
- demo(text){
- console.log(text)
- }
- }
-
- }
- </script>
-
- <style>
-
- </style>
ref完成逆向传值
只需要在组件之上使用ref即可直接取出子组件的数据
兄弟组件传值===同胞传值-中央事件总线(eventBus)
在同一父组件下的子组件进行相互数据传递
中央事件总线(eventBus):凌驾于两个兄弟组件之上的一个空的vue实例
1.在src文件夹下创建eventBus文件夹(容纳中央事件总线的文件夹),新建index.js文件
- // 容纳中央事件总线
- import Vue from "vue"
- export default new Vue
2.在要传递的组件(src/components/里面的组件文件)上抛出
- <template>
- <div>
- ziaaaaaaaaaaaaaaaaaaaaaa
- <!-- 1.需要通过事件来触发 -->
- <button @click="fun()">点我传值给zib</button>
- </div>
- </template>
-
- <script>
- // 2.引用中央事件总线
- import Eventbus from "@/eventbus"
- export default {
- methods:{
- fun(){
- // 3.开始使用中央事件总线来传出数据
- // 在中央事件总线的这个空vue实例之上绑定了一个自定义事件
- Eventbus.$emit("zia","我是子a的数据么么哒!!")
- }
- }
- }
- </script>
-
- <style>
-
- </style>
3.在要接收的组件中接收
- <template>
- <div>
- zizizizizizbbbbbbbbbbbbbb
- </div>
- </template>
-
- <script>
- // 1.引用中央事件总线
- import Eventbus from "@/eventbus"
- export default {
- mounted(){
- //注意是mounted 不是methods
- // 2.使用中央事件总线来监听接收数据
- // $on() 监听实例上的自定义事件
- // Eventbus.$on("你要监听的事件名",(自定义事件上的数据)=>{})
- Eventbus.$on("zia",(val)=>{
- console.log(val)
- })
- }
- }
- </script>
-
- <style>
-
- </style>
vuex-跨组件传值-爷爷传给孙子
vuex:状态(数据)管理工具
vuex可以把整个项目的数据集中地管理起来,方便组件与组件的使用(组件想使用数据, 不需要使用复杂的传递方式了,直接去vuex中进行数据的获取)
传统的vue是单向数据流,如果是兄弟或者是跨层级的组件在进行传递的时候,vue就非常麻烦,vuex就可以进行上述传递,简化了数据传递的复杂度
src/store文件夹 用来容纳vuex的文件夹
vuex创建流程
1.下载 npm install --save vuex
2.在src文件夹下新建store文件夹 并且新建index.js
- import Vue from 'vue'
- import Vuex from 'vuex'
-
- Vue.use(Vuex)
-
- export default new Vuex.Store({
-
- })
3.在main.js中引用vuex文件 并且在vue实例上注册
- import Vue from 'vue'
- import App from './App.vue'
- import router from './router'
- import store from './store'//引用
-
- Vue.config.productionTip = false
-
- new Vue({
- router,
- store,//注册
- render: h => h(App)
- }).$mount('#app')
-
vuex5大属性
vuex的所有数据都在state中进行创建
- import Vue from 'vue'
- import Vuex from 'vuex'
-
- Vue.use(Vuex)
-
- export default new Vuex.Store({
- state: {//创建数据的类似于组件中的data
- text:"你好",
- age:18,
- arr:[111,2222,33333],
- obj:{
- love:"女"
- }
- },
- mutations: {
- },
- actions: {
- },
- modules: {
- }
- })
-
1.取值方式一
任意组件想要使用数据,使用this.$store.state.xxx
- <template>
- <div>
- hhhhh{{this.$store.state.text}}
- </div>
- </template>
-
- <script>
- export default {
-
- }
- </script>
-
- <style>
-
- </style>
2.取值方式二
计算属性computed
防止数据没有请求到的时候页面会报错
- <template>
- <div>
- uuuuu{{newage}}
- </div>
- </template>
-
- <script>
- export default {
- // 取值方式2
- computed:{
- newage(){
- return this.$store.state.age
- }
- }
- }
- </script>
-
- <style>
-
- </style>
mutations属性:vuex的数据修改
vuex中state的数据不能直接修改
mutations里面封装的是一个个函数,每个函数就是一个修改的动作
如果要触发mutations的修改动作 我们要使用commit这个方法来进行调用commit触发mutations修改
1.通过事件触发commit来调用修改操作
- <template>
- <div>
- hhhhh{{this.$store.state.text}}
- <button @click="fun()">点我修改</button>
- </div>
- </template>
-
- <script>
- export default {
- methods:{
- fun(){
- // 需要触发这个函数之后把vuex的text变量进行修改
- // this.$store.commit("你要调用的mutations的名字",传递的参数)
- this.$store.commit("uptext",{newtext:"你坏"})
- }
- }
- }
- </script>
-
- <style>
-
- </style>
2.去store中编写对应的mutations修改动作
- mutations: {
- uptext(){
-
- }
-
- },
3.开始修改
- mutations: {
- // 第一个形参state就是指向上面的state数据源
- // 第二个形参接收的就是commit方法中的第二个参数
- uptext(state,payload){
- state.text=payload.newtext
- }
-
- },
扩展===vuex数据修改刷新丢失
在vuex中如果修改数据之后,页面刷新一次,那么页面的数据会恢复成默认值。
解决方法:在页面刷新的时候,把vuex里的数据转成字符串,转成对象,存储到本地,页面刷新后,将本地存储的数据重新渲染到页面中
- created() {
- //在页面加载时读取sessionStorage里的状态信息
- if (sessionStorage.getItem("store")) {
- this.$store.replaceState(
- Object.assign(
- {},
- this.$store.state,
- JSON.parse(sessionStorage.getItem("store"))
- )
- );
- }
-
- //在页面刷新时将vuex里的信息保存到sessionStorage里
- window.addEventListener("beforeunload", () => {
- sessionStorage.setItem("store", JSON.stringify(this.$store.state));
- });
- },
actions属性===触发异步操作
actions是一个触发器,可以帮我们触发一个异步操作(异步请求)
actions中一个个方法,每一个方法就是一个异步的动作
actions调用的话,使用dispatch()调用
1.页面通过dispatch来触发actions
- <template>
- <div>
- ppppp{{this.$store.state.text}}
-
- <button @click="fun()">点我触发异步操作</button>
- </div>
- </template>
-
- <script>
- export default {
- methods:{
- fun(){
- // 调用actions
- // this.$store.dispatch("你出发的actions的名字",{数据})
- this.$store.dispatch("demoLink",{xxx:vvv})
- }
- }
- }
- </script>
-
- <style>
-
- </style>
actions创建对应的方法
- actions: {
- // context形参 就是store对象
- demoLink(){
- console.log("我是actions")
- }
- },
数据请求闭环
- // <!-- 1.页面中通过事件触发一个函数 -->
- created(){
- // 2.通过dispatch触发一个actions
- this.$store.dispatch("getaxios",{url:"/data/one"})
- }
3.编写对应的actions
- actions: {
-
- // 3编写对应的actions
- getaxios(){
-
- }
- },
4.引用数据请求 并且发送
- import Vue from 'vue'
- import Vuex from 'vuex'
- // 4.引用数据请求
- import getlink from "@/apis/getapi.js"
-
- Vue.use(Vuex)
-
- export default new Vuex.Store({
- state: {//创建数据的类似于组件中的data
-
- },
- mutations: {
-
-
- },
- actions: {
-
- // 3编写对应的actions
- getaxios(context,payload){
- console.log(context)
- // 5.发送一部操作
- getlink(payload.url).then((ok)=>{
- console.log(ok)
- })
- }
- },
- modules: {
- }
- })
-
- actions: {
-
- // 3编写对应的actions
- getaxios(context,payload){
- console.log(context)
- // 5.发送一部操作
- getlink(payload.url).then((ok)=>{
- console.log(ok.data.data)
- // 6.把请求来的数据交给mutations来修改state
- context.commit("uparr",{arrdata:ok.data.data})
- })
- }
- },
7.创建对应的mutations
- // 7创建对应的mutations
- uparr(state,payload){
- // 8把请求来的数据修改state
- state.arr=payload.arrdata
- }
在页面展示
- <template>
- <div>
-
-
- <h1>-----</h1>
- {{newarr}}
- </div>
- </template>
-
- <script>
- export default {
- // 取值方式2
- computed:{
-
- newarr(){
- return this.$store.state.arr
- }
- },
- // <!-- 1.页面中通过事件触发一个函数 -->
- created(){
- // 2.通过dispatch触发一个actions
- this.$store.dispatch("getaxios",{url:"/data/one"})
- }
- }
- </script>
-
- <style>
-
- </style>
getters属性===vuex的计算属性
getters可以对一个数据在不同位置展示出不同的形态使用
getters处理的数据 任何组件都能用
vue的计算属性处理的数据只能当前组件使用
定义getters
- getters:{
- // 里面就一个形参 state代表的就是数据源
- newdemo(state){
- return state.demo.toUpperCase()
- }
- }
使用
在想使用的地方直接使用 this.$store.getters.xxx(getters里的函数名)
即可获取到处理好的数据
可以把原来写在一起的数据 修改 异步操作 计算属性 按照页面等进行分类管理
1.新建文件用来单独放置上述的属性
- let userm={
- state: {
- text:"我是user的数据"
- },
- mutations: {
-
- },
- actions: {
- },
-
- getters:{
-
- },
- }
- export default userm
2.把模块注入到vuex中
- import Vue from 'vue'
- import Vuex from 'vuex'
-
- // 引用模块
- import Homem from "./modules/homem.js"
- import Phonem from "./modules/phonem.js"
- import Userm from "./modules/userm.js"
-
- Vue.use(Vuex)
-
- export default new Vuex.Store({
-
- // 注入
- modules: {
- Homem,
- Phonem,
- Userm
-
- }
- })
-
3.使用数据 this.$store.state.模块名.xxx
slot槽口/插槽
用来混合父组件和子组件自己的模板(就是可以在组件被调用的时候向其内部插入新的dom节点)
使用方法:
1.在要抛出的组件使用:
solt子组减的值
2.在要接收的组件使用:
如果调用的时候组件使用的是双标签,默认情况下不能在他的开关标签中插入新的内容
- <template>
- <div>
- fufufuffufu
- <Zi>
- 这个h1是不会显示的
- <h1>你好么么哒!!!!^_!</h1>
- </Zi>
- </div>
- </template>
-
- <script>
- import Zi from "./zi.vue"
- export default {
- components:{
- Zi
- }
- }
- </script>
-
- <style>
-
- </style>
在你想插入新内容的组件中,放置一个 ,外部的内容就会显示在slot插入的位置
槽口虽然只有一个 但是外部插入的所有内容都在这一个上面显示 后期不好管理
- <template>
- <div>
- <!-- 插槽 -->
- <slot></slot>
- ziziziziz
-
- </div>
- </template>
1.定义槽口的时候 使用name创建槽口的名字
- <!-- 具名槽口 -->
- <slot name="xiaoming"></slot>
2.插入的时候需要指定往那个槽口插入 使用slot属性
- <template>
- <div>
- fufufuffufu
- <Zi>
- <h1 slot="xiaoming">你好么么哒!!!!^_!1</h1>
- <h1 slot="xiaohong">你好么么哒!!!!^_!2</h1>
- <h1>你好么么哒!!!!^_!3</h1>
- <h1>你好么么哒!!!!^_!4</h1>
- <h1 slot="xiaoming">你好么么哒!!!!^_!7</h1>
- <h1>你好么么哒!!!!^_!8</h1>
- </Zi>
- </div>
- </template>
作用域插槽
路由
为我们完成页面之间的跳转,让我们完成单页面多视图的应用(SPA)
vue-router库来实现路由
创建
手工创建
1.下载vue-route库
2.创建views文件夹 并写入路由页面组件
3.配置路由规则
3.1新建router文件夹 并新建index.js文件
3.2在index.js文件中
- import Vue from 'vue'//引用vue
- import VueRouter from 'vue-router'引用vuerouter
-
-
- Vue.use(VueRouter)在vue中使用路由功能
-
- 创建了路由规则配置
- const routes = [
- {
- path: '/home',
- name: 'Home',
- component: Home
- },
-
- ]
- 实例化路由对象 并且设置路由模式与路由规则的传入
- const router = new VueRouter({
- mode: 'history',
- base: process.env.BASE_URL,
- routes
- })
- 暴露
- export default router
4.注入路由 main.js文件中注入
- import Vue from 'vue'
- import App from './App.vue'
- import router from './router' 引用路由
-
-
- Vue.config.productionTip = false
-
- new Vue({
- router,注入路由
- render: h => h(App)
- }).$mount('#app')
-
vue-cli自动创建
在创建vue脚手架项目的时候 要选中router项
在项目创建好之后 src文件夹下多了两个文件夹
views===页面文件夹
router===配置路由的
创建一级路由
1.在/src/views文件夹下创建对应页面
2.配置路由页面规则 /src/router/index.js中进行配置
- import Vue from 'vue'
- import VueRouter from 'vue-router'
-
- // 1.引用路由页面到路由规则配置文件中
- import Home from '../views/home.vue'
- import Gouwu from '../views/gouwu.vue'
- import Jingxi from '../views/jingxi.vue'
- import Fenlei from '../views/fenlei.vue'
- import Wode from '../views/wode.vue'
-
- // 在vue中使用路由功能
- Vue.use(VueRouter)
- // 2、配置路由规则
- const routes = [
- {
- path: '/',//url路径
- name: 'Home',//给当前的规则起个名字
- component: Home //你匹配的路由页面
- },
- {
- path: '/gouwu',//url路径
- name: 'gouwu',//给当前的规则起个名字
- component: Gouwu //你匹配的路由页面
- },
- {
- path: '/fenlei',//url路径
- name: 'fenlei',//给当前的规则起个名字
- component: Fenlei //你匹配的路由页面
- },
- {
- path: '/jingxi',//url路径
- name: 'jingxi',//给当前的规则起个名字
- component: Jingxi //你匹配的路由页面
- },
- {
- path: '/wode',//url路径
- name: 'wode',//给当前的规则起个名字
- component: Wode //你匹配的路由页面
- },
- ]
-
- const router = new VueRouter({
- mode: 'history',
- base: process.env.BASE_URL,
- routes
- })
-
- export default router
-
3.设置路由出口,在app.vue中 使用router-view进行标识
路由导航
分类
声明式==标签的跳转方式
router-link来进行页面的切换 其中to属性来设置跳转地址
选中的样式类
在vue路由导航中 会默认给我们选中的当前导航添加样式类 router-link-active
如果在配置路由的时候,路由规则的path中,有单独的/ ,那么无论是否选中当前这个路由,都会添加相应的类名。解决方法:在配置路由的时候,path中不设置单独 /
但是如果在设置路由规则path的时候,没有设置单独的 / 那么第一次进入页面的时候就没有默认路由规则,也就是没有默认的首页,解决方式就是使用重定向
编程式==js的方式进行跳转
this.$router.push("/要跳转的页面")
- <template>
- <div>
- 404页面
- <br>
- <button v-on:click="fun()">点我去首页</button>
- </div>
- </template>
-
- <script>
- export default {
- methods:{
- fun(){
- // 编程式导航
- this.$router.push("/home")
- }
- }
- }
- </script>
-
- <style>
-
- </style>
this.$router.replace("/要跳转的页面")===不能回退,付款等页面使用
this.$router.go( ) 正数-前进 负数-回退
重新定位方向 可以在第一次进入页面的时候帮助用户自动把页面进行指定为位置的切换
- const routes = [
- {
- path: '/home',
- name: 'Home',
- component: Home
- },
- {
- path: '/shop',
- name: 'shop',
- component: Shop
- },
- {
- path: '/phone',
- name: 'phone',
- component: Phone
- },
- {
- path: '/user',
- name: 'user',
- component: User
- },
-
- // 重定向
- {
- path:"/",
- // 重新定位方向
- redirect:"/home"
- }
-
- ]
url中出现了没有配置过得路由页面,就会出现白屏
解决方法:需要给用户没有在url中没有配置过路由的情况下, 作出一个页面没有找到的提示
404页面必须在路由规则的最下面 就算有重定向也要在它下面
- const routes = [
- {
- path: '/home',
- name: 'Home',
- component: Home
- },
- {
- path: '/shop',
- name: 'shop',
- component: Shop
- },
- {
- path: '/phone',
- name: 'phone',
- component: Phone
- },
- {
- path: '/user',
- name: 'user',
- component: User
- },
-
-
- // 重定向
- {
- path:"/",
- // 重新定位方向
- redirect:"/home"
- },
- // 404页面必须在路由规则的最最最下面 就算有重定向也要在他下面
- // 404页面必须在路由规则的最最最下面 就算有重定向也要在他下面
- {
- path: '*',
- name: 'no',
- component: No
- }
-
- ]
在一个路由中嵌套另外一个路由就叫多级路由
(1)在views文件夹创建一级界面文件,在views/二级路由文件夹创建二级界面文件
(2)一级页面写 1.写切换的页面 2.router-view路由出口
- <router-link to="/1">切换页面1</router-link>
- <router-link to="/2">切换页面1</router-link>
- <router-view></router-view> //路由出口
(3)在router/index.js文件中 先在顶部import引入一级和二级页面。给一级路由添加children属性,把二级页面添加进去
使用children关键字进行配置
1.在views文件夹下 新建二级路由页面
2.配置路由规则
2.1在router文件夹下的index.js中引用二级路由页面
2.2在要添加二级路由的一级路由的配置页(router/index.js)中配置二级路由
- import Vue from 'vue'
- import VueRouter from 'vue-router'
- import Home from '../views/home.vue'
- import Sj from '../views/shiji.vue'
- import Syy from '../views/shuyingyin.vue'
- import Wode from '../views/wode.vue'
- import Xz from '../views/xiaozu.vue'
-
-
- // 1.引用二级路由页面
- import Era from "@/views/er/era.vue"
- import Erc from "@/views/er/erc.vue"
- import Erd from "@/views/er/erd.vue"
- import Ere from "@/views/er/ere.vue"
-
- Vue.use(VueRouter)
-
- const routes = [
- {
- path: '/home',
- name: 'Home',
- component: Home
- },
-
- {
- path: '/sj',
- name: 'Sj',
- component: Sj
- },
- {
- path: '/syy',
- name: 'Syy',
- component: Syy,
- // 2.二级路由配置
- children:[
- {
- path: '/era',
- name: 'Era',
- component: Era
- },
- {
- path: '/erc',
- name: 'Erc',
- component: Erc
- },
- {
- path: '/erd',
- name: 'Erd',
- component: Erd
- },
- {
- path: '/ere',
- name: 'Ere',
- component: Ere
- },
- ]
- },
- {
- path: '/wode',
- name: 'Wode',
- component: Wode
- },
- {
- path: '/xz',
- name: 'Xz',
- component: Xz
- },
-
- {
- path:"/",
- redirect:"/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')
- // }
- ]
-
- const router = new VueRouter({
- mode: 'history',
- base: process.env.BASE_URL,
- routes
- })
-
- export default router
-
3.在对应一级页面中,使用配置二级路由出口
- <template>
- <div>
- <Bb/>
- 书影音
- <!-- 配置二级路由的出口 -->
- <router-view></router-view>
- </div>
- </template>
-
- <script>
- export default {
-
- }
- </script>
-
- <style>
-
- </style>
4.设置路由导航
4.1如果多级路由在配置规则(index.js)的时候,path带 / - path: “/xxx” 那路由导航()属性就是 /xxx
- {
- path: '/era', //path带/斜杠
- name: 'Era',
- component: Era
- },
-
- 路由导航
- <router-link to="/era">era</router-link>
4.2如果多级路由在配置规则的时候 path不带 / path:“xxx” 那么 路由导航to属性就是/一级路由/二级路由
- {
- path: 'era', //path不带/
- name: 'Era',
- component: Era
- },
-
- 路由导航
- <router-link to="/syy/era">era</router-link>
在vue设置路由的时候,有两种模式:hash、history
在main.js
中使用mode来设置
mode: 'history',
区别 | hash(默认值) | history |
---|---|---|
url展示上 | url带# | url不带# |
兼容性 | 支持低版本浏览器 | 是HTML5新增的所以不兼容低版本浏览器 |
刷新页面(上线之后) | 刷新正常 | 刷新页面会丢失 |
#号的影响
在开发APP分享页面的时候,如果这个页面就是vue写的,在嵌入到第三方原生app 的时候,有的app对url有要求,不能带#
动态路由匹配/路由传参
把数据从一个路由页面传递到另外一个页面的技术
传参方式
params
1.在路由规则中设置接收参数(谁接收数据,就在谁的路由规则中配置)
- {
- path: '/xz/:xiaoming',//接收数据的规则上设置接收参数
- name: 'Xz',
- component: Xz
- },
2.发送数据
this.$router.push({name:“要跳转的路由规则name”,params:{配置的接收参数:“数据”}})
<router-link v-bind:to="{name:“要跳转的路由规则的name”,params:{配置的接收参数:“数据”}}">
- fun(id){
- console.log(id)
- // 传递数据
- // this.$router.push({name:"你要跳转的路由规则的name",params:{你配置的接收参数:"数据"}})
- this.$router.push({name:"Xz",params:{xiaoming:id}})
- }
3.接收数据this.$route.params.xxx
<h1>{{this.$route.params.xiaoming}}</h1>
query
1.发送数据
this.$router.push({name:“要跳转的路由规则的name”,query:{接收参数:“数据”}})
this.$router.push({path:“要跳转的路由的路径”,query:{接收参数:“数据”}})
- // 使用query方式进行传参
- this.$router.push({name:"Sj",query:{xiaohong:"我是query传参"}})
2.接收数据
this.$route.query.xxx
区别
1.用法上:
query方式可以使用path也可以使用name作为跳转路径,params只能用name
接收上:query使用this.r o u t e . q u e r y . x x x 而 p a r a m s 使 用 t h i s . route.query.xxx 而params使用this.route.query.xxx而params使用this.route.params.xxx
2.url展示上不同
query是key=val query显示key相对来说不安全
params url只有val 不显示key 相对来说安全一些
r o u t e r 与 router与router与route
$router 是vueRouter的全局对象里面包含了对路由全局操作的属性和方法
$route 是一个路由对象。每一个路由都有一个route对象也就是说他是类似于局部页面路由的一个对象他只能处理当前路由页面的操作
路由懒加载
懒加载就是按需加载,在想使用的时候进行加载
就是给使用者更好的用户体验,路由的项目可能会出现首页白屏问题
路由是完成spa单页面应用的一个技术,就是项目中之后一个页面,如果用户需要切换页面显示的话,就是在当前页面对整体内容进行一个替换
项目在第一次加载的时候 会把全部页面都加载 然后把需要显示的页面显示出来,可能页面过多,导致加载事件过长,那么用户所看到的就是白屏
路由懒加载分为两种:
在router/index.js中修改,采用懒加载后头部不需要import Home from '../views/home.vue的方式进行引用
1.vue异步组件的方式
component: (resolve) => require(['你要引用的路由页面路径'], resolve)
2.es中import的方式
- component: () => import('你要引用的路由页面路径')
-
- {
- path: '/class',
- name: 'Class',
- component: () => import ('../views/class.vue'),
- },
路由钩子/路由守卫/导航守卫
路由切换的时候被自动调用的函数
使用场景:vue项目中进行所在路由页面切换的时候 进行一些项目的验证,比如:用户登录的状态验证,就需要每次页面切换的时候进行状态的验证(会自动执行)
全局守卫
无论哪个路由 在切换到时候都会触发这个钩子函数
在router/index.js中写。写在实例化路由对象之后
全局前置守卫-beforeEach()
- // 全局前置守卫
- // router.beforeEach((to去哪里,from从哪里来,next下一步)=>{})
- router.beforeEach((to,from,next)=>{
- console.log("to",to)
- console.log("from",from)
-
-
- if(to.path=="/about"){
- next()
- }else{
- alert("您没有登录请您登录后在试!!!")
- next("/about")
- }
-
- })
全局后置守卫-afterEach()
进入到路由的时候生效
- // 全局后置守卫
- // router.afterEach((to从哪来,from去哪里)=>{})
- router.afterEach((to,from)=>{
- console.log("to",to)
- console.log("from",from)
- })
相对于全局守卫来说,路由守卫仅对一个路由页面生效
router/index.js 钩子函数写在指定要设置守卫的路由配置中,与path 那么 同级
- {
- path: '/phone',
- name: 'phone',
- component: () => import( '../views/phone.vue'),
- // 路由独享守卫
- beforeEnter(to,from,next){
- console.log(to)
- console.log(from)
- // 进行一些是否登录的判断判断成功让她进入 不成功不能进
- alert("当前页面是vip页面")
- next("/about")//不让下一步
- }
- },
写在指定的.vue文件中
- <template>
- <div>
- 组件内守卫
- </div>
- </template>
-
- <script>
- export default {
- // 进入组件的时候调用
- beforeRouteEnter(to,from,next){
- console.log(to)
- console.log(from)
- console.log("进来了")
- next()
- },
- // 离开组件的时候调用
- beforeRouteLeave(to,from,next){
- console.log("离开了")
- console.log(to)
- console.log(from)
- if(confirm("是否离开?")){
- next()
- }else{
- next(false)
- }
- }
- }
- </script>
-
- <style>
-
- </style>
开发者可以再路由中自己添加一些数据 方便页面使用
- {
- path: 'erf',
- name: 'erf',
- component: () => import( '../views/er/erf.vue'),
- meta:{
- title:"账号权限"
- }
- },
页面得到路由信息
this.$router.options.routes
mixin-混入
mixin是vue组件复用功能的技术之一 它可以把多个组件中重复出现的属性和方法多次进行封装方便多次调用
使用
1.混入就是把组件多次使用的属性和方法等内容进行封装
新建mixin文件夹用来容纳混入的封装
- export let demo={
- methods:{
- fun(){
- console.log("你好!!!!!!")
- }
- },
- data(){
- return {
-
- }
- },
- computed:{
-
- }
- }
慎用全局混入,可能会造成代码的污染
- import Vue from 'vue'
- import App from './App.vue'
- import router from './router'
- import store from './store'
- // 1.引用mixin
- import {demo} from "./mixins"
- // 2.配置全局混入
- Vue.mixin(demo)
-
- Vue.config.productionTip = false
-
- new Vue({
- router,
- store,
- render: h => h(App)
- }).$mount('#app')
-
- <template>
- <div class="about">
- <h1>This is an about page</h1>
- <!-- 3.就可以直接想怎么用就怎么用混入的内容 -->
- <button @click="fun()">点我调用混入的方法--{{text}}</button>
- </div>
- </template>
- <script>
- // 1.引用混入
- import {demo} from "@/mixins"
- export default {
- // 2.调用混入
- mixins:[demo]
- }
-
- </script>
-
-
生命周期钩子函数
生命周期 vue实例从创建到销毁的过程
钩子函数 就是特定阶段内被自动调用的函数。给开发者在程序不同阶段提供一个自动执行程序(逻辑)的场所
8个钩子函数 4组(实例创建 模板渲染 数据更新 实例销毁)
实例的创建
beforeCreate实例准备创建。
created 实例创建完毕。在vue实例new 创建完毕之后立即调用,但是这个时候只是把vue实例出来了,实例中的data methods等属性还没有开始处理
模板渲染
beforeMount模板准备渲染
mounted 页面加载完毕之后立即调用 页面已经显示了 vue实例中的内容也已经处理完了
数据更新
beforeUpdata 开始准备更新
updated 更新完毕
实例销毁
beforeDestory 开始准备销毁
Destorted 销毁完毕
常见问题
1.生命周期在页面初次加载的时候执行什么?
前两组 分别为 实例创建前后(带英文) 模板创建前后(带英文)
2.声明周期的作用是什么?
vue实例从创建到销毁的过程中在特定阶段内被自动调用的函数同时给开发者在程序的不同阶段提供一个自动执行程序(逻辑)的场所
3.vue生命周期一共几个阶段?
4大阶段 8个钩子
4.简述vue生命周期的各个钩子函数?
beforeCreate 实例准备创建(数据观测与初始化事件还没有执行)
created 实例创建完毕 (完成了诗句的观测 属性 方法也都进行了初始化 但是页面没有显示渲染)
beforeMount 模板准备渲染 (在准备吧template模板网页面中进行挂载 准备编译页面内容)
mounted 页面加载完毕之后立即调用 (页面被成功的进行了挂载 页面的dom内容也都生成完毕)
updated 更新完毕(数据已经成功的在页面dom中更新完毕了)
beforeDestory 开始准备销毁(vue实例还能用)
Destoryed 销毁完毕
5.vue数据请求应该在哪个钩子函数中进行调用,为什么?
在created和mounted中都可以
但是,如果要涉及请求完毕操作dom的时候,那么必须在mounted中进行数据请求
过滤器
在不改变原始数据的情况下 格式化展示数据
全局过滤器===filter
局部过滤器===filters
1.写在与data、methods等 同级位置
filters:{
过滤器的名字(操纵的数据){
return 要做的事情===函数
}}
- export default {
- props:["datalist"],
- // 过滤器
- filters:{
- xiaoming(val){
- if(val.length>6){
- return val.substr(0,5)+".."
- }else{
- return val
- }
-
- }
- }
- }
使用过滤器,在想使用的数据后面使用 管道符(|)+过滤器名字
在项目的根目录下vue.config.js文件中
- module.exports={
- devServer:{
- open:true
- },
-
- // 配置引用别名
- configureWebpack:{
- resolve:{
- alias:{
- // 别名:真实路径
- "niubi":"@/utils"
- }
- }
- }
- }
在给多个组件使用用一个挂载点并且动态切换(多个组件每次只显示一个并且动态的进行切换)
语法:
在页面想显示多个组件的时候会用下面的语法 来声明挂载点
- <template>
- <div>
- phone
- <button @click="fun('One')">点我去one</button>
- <button @click="fun('Two')">点我去two</button>
- <button @click="fun('Three')">点我去three</button>
- <component :is="com"></component>
- </div>
- </template>
-
- <script>
- import One from "@/components/one.vue"
- import Two from "@/components/two.vue"
- import Three from "@/components/three.vue"
- export default {
- methods:{
- fun(data){
- this.com=data
- }
- },
- data(){
- return {
- com:"Three"
- }
- },
- components:{
- One,Two,Three
- }
- }
- </script>
-
- <style>
-
- </style>
keep-alive
在动态组件中如果有多个输入框 那么我们在切换动态组件的时候会发现这些输入框的内容会丢失
在多个路由页面中如果有多个输入框 那么我们在切换路由页面的时候会发现这些驶入框的内容也会丢失
我们在路由或者是动态组件切换的时候因为 每次切换vue都会出现一个新的vue组件实例 所以会丢失
keep-alive 可以在keep-alive包裹的内容 在切换的时候把数据状态保存在内存中 防止重复的DOM渲染 减少了性能与时间上的损耗
用在动态组件之上
- <keep-alive>
- <component :is="com"></component>
- </keep-alive>
用在路由之上 只需包裹路由的出口
- <keep-alive>
- <router-view/>
- </keep-alive>
include 你想缓存的
- <keep-alive include="One">
- <component :is="com"></component>
- </keep-alive>
可以写多个 中间用逗号隔开
- <keep-alive include="One,Two">
- <component :is="com"></component>
- </keep-alive>
exclude 你不想缓存谁
- <keep-alive exclude="One,Two">
- <component :is="com"></component>
- </keep-alive>
有两个钩子函数 但是在写的时候一定要在被keep-alive所管理的组件中进行使用
activated 进入到被keep-alive管理的组件时候触发
deactivated 离开被keep-alive管理的组件时候触发
- activated(){
- console.log("进入到keep-alive管理的组件了")
- },
- deactivated(){
- console.log("离开了keep-alive管理的组件了")
- }
问题:vue数据改变页面没有改变(没有更新)的情况?
原理:当vue中data里的数据(对象和数组)在初始化完毕之后 再向其中插入新的属性的时候,这时候数据发生改变,但是页面视图不会更新
- <template>
- <div>
- <h1>vue数据变视图不会改变-----$set</h1>
- <h1>{{ obj.name }}--{{obj.age}}</h1>
- <button @click="fun()">点我添加新内容</button>
- <!-- 问题所在: 当vue的data中的数据(对象和数组)在初始化完毕之后
- 再向其中插入新的属性的时候
- 那么这时数据发生改变 但是页面视图不会更新 -->
- </div>
- </template>
-
- <script>
- export default {
- data() {
- return {
- obj: {
- name: "xixi",
- },
- }
- },
- methods:{
- fun(){
- this.obj.age=18
- console.log("age",this.obj.age)
- }
- }
-
- };
- </script>
-
- <style>
- </style>
问题:Object.defineProerty()的问题
在vue2.0中双向绑定使用的是数据劫持Object.defineProerty(),但是Object.defineProerty()就监听不到 监听不到就没有数据劫持 没有劫持就没有双向绑定 所以数据变了视图也不会改变
解决:$set
想中途添加一个新属性并且数据变视图也要改变怎么办?
语法:this.$set(“要修改的”,“要新增的key”,“要新增的val”)
- <h2>$set应用</h2>
- <button @click="set()">点击更改数据</button>
- <h3>{{ obj.text }}</h3>
-
- set(text){
- // this.$set(this.obj,"text",text);
- this.$set(this.obj,"text",text);
- this.obj.text="我是$set更改后的数据";
- console.log(this.obj.text)
- }
就是在vue中进行dom操作
- <template>
- <div>
- <input type="text" id="demoinput">
- <!-- 1.使用ref给元素起个名字 -->
- <input type="text" ref="refinput">
- <input type="text">
- user
- <button @click="fun()">点我得到输入框的值</button>
- </div>
- </template>
-
- <script>
- export default {
- methods:{
- fun(){
- // console.log(document.getElementById("demoinput").value)
- // 2.找到ref的内容
- console.log(this.$refs.refinput.value)
- }
- }
- }
- </script>
-
- <style>
-
- </style>
ref绑定到组件之上
完成逆向传值
可以在父组件中触发子组件的方法
自定义指令=directives
在现有的指令不够用的时候,自己创建指令
语法:
写在与data methods同级
directives:{
自定义指令的名字:{
自定义指令的钩子函数(el 绑定的自定义指令所在的dom元素){
要操作的逻辑(函数)
}
}
}
自定义指令钩子函数
bind:绑定指令到元素上 只执行一次
inserted:绑定了指令的元素在插入页面展示的时候调用
update:所有节点更新的时候调用
componentUpdate:指令所在组件的节点一级他自己所有的子节点全部更新了 再调用
unbind:解除指令和元素的绑定时候调用,只执行一次
- directives:{//自定义指令
- xiaoming:{//自定义指令的名字随便起
- inserted(el){
- el.style.color="red";
- }
- }
- },
v-自定义指令的名字
<h1 v-xiaoming>This is an about page</h1>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。