解析vue项目
1.为什么浏览器中访问某个地址,会显示某个页面组件
1.根组件:App.vue 必须是
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
2.配置路由
router---->index.js--->const routes = [
{
path: '/ln',
name: 'ln',
component: Ln # 组件,需要导入
},
]
3.放心大胆的写页面组件 -src---->views文件夹--->xxx.vue
在页面组件中使用组件
1.写一个小组件,eg:写个Child.vue(components文件下写的)
2.在父组件中,导入组件
@代指src路径
import Child from "@/components/Child";
3.父组件中,注册组件
components: {
Child
}
4.父组件中使用组件
<Child :msg="msg" @myevent="handleEvent"></Child>
5.自定义属性,自定义事件,插槽,跟之前一模一样
基本使用
Child.vue
<template>
<div>
<h1>子组件child</h1>
<button @click="back">后退</button>
{{title}}
<button @click="forward">前进</button>
</div>
</template>
<script>
export default {
name: "Child",
data(){
return {
title:'首页',
}
},
methods:{
back(){
alert('后退了')
},
forward(){
alert('前进了')
}
},
}
</script>
<style scoped>
</style>
Ln.vue
<template>
<div>
<h1>Ln.Vue的组件</h1>
<hr>
<Child></Child>
</div>
</template>
<script>
import Child from "@/components/Child.vue";
export default {
name: "Ln.vue",
components:{Child}
}
</script>
<style scoped>
</style>
组件间数据传递
父传子
Child.vue
<template>
<div>
<h1>子组件child</h1>
<button @click="back">后退</button>
{{title}}
<button @click="forward">前进</button>
<br>
<h2>数据传递--子组件接收父组件</h2>
父组件传递给我的:{{name1}}
</div>
</template>
<script>
export default {
name: "Child",
data(){
return {
title:'首页',
}
},
methods:{
back(){
alert('后退了')
},
forward(){
alert('前进了')
}
},
props:["name1"]
}
</script>
<style scoped>
</style>
Ln.vue
<template>
<div>
<h1>Ln.Vue的组件</h1>
我传递给子组件的:{{username}}
<hr>
<Child :name1="username"></Child>
</div>
</template>
<script>
import Child from "@/components/Child.vue";
export default {
name: "Ln.vue",
components:{Child},
data(){
return {
username:'hello nana'
}
}
}
</script>
<style scoped>
</style>
子传父
Child.vue
<template>
<div>
<h1>子组件child</h1>
<button @click="back">后退</button>
{{title}}
<button @click="forward">前进</button>
<br>
<h2>数据传递--子组件接收父组件</h2>
父组件传递给我的:{{name1}}
<br>
<h2>数据传递--子组件给父组件传递消息</h2>
<p><input type="text" v-model="name2">-->{{name2}} <button @click = 'handleSend'>给父组件发送消息</button></p>
</div>
</template>
<script>
export default {
name: "Child",
data(){
return {
title:'首页',
name2:''
}
},
methods:{
back(){
alert('后退了')
},
forward(){
alert('前进了')
},
handleSend(){
this.$emit('myevent',this.name2)
}
},
props:["name1"]
}
</script>
<style scoped>
</style>
Ln.vue
<template>
<div>
<h1>Ln.Vue的组件</h1>
我传递给子组件的:{{username}}
<hr>
<Child :name1="username" @myevent = 'handevent' ></Child>
</div>
</template>
<script>
import Child from "@/components/Child.vue";
export default {
name: "Ln.vue",
components:{Child},
data(){
return {
username:'hello nana'
}
},
methods:{
handevent(name){
alert('接收到子组件传递的消息----->'+name)
}
}
}
</script>
<style scoped>
</style>
插槽的使用
Child.vue
<template>
<div>
<h1>子组件child</h1>
<button @click="back">后退</button>
{{title}}
<button @click="forward">前进</button>
<br>
<h2>数据传递--子组件接收父组件</h2>
父组件传递给我的:{{name1}}
<br>
<h2>数据传递--子组件给父组件传递消息</h2>
<p><input type="text" v-model="name2">-->{{name2}} <button @click = 'handleSend'>给父组件发送消息</button></p>
<h2>插槽---无名</h2>
<slot></slot>
<h2>插槽---有名</h2>
<slot name = 'middle'></slot>
<slot name = 'min'></slot>
</div>
</template>
<script>
export default {
name: "Child",
data(){
return {
title:'首页',
name2:''
}
},
methods:{
back(){
alert('后退了')
},
forward(){
alert('前进了')
},
handleSend(){
this.$emit('myevent',this.name2)
}
},
props:["name1"]
}
</script>
<style scoped>
</style>
Ln.vue
<template>
<div>
<h1>Ln.Vue的组件</h1>
我传递给子组件的:{{username}}
<hr>
<Child :name1="username" @myevent = 'handevent' >
<div>无名的插槽</div>
<div slot="min">有名插槽--min</div>
<div slot="middle">有名插槽--middle</div>
</Child>
</div>
</template>
<script>
import Child from "@/components/Child.vue";
export default {
name: "Ln.vue",
components:{Child},
data(){
return {
username:'hello nana'
}
},
methods:{
handevent(name){
alert('接收到子组件传递的消息----->'+name)
}
}
}
</script>
<style scoped>
</style>
解决后端跨域问题
针对在vue中向后端django中发起post请求
"""
Network Error
AxiosError: Network Error at XMLHttpRequest.handleError
"""
1.安装
pip3.8 install django-cors-headers
2.注册app
INSTALLED_APPS = (
...
'corsheaders',
...
)
3.配置中间件
MIDDLEWARE = [
...
'corsheaders.middleware.CorsMiddleware',
...
]
4. 配置文件中加入:setting下面添加下面的配置
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_METHODS = (
'DELETE',
'GET',
'OPTIONS',
'PATCH',
'POST',
'PUT',
'VIEW',
)
CORS_ALLOW_HEADERS = (
'XMLHttpRequest',
'X_FILENAME',
'accept-encoding',
'authorization',
'content-type',
'dnt',
'origin',
'user-agent',
'x-csrftoken',
'x-requested-with',
'Pragma',
'token'
)
登陆小案例
步骤
1.登录页面:LoginView.vue
2.访问/login 显示这个页面组件
3.在LoginView.vue写html,和js,axios
ps:安装 axios
cnpm install -S axios --->S:把安装的axios放到package.json中
4.写ajax,向后端发送请求,给按钮绑定一个事件
eg:
handleSubmit() {
console.log(this.name, this.password)
axios.post('http://127.0.0.1:8000/login/', {
name: this.name,
password: this.password
}).then(res => {
# console.log(res.data)
if (res.data.code == 100) {
# 跳转到百度
location.href = 'http://www.baidu.com'
} else {
alert(res.data.msg)
}
})
}
5.写个后端的登录接口,处理好跨域问题,处理跨域如下
代码
LoginView.vue
<template>
<div>
<h1>登陆</h1>
<div>
用户名:<input type="text" v-model="username">
</div>
<div>
密码:<input type="password" v-model="password">
</div>
<div>
<button @click="handleClick">登陆</button>
</div>
</div>
</template>
<script>
import axios from "axios"
export default {
name: "LoginView",
data(){
return {
username:'',
password:''
}
},
methods:{
handleClick(){
axios.post('http://127.0.0.1:8000/login/',{
username:this.username,
password:this.password
}).then(res=>{
// console.log(res.data) //{code: 100, msg: '登陆成功'}
if (res.data.code == 100){
location.href='https://www.baidu.com'
}else {
//失败
alert(res.data.msg)
}
})
}
}
}
</script>
<style scoped>
</style>
views.py-->django后端
from django.http import JsonResponse
import json
def login(request):
# print(request.body) # b'{"username":"nana","password":"123"}'
data = json.loads(request.body)
name = data.get('username')
pwd = data.get('password')
if name == 'nana' and pwd == '123':
return JsonResponse({'code':100,'msg':'登陆成功'})
else:
return JsonResponse({'code': 101, 'msg': '登陆失败'})
scoped
1.新建的组件加了scoped,表示样式只在当前组件生效,如果不加,子组件都会使用这个样式
<style scoped>
</style>
2.作用:让样式在局部生效,防止冲突。
ref属性
1.ref属性
1.放在普通标签上,通过 this.$refs.名字--->取到的是dom对象,可以直接操作dom
2.放在组件上,通过该this.$refs.名字--->取到的是组件对象,这样在父组件中,就拿到了子组件对象,对象属性和方法直接用即可
ref放在普通标签上
<template>
<div class = 'home '>
<h1>refs的使用---原生标签</h1>
<input type="text" v-model="name" ref="myinput">-->{{name}}
<p>
<img :src="img" alt="" height="300px" ref="myimg">
</p>
<p>
<button @click="handleClick">点我看控制台输出</button>
</p>
<hr>
<h1>refs的使用---组件</h1>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'HomeView',
data(){
return {
name:'',
img:'https://p2.itc.cn/images01/20210315/f7d1d8fe2aae4243bc5a800515c7a515.png'
}
},
methods:{
handleClick(){
console.log(this.$refs) //{myinput: input, myimg: img}
this.$refs.myinput.value='okk'
console.log(this.name) //nanan-->input框显示'okk'
}
}
}
</script>
<style>
</style>
ref放在组件上
HomeView.vue
<template>
<div class = 'home '>
<h1>refs的使用---组件</h1>
<HelloWorld :myname="name1" :myage="age" ref="myhello"></HelloWorld>
<button @click="handleClick1">点我看控制台输出</button>
</div>
</template>
<script>
import HelloWorld from "@/components/HelloWorld.vue";
export default {
name: 'HomeView',
data(){
return {
name1:'nana',
age:18
}
},
methods:{
handleClick1(){
console.log(this.$refs) //{myhello: VueComponent}
console.log(this.$refs.myhello) //VueComponent
console.log(this.$refs.myhello.hobby) //read
this.$refs.myhello.hobby='play'
}
},
components:{HelloWorld},
}
</script>
<style>
</style>
HelloWorld.vue
<template>
<div class="hello">
<h2>我是helloworld组件</h2>
<div>我的名字:{{myname}}</div>
<div>我的年龄:{{myage}}</div>
<div>我的爱好:{{hobby}}</div>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props:['myname','myage'],
data(){
return {
hobby:'read'
}
}
}
</script>
<style scoped>
</style>
props
props:父传子之自定义属性
1.功能:让组件接收外部传过来的数据
2.方式:
1.基本使用
props: ['msg'],
2.限制类型:
props: {'msg': Boolean},
3.限制类型,必填,默认值
props: {
msg: {
type: String, # 限制类型
required: true, # 限制必要性
default: '老王' # 指定默认值
}
}
混入mixin
1.包下的 index.js有特殊含义
-之前导入
import xx from './mixin/index.js'
-可以写成
import xx from './mixin'
ps:类似于包下面的__init__.py
2.mixin(混入)
功能:可以把多个组件共用的配置提取成一个混入对象
3.使用步骤
1.定义混入对象:mixin--->index.js中写
"""
export const lqz = {
data() {
return {
name: 'lqz'
}
},
methods: {
handleName() {
alert(this.name)
}
}
}
"""
2.使用混入:局部使用,组件中使用
import {lqz} from '@/mixin'
mixins: [lqz] # 注册混入
3.全局使用混入:每个组件都有效main.js中
import {lqz} from '@/mixin'
Vue.mixin(lqz)
背景
当有好几个页面,想使用相同的名字或者方法时,会出现代码冗余的情况
<template>
<div class = 'home '>
<h1>首页</h1>
<button @click="handleName">点我弹名字</button>
</div>
</template>
<script>
export default {
name: 'HomeView',
data(){
return {
name:'home'
}
},
methods:{
handleName(){
alert(this.name)
}
},
}
</script>
<style>
</style>
<template>
<div class="about">
<h1>about</h1>
<button @click="handleName">点我弹名字</button>
</div>
</template>
<script >
export default {
name:'AboutView',
data(){
return {
name:'about'
}
},
methods:{
handleName(){
alert(this.name)
}
},
}
</script>
使用mixin
局部使用
Mixin/index.js
export const ln={
data(){
return {
name:'ln'
}
},
methods:{
handleName(){
alert(this.name)
}
},
}
AboutView.vue
<template>
<div class="about">
<h1>about</h1>
<button @click="handleName">点我弹名字</button>
</div>
</template>
<script >
import {ln} from '@/mixin'
export default {
name:'AboutView',
data(){
return {
name:'about'
}
},
//注册混入
mixins:[ln]
}
</script>
HomeView.vue
<template>
<div class="about">
<h1>home</h1>
<button @click="handleName">点我弹名字</button>
</div>
</template>
<script >
import {ln} from '@/mixin'
export default {
name:'AboutView',
//注册混入
mixins:[ln]
}
</script>
全局使用
main.js
import {ln} from '@/mixin'
Vue.mixin(ln)
插件
1.插件功能:用于增强Vue,有很多第三方插件
(vuex,router,elemetui)
2.定义自己的插件
本质:包含install方法的一个对象,install的第一个参数是Vue,第二个以后的参数是插件使用者传递的数据
3.使用步骤:
1.定义插件:plugins--->index.js--->
export default {
install() {
# 1.在vue实例中放属性
# 2.定义混入,全局都可以使用混入
# 3.自定义指令(不讲了)--->以后我们可能使用了一个第三方插件,它提供了一些指令 v-lq
# 4.定义全局组件--->全局
}
}
2.在main.js中 使用插件
import lqz from '@/plugins'
Vue.use(lqz) # 这句话,就会执行lqz中得install,并且把vue传入
使用
定义插件
import Vue from "vue";
export default {
install(a) {
console.log('执行了插件', a)
// 定义指令
//定义全局指令:跟v-bind一样,获取焦点
Vue.directive("fbind", {
//指令与元素成功绑定时(一上来)
bind(element, binding) {
element.value = binding.value;
},
//指令所在元素被插入页面时
inserted(element, binding) {
element.focus();
},
//指令所在的模板被重新解析时
update(element, binding) {
element.value = binding.value;
},
});
//定义混入,所有vc和vm上都有name和lqz
Vue.mixin({
data() {
return {
name: '彭于晏',
age: 19,
};
},
});
// 原型上放方法,所有vc和vm都可以用hello
Vue.prototype.hello = () => {
alert("你好啊");
};
}
}
plugins/index.js
export default {
install(vue){
console.log('插件--->',vue) //是一个vue对象
}
}
main.js
import ln from '@/plugins'
Vue.use(ln) //这句话,就会执行lqz中得install,并且把vue传入
1.在vue实例中放属性
plugins/index.js
import Vue from 'vue'
import axios from "axios";
export default {
install(){
Vue.prototype.$ajax=axios
}
}
//等同于:在main.js中写以下代码:
ps:往vue的原型中放axios对象,以后再组件中this.$ajax拿到的就是这个axios对象,直接用即可
import axios from "axios";
Vue.prototype.$ajax=axios
HomeView.vue
<template>
<div class = 'home '>
<h1>首页</h1>
<button @click="handleClick">点我看控制台 </button>
</div>
</template>
<script>
export default {
name: 'HomeView',
methods:{
handleClick(){
this.$ajax.get('http://www.baidu.com').then(res=>{
})
}
}
}
</script>
<style>
</style>
2.定义混入,全局都可以使用混入
plugins/index.js
import Vue from 'vue'
import axios from "axios";
export default {
install(){
Vue.mixin({
data(){
return {
name:'nana',
age:18
}
},
})
}
}
HomeView.vue
<template>
<div class = 'home '>
<h1>首页</h1>
{{name}}-->{{age}}
<button @click="handleClick">点我看控制台 </button>
</div>
</template>
<script>
export default {
name: 'HomeView',
methods:{
handleClick(){
this.$ajax.get('http://www.baidu.com').then(res=>{
})
}
},
}
</script>
<style>
</style>
Elementui
1.ui 库,控制样式的,它就是vue的一个插件
2.在vue项目中引入 elementui
1 在项目中安装:
cnpm install element-ui -S
2.main.js配置
import ElementUI from 'element-ui'; # 把对象引入
import 'element-ui/lib/theme-chalk/index.css'; # 把样式引入
Vue.use(ElementUI)
3.看到好看的,直接复制
1.html
2.css
3.js
3.文档:https://element.eleme.cn/#/zh-CN/component/installation
补充
1.vue届的ui库
1.Element Plus - 经典中的经典,全面支持 Vue 3
2.Vant 3 - 有赞团队开源移动 UI 组件库,全面支持 Vue 3
https://vant-contrib.gitee.io/vant/#/zh-CN
3.TDesign - 鹅厂优质 UI 组件,配套工具完满,设计工整,文档清晰
4.Ant Design Vue - 阿里前端 UI 库,面向企业级中后台
5.iView:
作业
编写 首页,登录页面,注册页面
LoginView.vue
<template>
<div>
<h1>登陆页面</h1>
<div>用户名: <input type="text" v-model="username"></div>
<div>密码: <input type="password" v-model="password"></div>
<el-row>
<el-button type="success" plain @click="LoginClick">登陆</el-button>
</el-row>
</div>
</template>
<script>
export default {
data(){
return {
username:'',
password:'',
}
},
methods:{
LoginClick(){
this.$ajax.post('http://127.0.0.1:8000/login/',{
username:this.username,
password:this.password
}).then(res=>{
// console.log(res.data) {code: 100, msg: '登陆成功'}
if (res.data.code==100){
alert('登陆成功')
}else {
alert(res.data.msg)
}
})
}
}
}
</script>
<style scoped>
</style>
RegisterView.vue
<template>
<div>
<h1>注册页面</h1>
<div>用户名: <input type="text" v-model="username"></div>
<div>密码: <input type="password" v-model="password"></div>
<el-row>
<el-button type="success" plain @click="RegisterClick">注册</el-button>
</el-row>
</div>
</template>
<script>
export default {
name: "RegiesterView",
data(){
return {
username:'',
password:''
}
},
methods:{
RegisterClick(){
this.$ajax.post('http://127.0.0.1:8000/register/',{
username:this.username,
password:this.password
}).then(res=>{
// console.log(res.data) {code: 100, msg: '登陆成功'}
if (res.data.code==100){
alert('注册成功')
}else {
alert(res.data.msg)
}
})
}
}
}
</script>
<style scoped>
</style>
views.py
from rest_framework.viewsets import ViewSet
from .models import User
from rest_framework.response import Response
class LoginView(ViewSet):
def login(self,request):
print(request.data)
name = request.data.get('username')
password = request.data.get('password')
user_obj = User.objects.filter(username=name,password=password).first()
if not user_obj:
return Response({'code':101,'msg':'用户名或密码错误'})
else:
return Response({'code': 100, 'msg': '登陆成功'})
class RegisterView(ViewSet):
def register(self,request):
print(request.data)
name = request.data.get('username')
password = request.data.get('password')
user_obj = User.objects.filter(username=name).first()
if user_obj:
return Response({'code':101,'msg':'用户已经存在'})
user = User(username=name,password=password)
user.save()
return Response({'code': 100, 'msg': '注册成功'})