vue
一、Vue框架
1.1 vue:
# 前端三大框架 Angular React Vue # 设计模式:MVVM # js渐进式框架:一个页面小到一个变量,大到整个页面,均可以有vue控制,vue也可以控制整个项目 # 可以完全脱离服务器端,以前端代码复用的方式渲染整个页面:组件化开发
1.2 Vue实例
1. el: 实例 2. data: 数据 3. methons:方法 4. computed:计算 5. watch:监听 6. delimiters:分隔符
二、Vue的优点
1. 单页面, 高效 2. 数据双向绑定: 3. 虚拟DOM:页面缓存 4. 组件化开发 5. 数据驱动,从数据出发,不是从DOM出发 6. 轻量级
三、vue的指令
3.1 文本指令
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>文本指令</title> </head> <body> <div id="app"> <!-- 1. 插值表达式:在文本内置直接写变量挥着变量表达式--> <p>{{ msg }}</p> <p>{{ num * 3 - 5 }}</p> <!--2. v-text, v-html, v-once 三个文本指令--> <p v-text="message"></p> <h4 v-text="msg">==================</h4> <!-- 默认 v-text 是没有闪烁问题的 --> <!-- v-text会覆盖元素中原本的内容,但是 插值表达式 只会替换自己的这个占位符,不会把 整个元素的内容清空 -- <!--v-html可以直接解析文本内容,文本内容需要一字符串形式包裹,如果文本内容为无法解析的内容,直接显示字符串--> <p v-html="'htmlMSG'"></p> <p v-html="'<b>v-html解析标签</b>'"></p> <p v-html="htmlMSG" @click="ChangeMSG"></p> <!--3. v-once:插值表达式渲染文本,once来限制文本不可修改--> <!--插值表达式中一个变量被限制,整个结果都被限制--> <p v-once="htmlMSG">{{ htmlMSG + msg }}</p> </div> </body> <script src="js/vue.js"></script> <script> new Vue({ el: '#app', data: { msg: 'p标签的msg', num: 10, message: 'v-text文本指令', htmlMSG: '<b>加粗的v-html文本指令</b>' }, methods: { ChangeMSG () { this.htmlMSG = '测试能否更改' } } }) </script> </html>
3.2 斗篷指令
<style type="text/css"> [v-cloak] { display: none; } </style> <div id="app" v-cloak> {{ msg }} </div> <script src="js/vue.min.js"></script> <script type="text/javascript"> new Vue({ el: "#app", data: { msg: "message" } }) </script> <!-- 避免页面闪烁-->
3.3 属性指令
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>属性指令</title> <style> .box { width: 200px; height: 200px; background-color: orange; } .wrap { width: 100px; height: 100px; background-color: red; } .kiss { width: 150px; height: 150px; background-color: cyan; } .x { width: 300px; } .y { height: 300px; } .z { background-color: brown; } </style> </head> <body> <div id="app"> <!--v-bind:属性名="属性值", v-bind:可以简写为:--> <!-- v-bind:style="MyStyle", v-bind:class="MyClass", v-bind:aaa="MyAAA" --> <div class="box" v-bind:style="myStyle" @click="changeColor('pink')"></div> <!-- 1. 操作单个样式: w变量的值就是为属性宽提供数据的--> <div class="box" v-bind:style="{'width': w}" @click="changeWidth"></div> <!-- 2. 操作多个样式: more_style是一个对象变量, 可以复制多个key:value的模式 --> <div class="box" v-bind:style="more_style" @click="changeStyle"></div> <!-- 3. v-bind:可以简写为: 可以绑定所有系统和自定义属性,属性一旦绑定, 后方就是变量名 --> <div :aaa="AAA">简写v-bind</div> <!-- 4. 操作单个类名 --> <!-- 直接赋值, c1就是变量, 变量值就是类名--> <div :class="c1" @click="changeClass"></div> <!-- 布尔切换:该div有一个kiss类名, kiss_able的true或false决定kiss的生效 --> <div :class="{kiss: kiss_able}"></div> <!-- 5. 操作多个类名:[变量1, 变量2, ... ,变量n], 每个变量的值都是的类名 --> <div class="[x, y, {z: is_z}]"></div> </div> </body> <script src="js/vue.js"></script> <script> new Vue({ el: '#app', data: { myStyle: 'background-color: red;', w: '400px', more_style: { width: '100px', height: '100px', borderRadius: '50%', backgroundColor: 'cyan' }, c1: 'wrap', kiss_able: true, x: 'x', y: 'y', is_z: true, }, methods: { changeColor (color) { this.myStyle = 'background-color:' + color + ';'; }, changeWidth () { this.w = '500px' }, changeStyle () { // 可以更改全局样式 // this.more_style = { // width: '200px', // height: '200px', // borderRadius: '50%', // backgroundColor: 'tan' // }; // 也可以更改其中一个样式 this.more_style.borderRadius = '30%'; }, changeClass () { if (this.c1 === 'box') { this.c1 = 'wrap' } else { this.c1 = 'box'; } }, }, }) </script> </html>
3.4 事件指令
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>事件指令</title> </head> <body> <!--事件指令:1)明确事件名 2)明确事件函数 v-on:事件名="事件函数"--> <div id="app"> <!-- 1. 基础的绑定事件 单击: v-on:click 双击: v-on:dblclick--> <p v-on:click="clickAction">单击</p> <p v-on:dblclick="dblclickAction">双击</p> <!--2. 点击事件传参数--> <ul> <li v-on:click="liAction(0)">111</li> <li v-on:click="liAction(1)">222</li> <li v-on:click="liAction(2)">333</li> </ul> <!--3. 传递事件对象--> <p v-on:click="sysAction1">不传自定义参数</p> <p v-on:click="sysAction2(888, $event)">传自定义参数</p> <!--4. v-on: 可以简写为 @--> <p @click="clickAction">单击</p> </div> </body> <script src="js/vue.js"></script> <script> new Vue ({ el: '#app', data:{}, methods: { clickAction () { alert('单击') }, dblclickAction () { alert('双击') }, liAction(index) { alert(index) }, sysAction1 (ev) { // 接收到鼠标点击事件 console.log(ev) }, sysAction2(num, ev) { console.log(num); console.log(ev); }, } }) </script> </html>
3.5 表单指令
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>表单指令</title> </head> <body> <div id="app"> <!-- v-model表单指令, v-model="变量" 变量给value属性提供值--> <!-- 1. 数据的双向绑定 将两个input框的值设定为一样即可 --> <input type="text" v-model="val"> <input type="text" v-model="val"> <p>{{ val }}</p> <!-- 2. 普通输入框,直接绑定变量即可--> <form action=""> <input type="text" v-model="val"> </form> <!-- 3. 单选框--> <!-- radio_val的值是多个单选框中一个value值, 代表该单选框默认选中 --> <form action=""> <p> <label for="male">男</label> <input type="radio" id="male" value="male" v-model="radio_val" name="sex"> <label for="male">女</label> <input type="radio" id="female" value="female" v-model="radio_val" name="sex"> <button @click="alterValue">单选框提交给后台的value</button> <span>{{ radio_val + '被选中'}}</span> </p> </form> <!-- 4. 独立使用的复选框 --> <!-- sure_val的值为true或者false, 决定该单个复选框是否选中 --> <form action=""> <p> <input type="checkbox" name="sure" value="同意" v-model="sure_val"> <span>{{ sure_val }}</span> </p> </form> <form action=""> <p> 男:<input type="checkbox" name="hobby" value="male" v-model="hobby_val"> 女:<input type="checkbox" name="hobby" value="female" v-model="hobby_val"> 哇塞:<input type="checkbox" name="hobby" value="?" v-model="hobby_val"> <span>{{ hobby_val }}</span> </p> </form> </div> </body> <script src="js/vue.js"></script> <script> new Vue({ el: '#app', data: { val: '', radio_val: 'male', sure_val: true, hobby_val: [] }, methods: { alterValue () { alert(this.radio_val) } } }) </script> </html>
3.6 条件指令
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>条件指令</title> <style> .box { width: 200px; height: 200px; } .b1 {background-color: orange;} .b2 {background-color: cyan;} .r {background-color: red;} .g {background-color: green;} .b {background-color: blue;} </style> </head> <body> <div id="app"> <!-- v-if v-show 条件指令: v-if="变量" v-show="变量"--> <!-- 1. v-if、 v-show比较, 两者绑定的变量值都是true|false --> <!--v-if在隐藏时,不被渲染 | v-show在隐藏时,采用display: none存在--> <p> <button @click="toggleAction(true)">显示</button> <button @click="toggleAction(false)">隐藏</button> </p> <div class="box b1" v-if="is_show"></div> <div class="box b2" v-show="is_show"></div> <!-- 2. v-if, v-else-if v-else --> <p> <button @click="toggleShow('red')">红</button> <button @click="toggleShow('green')">绿</button> <button @click="toggleShow('blue')">蓝</button> </p> <div class="box r" v-if="color == 'red'"></div> <div class="box g" v-else-if="color == 'green'"></div> <div class="box b" v-else></div> </div> </body> <script src="js/vue.js"></script> <script> new Vue({ el: '#app', data: { is_show: false, color: 'red' }, methods: { toggleAction (is_show) { this.is_show = is_show }, toggleShow (color) { this.color = color } } }) </script> </html>
3.7 循环指令
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>循环指令</title> </head> <body> <div id="app"> <!-- 1. 对数组的循环 --> <ul> <li v-for="(arr, i) in array">{{ i }} : {{ arr }}</li> </ul> <!-- 2. 对对象(字典)的循环 --> <ul> <li v-for="(v, k, index) in dic">{{index}}:{{k}}:{{v}}</li> </ul> <!-- 3. 列表套字典循环 --> <ul> <p v-for="info in msg"> <span v-for="(v, k, i) in info"> <!--{{ person['name'] }}--> <!--{{ person.age }}--> <!--{{ person.gender }}--> <b v-if="i != 0">|</b> <span>{{ k }}:{{ v }} </span> </span> </p> </ul> </div> </body> <script src="js/vue.js"></script> <script> new Vue({ el: '#app', data: { array: ['aaa','bbb','ccc'], dic: { 'name': 'wangyong', 'age': 20, 'gender': 'male', }, msg: [ {'name': 'wangyong', 'age': 20, 'gender': 'male',}, {'name': 'jiyuzhi', 'age': 20, 'gender': 'male',}, ] }, }) </script> </html>
3.8 todolist案例
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>todolist</title> </head> <body> <div id="app"> <div> <input type="text" v-model="msg_val"> <button @click="sendMsg">提交</button> <ul> <li v-for="(msg, index) in msgs"> <span @click="deleteMsg(index)">{{ msg }}</span> </li> </ul> </div> </div> </body> <script src="js/vue.js"></script> <script> new Vue({ el: '#app', data: { msg_val: '', // msgs: ['第一条留言', '第二条留言'] msgs: localStorage.msgs ? localStorage.msgs.split(','):[] }, methods: { sendMsg () { // 1)判断是否有数据,如果没有,直接结束 if (!this.msg_val) return; // 2)将用户提交的数据添加到留言组中 // this.msgs.push(this.msg_val); // 尾增 this.msgs.unshift(this.msg_val); // 首增 // 3)数据同步到前台数据库 localStorage.msgs = this.msgs; // 4)清空输入框 this.msg_val = ''; }, deleteMsg (index) { // splice方法删除数据 this.msgs.splice(index, 1); // 同步删除数据库中的内容 localStorage.msgs = this.msgs }, } }) </script> </html>
3.9 插值表达式符号修改(delimiters)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Title</title> </head> <body> <div id="app"> <p>{{ msg }}</p> <p>{{{ msg }}}</p> </div> </body> <script src="js/vue.js"></script> <script> new Vue({ el: '#app', data: { msg: 'hello world' }, delimiters: ['{{{', '}}}'] // 设计修改后的样式 }) </script> </html>
四、vue的属性
4.1 计算属性(computed)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>监听多个变量</title> </head> <body> <div id="app"> <input type="text" v-model="a_val"> <input type="text" v-model="b_val"> <input type="text" v-model="c_val"> <p>{{ val_fn }}</p> </div> </body> <script src="js/vue.js"></script> <script> new Vue({ el: '#app', data: { a_val: '', b_val: '', c_val: '', }, // computed内部书写方法 - 管理可以监听多个变量的方法 // 1)方法名 可以直接作为变量被渲染,值为方法的返回值 // 2) 在方法名被渲染后(在页面中使用了),方法内部的所有变量都会被监听 // 3)computed用来解决一个变量值依赖一个或多个变量值 computed: { val_fn () { return this.a_val + this.b_val + this.c_val } } }) </script> </html>
4.2 监听属性(watch)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>监听属性</title> </head> <body> <div id="app"> <p>姓名:<input type="text" v-model="full_name"></p> 姓:<input type="text" v-model="last_name"> 名:<input type="text" v-model="first_name"> </div> </body> <script src="js/vue.js"></script> <script> new Vue({ el: '#app', data: { full_name: '', last_name: '', first_name: '', }, // watch内部书写方法 - 管理 监听绑定的属性(提前要存在) 的方法 // 1)方法名 被监听的变量名(属性) // 2) 在方法名被渲染后,方法名代表的属性值改变,绑定的方法就会被调用 // 3)watch用来解决多个变量值依赖一个变量值 watch: { full_name () { let name = this.full_name.split(' '); this.last_name = name[0]; this.first_name = name[1]; } } }) </script> </html>
五、vue的组件
5.1 组件的引入
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <h1 id="app"> {{ msg }} </h1> <div id="main"> {{ msg }} </div> </body> <script src="js/vue.js"></script> <script> // 1、new Vue创建的是vue实例,一个实例就是一个vue组件,new出了的实例称之为根组件 // 注:在实际开发中一个页面只有一个根组件 // 2、每个组件均由 html模板 css样式 js逻辑 组成 // html模板: template,根组件的模板就采用挂载点即可,无需创建自身template // 注:挂载点是必须的(作为虚拟DOM渲染替换的依据),挂载点可以读取,作为根组件的模板,使用根组件无需书写template // 3、根组件内部可以注册使用n个子组件,子组件必须拥有自己的 html模板 css样式 js逻辑 // 如果创建子组件 | 如何使用子组件 | 父子组件间的通信 let app = new Vue({ el: '#app', data: { msg: 'app的msg', c: 'red' }, // template: '<ul>{{ msg }}</ul>', template: `<h1 id="app" :style="{color: c}" @click="action"> {{ msg }} </h1> `, methods: { action () { alert(this.msg) } } }); let main = new Vue({ el: '#main', data: { msg: 'main的msg' } }); // 知识点:利用原生js完成两个组件的交互 // 获取组件的数据 // console.log(app.msg); // 修改组件的数据 // app.msg = '12345'; main.msg = app.msg; </script> </html>
5.2 常用方法
5.2.1 局部组件
1. 书写自己的html代码:template:` ... ` 2. 获取父组件的数据: props = [] 3. 子组件数据获取时通过函数返回值来 data () { return { num: 0 } }
5.2.2 根组件
1. 注册子组件函数: components:{} 2. 注册时候,如果变量名与变量值都是一样的话,可以简写一个, components: { box, },
5.3 父组件传递数据给子组件
# 父组件传递数据给子组件的真谛:通过绑定属性的方式进行数据传递 1. 父组件模板中写子组件标签 2. 父组件的数据绑定给子组件标签的自定义属性 3. 在子组件内部通过props拿到自定义属性 4. 使用自定义属性就可以获得父组件的数据
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Title</title> <style> .box { width: 200px; border: 1px solid black; border-radius: 10px; overflow: hidden; float: left; } .box img { width: 100%; } p { text-align: center; color: red; } </style> </head> <body> <div id="app"> <!-- box_data为自己创建的数据,后期可以为后台传过来的数据 --> <!-- 通过在子组件中创立一个属性得到可以获取的属性值,在子组件中接受属性值,这样父组件就能将数据传给子组件看了--> <box v-for="data_obj in box_data" :data_obj="data_obj"></box> </div> </body> <script src="js/vue.js"></script> <script> let data = [ { img_url: 'img/001.jpg', img_title: '第一张图' }, { img_url: 'img/002.jpg', img_title: '第二张图' }, ]; let box = { // 通过props props: ['data_obj'], template:`<div class="box"> <img :src="data_obj.img_url" alt="" > <p @click="action">第{{ num }}次点击</p> </div>`, data () { return { num: 0, } }, methods: { action () { this.num++ }, } }; new Vue({ el: '#app', components: { box, }, data: { box_data: data } }) </script> </html>
# 子组件传递数据给父组件的真谛:通过发送事件请求的方式进行数据传递 1. 在根标签的挂在点对应的标签内,创建自定义标签并绑定自定义事件 @事件名="事件值" 2. "事件值"为在根组件中的事件名 3. 子组件创立需要通过方式 Vue.component('自定义标签名',{ ... }) 4. 在子组件中通过事件,通过this.$emit('事件名',子组件传出的值1,子组件传出的值2,...) 5. 在根组件定义的事件中, 子组件传出的值为 创建的事件的参数,即 2 中的事件值对应的事件名的参数
<div id="app"> <global-tag @send_action='receiveAction'></global-tag> </div> <script type="text/javascript"> Vue.component('global-tag', { data () { return { sub_data1: "数据1", sub_data2: '数据2' } }, template: '<div @click="clickAction">发生</div>', methods: { clickAction () { this.$emit('send_action', this.sub_data1, this.sub_data2) } } }) new Vue({ el: '#app', methods: { receiveAction (v1, v2) { console.log(v1, v2) } } }) </script>
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <div id="app"> <h1>{{ title }}</h1> <sub-tag @send_val="recv_val"></sub-tag> </div> </body> <script src="js/vue.js"></script> <script> let subTag = { template: ` <div> <input type="text" v-model="val"> <button @click="changeTitle">修改</button> </div> `, data () { return { val: '' } }, methods: { changeTitle () { if (!this.val) return; // 如果有数据,将数据发生给父组件 this.$emit('send_val', this.val); this.val = ''; } } }; new Vue({ el: '#app', data: { title: '父组件标题' }, components: { subTag }, methods: { recv_val (val) { this.title = val; } } }) </script> </html>
六、生命周期钩子
表示一个vue实例从创建到销毁的这个过程,将这个过程的一些时间节点赋予了对应的钩子函数 钩子函数: 满足特点条件被回调的方法
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Title</title> </head> <body> <div id="app"> <tag></tag> </div> </body> <script src="js/vue.js"></script> <script> let tag = { template: ` <h1 @click="action">{{ msg }}</h1> `, data () { return { msg: '局部组件' } }, methods: { action () { console.log(this.msg) } }, beforeCreate () { console.log(this.data); // undefined console.log('实例刚刚创建, data, methods尚未创建') }, created () { console.log(this.msg); // 局部组件 // 获取方法 想要获取data, methods,需要使用 this.$options.data, this.$option.methods console.log(this.$options.methods); console.log('实例创建成功, data, methods已拥有') }, mounted () { console.log('页面已经被渲染, data, methods已更新') } }; new Vue ({ el: '#app', data: { info: 123 }, components: { tag, }, }) </script> </html>
官网下载node.js安装包,傻瓜式安装:http://nodejs.cn/,安装完之后就有npm,类似python中的pip
然后cmd中运行npm install -g cnpm -- registry=https://registry.npm.taobao.org # 如果上面不成功,则 npm install -g cnpm
cnpm install -g @vue/cli
npm cache clean --force
vue create 项目名 // 要提前进入目标目录(项目应该创建在哪个目录下) // 选择自定义方式创建项目,选取Router, Vuex插件
cd vue_proj cnpm run serve
方式二:pycharm启动
node_modules: # 项目依赖 public: # 公用文件 favicon.ico: # 页面标签图标 index.html: # 项目的唯一页面(单页面) 模板 src: # 项目开发文件目录 assets: # 静态资源 css|js|img components: # 小组件 *.vue views: # 视图组件 *.vue App.vue: # 根组件 main.js: # 主脚本文件 router index.js: # 路由脚本文件 - vue-router store index.js: # 仓库脚本文件 - vuex *.xml|json|js: # 一系列配置文件 README.md: # 使用说明 【记住】 根组件写在src目录下的App.vue中, 渲染的模板不是放在public目下的index.html中
<div id="#app"></div>
<template> <div id="app"> <div id="nav"> <router-link to="/">Home</router-link> | <router-link to="/about">About</router-link> </div> <router-view/> </div> </template>
import Vue from 'vue' // node_modules下的依赖直接写名字 import App from './App.vue' // ./代表相对路径的当前目录,文件后缀军可以省略 import router from '@/router.js' // @ 代表src的绝对路径 import store from './store' // 在main中配置的信息就是给整个项目配置 // 已配置 vue | 根组件App | 路由 | 仓库 // 以后还可以配置 cookie | ajax(axios) | element-ui Vue.config.productionTip = false; // Tip小提示 // 原内容为, 可以由后面的new Vue替换 // new Vue({ // router, // store, // render: h => h(App) // }).$mount('#app') new Vue({ el: '#app', router: router, store, // render: function (fn) { // return fn(App) // } // 解释:function (h) {return 1} | (h) => {return 1} | h => 1 render: readTemplateFn => readTemplateFn(App) });
<!-- components/ClickComponents.vue --> <!--html代码:有且只有一个根标签--> <template> <div @click="actionColor" :class="{active: is_active}">点我变颜色</div> </template> <!--js代码:在export default {} 的括号内完成组件的各项成员:data|methods|... --> <script> export default { name: "ClickComponents", data () { return{ is_active: false } }, methods: { actionColor () { this.is_active = !this.is_active; } } } </script> <!--css代码:scoped样式组件化 - 样式只在该组件内部起作用 --> <style scoped> .active { color: red; } </style>
八、路由
import Main from './views/Main' routes: [ { path: '/main', name: 'main', component: Main } ]
<router-link :to="{name: 'main'}">主页</router-link>
router-link:会被vue渲染成a标签,但是点击这样的a标签不能发生页面的转跳,只会出现组件的替换 a:也可以完成同样的效果,但是会发生页面的转跳
router [ { path: '/', name: 'home', component: Home }, { path: '/home', redirect: '/', // 重定向 } ]
{ // path如果通过头直接访问,路由必须完全对应 // :id代表可以完成任意内容匹配,用变量id保存 // 请求/course/detail/1 和 /course/detail/abc,id变量分别存的1和abc, path: '/course/detail/:id', name: 'course-detail', component: CourseDetail },
<template> <div class="course"> <h1>课程</h1> <hr> <ul> <li v-for="course in courses" :key="course.title"> <!--<router-link :to="{name: 'course-detail'}">{{ course.title}}</router-link>--> <router-link :to="'/course/detail/' + course.id">{{ course.title}}</router-link> </li> </ul> </div> </template> <script> let course_list = [ { id: 1, title: '水浒传' }, { id: 2, title: '西游记' }, { id: 3, title: '三国演义' }, ]; export default { name: "Course", data () { return { courses: [] } }, // 组件创建成功去获取数据 created () { this.courses = course_list } } </script> <style scoped> li a { display: block; } li { border: 1px solid orange; background-color: rgba(123,80,66, 0.3); margin-top: 10px; line-height: 80px; cursor: pointer; } </style>
<template> <div class="course-detail"> <h1>课程详情</h1> <hr> <h2>{{ ctx }}</h2> </div> </template> <script> let course_detail_list = [ '数据有误', '水浒传', '西游记', '三国演义' ]; export default { name: "CourseDetail", data () { return { ctx: '' } }, created () { console.log('详情页面被渲染了'); // this.$route:负责路由的数据 // this.$router:负责路由的路径 // this.$route.params可以拿到链接中 :变量 变量中的数据 let index = this.$route.params.id; // 获取id的值 if (index < 0 || index >= course_detail_list.length) index = 0; this.ctx = course_detail_list[index] } } </script> <style scoped></style>
{ path: '/course/detail', name: 'course-detail', component: CourseDetail }
<router-link :to="'/course/detail?id=' + course.id">{{ course.title }}</router-link>
created () { let index = this.$route.query.id; if (index < 0 || index >= course_detail_list.length) index = 0; this.ctx = course_detail_list[index] }
{ path: '/course/detail', name: 'course-detail', component: CourseDetail }
// methods: { // 转跳的方法 (参数) { // this.$router.push({ // name: 'course-detail', // params 或者 query: { // 参数们 // }, // : { // 参数们 // } // }) // } // } methods: { toDetail (id) { this.$router.push({path: '/course/detail?id=' + id}); this.$router.push({ name: 'course-detail', // query: { // id:id // }, params: { id:id } }); } }
// created () { // let 参数的数据 = this.$route.query.参数的key 或者 this.$route.params.参数的key // } created () { let index = this.$route.params.id; if (index < 0 || index >= course_datail_list.length) index = 0; this.ctx = course_datail_list[index]; // let index = this.$route.query.id; // if (index < 0 || index >= course_datail_list.length) index = 0; // this.ctx = course_datail_list[index]; }
this.$router.go(-1) //返回历史记录的前一页
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex); export default new Vuex.Store({ // 全局可以访问的变量 - 获取值 // 组件内:this.$store.state.title state: { title: '主页' }, // 全局可以访问的方法 - 修改值 // 组件内:this.$store.commit('updateTitle', '新值') mutations: { updateTitle (state, newValue) { state.title = newValue } }, actions: {} })
<template> <div class="mainsubsub"> <input type="text" v-model="val"> <button @click="btnClick">修改</button> </div> </template> <script> export default { name: "MainSubSub", data () { return { val: '' } }, methods: { btnClick () { this.$store.commit('updateTitle', this.val) } } } </script> <style scoped> </style>
>: cd 项目目录 >: cnpm install axios --save
import Axios from 'axios' Vue.prototype.$axios = Axios;
// 测试axios是否配置成功, 可以在Home组件中或者其他位置 created () { console.log(this.$axios) }
// 方式一 this.$axios({ url: 'http://localhost:8000/test/', method: 'get', params: { username: 'wangyong', password: '123', method: 'get', } }).then((response) => { console.log(response) }).error((error) => { console.log(error) }); // 方式二 this.$axios.get('http://localhost:8000/test/', { params: { username: 'wangyong', password: '123', method: 'get', } }).then((response) => { console.log(response) }).error((error) => { console.log(error) });
// 方式一 this.$axios({ url: 'http://localhost:8000/test/', method: 'post', data: { username: 'wangyong', password: '123', method: 'post', } }).then((response) => { console.log(response) }); // 方式二 this.$axios.post('http://localhost:8000/test/', { username: 'wangyong', password: '123', method: 'get', }).then((response) => { console.log(response) }); // 【注意】:post请求,在后台收到的信息在request.body中获得,从request.POST中无法获取数据
cnpm install jquery
const webpack = require("webpack"); module.exports = { configureWebpack: { plugins: [ new webpack.ProvidePlugin({ $: "jquery", jQuery: "jquery", "window.jQuery": "jquery", "window.$": "jquery", Popper: ["popper.js", "default"] }) ] } };
// 引入jQuery import $ from 'jquery' Vue.prototype.$ = $;
window.$.ajax({ url:"", type:"get" }).then(response => { console.log(response); }); window.$.ajax({ url:"", type:"post", data:data, }).then(response => { console.log(response); });
通常情况下,A网页访问B服务器资源时,不满足以下三个条件其一就是跨域访问 1)服务器不一致 - ip 2)应用不一致 - 端口 3)协议不一致 - http <-> https
''' 1)安装django-cors-headers模块 pip3 install django-cors-headers 2)在settings.py中配置 # 注册app INSTALLED_APPS = [ ... 'corsheaders' ] 3)添加中间件 MIDDLEWARE = [ ... 'corsheaders.middleware.CorsMiddleware' ] 4)允许跨域源 CORS_ORIGIN_ALLOW_ALL = True '''
>: cd 项目目录 >: cnpm install vue-cookie --save
import cookie from 'vue-cookie' Vue.prototype.$cookie = cookie;
// 获取后台返回的token值做为cookie let token = response.data.token; // 设置cookie值 // this.$cookie.set(key, value, time) this.$cookie.set('token', token, 1); // 获取cookie // this.$cookie.get(key) console.log(this.$cookie.get('token')); // 删除cookie // this.$cookie.delete(key) this.$cookie.delete('token');
12.1
12.1.1
>: cnpm install element-ui
12.1.2
import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; Vue.use(ElementUI);
>: cnpm install jquery >: cnpm install bootstrap@3
const webpack = require("webpack"); module.exports = { configureWebpack: { plugins: [ new webpack.ProvidePlugin({ $: "jquery", jQuery: "jquery", "window.jQuery": "jquery", "window.$": "jquery", Popper: ["popper.js", "default"] }) ] } };
测试时候,需要加上window
import 'bootstrap' import 'bootstrap/dist/css/bootstrap.min.css'
12.3
>: cnpm i vant -S
babel.config.js)
// 安装插件 cnpm i babel-plugin-import -Dmodule.exports = { presets: [ '@vue/cli-plugin-babel/preset' ], plugins: [ ['import', { libraryName: 'vant', libraryDirectory: 'es', style: true }, 'vant'] ] }
import 'vant/lib/index.css';
<template> <div> <h1>列表页</h1> <van-pull-refresh v-model="isLoading" @refresh="onRefresh"> <van-list v-model="loading" :finished="finished" finished-text="没有更多了" @load="onLoad"> <van-cell v-for="item in list" :key="item" :title="item"/> </van-list> </van-pull-refresh> </div> </template> <script> import Vue from 'vue'; import {List, Cell, PullRefresh, Toast } from 'vant'; Vue.use(List); Vue.use(Cell); Vue.use(PullRefresh); Vue.use(Toast); export default { name: "list", data() { return { list: [], loading: false, finished: false, isLoading: false, } ; }, methods: { onRefresh() { setTimeout(() => { Toast('刷新成功'); this.isLoading = false; for (let i = 0; i < 20; i++) { this.list.push(this.list.length + 1); } }, 500); }, onLoad() { // 异步更新数据 // setTimeout 仅做示例,真实场景中一般为 ajax 请求 setTimeout(() => { for (let i = 0; i < 20; i++) { this.list.push(this.list.length + 1); } // 加载状态结束 this.loading = false; // 数据全部加载完成 if (this.list.length >= 200) { this.finished = true; } }, 1000); } } } </script> <style scoped> </style>
{ path: '/list', name: 'LIST', component: LIST, },
<!-- 在需要引入的vue中 --> <router-link to="/list">列表页</router-link>