luffy项目前端

# 1.创建项目

# 1 vue.create luffy.city
# 2 删除一些不用的
	app.vue中只保留
	<template>
		<div id="app">

		<router-view/>
		</div>
	</template>
# HomeView.vue
	<template>
		  <div class="home">
			<h1>首页</h1>
		  </div>
		</template>

	<script>

		export default {
		  name: 'HomeView',

		}
	</script>

# router/index.js

	const routes = [
	  {
		path: '/',
		name: 'home',
		component: HomeView
	  },

]

2.安装axios

# 1.安装 cnpm install axios
# 2.main.js中配置
	//1.axios配置,配置完在组件中使用直接this.$axios即可
	import axios from 'axios'
	Vue.prototype.$axios = axios
# 3.使用this.$axios.get()

3.引入element-ui

//vue2使用elementui
//安装 cnpm install element-ui -S
//2.element-ui配置
	import ElementUI from 'element-ui'
	import 'element-ui/lib/theme-chalk/index.css'
	Vue.use(ElementUI)
//3.使用-->在任意组件中复制粘贴(template,script,style)

//vue3使用element-plus

4.引入vue-cookies

// 1.安装 cnpm install vue-cookies -S
// 2.配置main.js
	//vue-cookies配置
	import cookies from 'vue-cookies'
	Vue.prototype.$cookies = cookies
// 3使用this.$cookies.set()

5.前台全局样式和js配置

# body div 默认样式,统一去掉
# 写一个,应用到项目中


# 后端接口的地址,统一写,以后统一改

global.css

/* 声明全局样式和项目的初始化样式 */
body, h1, h2, h3, h4, h5, h6, p, table, tr, td, ul, li, a, form, input, select, option, textarea {
    margin: 0;
    padding: 0;
    font-size: 15px;
}

a {
    text-decoration: none;
    color: #333;
}

ul {
    list-style: none;
}

table {
    border-collapse: collapse; /* 合并边框 */
}


使用main.sj
//5.去掉所有标签样式
import '@/assets/css/global.css'

settings文件
将路径配置成全局配置创建settings文件

export default {
    BASE_URL:'http://127.0.0.1:8000/api/v1/'
}

使用
//6.导入全局配置
import settings from "@/assets/js/settings";
Vue.prototype.$settings = settings

6.引入jquery和bootstrap

下载---> cnpm install jquery
	cnpm install bootstrap@3
使用
import 'bootstrap'
import 'bootstrap/dist/css/bootstrap.min.css'
由于会冲突需要在config.js中配置
const webpack = require("webpack");

module.exports = {
    configureWebpack: {
        plugins: [
            new webpack.ProvidePlugin({
                $: "jquery",
                jQuery: "jquery",
                "window.jQuery": "jquery",
                "window.$": "jquery",
                Popper: ["popper.js", "default"]
            })
        ]
    }
};

7.编写前端组件

views.HomeView.vue页面组件

<template>
  <div class="home">

    <Header></Header>
    <Banner></Banner>
    <div class="course">
      <el-row>
        <el-col :span="6" v-for="(o, index) in 8" :key="o" class="course_detail">
          <el-card :body-style="{ padding: '0px' }">
            <img src="https://img1.baidu.com/it/u=2806336810,4108315549&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=666"
                 class="image">
            <div style="padding: 14px;">
              <span>好看的美女</span>
              <div class="bottom clearfix">
                <time class="time">价格999</time>
                <el-button type="text" class="button">查看美女联系</el-button>
              </div>
            </div>
          </el-card>
        </el-col>
      </el-row>
    </div>
    <div ><img src="https://img0.baidu.com/it/u=2527001186,1884851821&fm=253&fmt=auto&app=138&f=JPG?w=1295&h=500" alt=""
              style="padding-left: 28px"></div>
    <Footer></Footer>
    
    

  </div>
</template>

<script>
import Header from '@/components/Header'
import Banner from '@/components/Banner'
import Footer from '@/components/Footer'

export default {
  name: 'HomeView',
  data() {
    return{}
  },
  components: {
    Header, Banner, Footer
  }
}
</script>

<style scoped>
.time {
  font-size: 13px;
  color: #999;
}

.course_detail {
  padding: 50px;
}

.bottom {
  margin-top: 13px;
  line-height: 12px;
}

.button {
  padding: 0;
  float: right;
}

.image {
  width: 100%;
  display: block;
}

.clearfix:before,
.clearfix:after {
  display: table;
  content: "";
}

.clearfix:after {
  clear: both
}
</style>


局部组件

components.Bannser.vue 首页轮播图与后端数据接通

<template>
    <div class="banner">
      <el-carousel :interval="5000" arrow="always" height="400px">
        <el-carousel-item v-for="item in bannerList" :key="item.title">
          <div v-if="item.image.indexOf('http')==-1">
            <router-link :to="item.link"><img :src="item.image" alt=""></router-link>
          </div>
          <div v-else>
            <a :href="item.link"><img :src="item.image" alt=""></a>
          </div>
  
        </el-carousel-item>
      </el-carousel>
  
    </div>
  
  </template>
  
  <script>
  export default {
    name: "Banner",
    data() {
      return {
        bannerList: []
      }
    },
    created() {
      this.$axios.get(this.$settings.BASE_URL + 'home/banner/').then(res => {
        this.bannerList = res.data.result
        console.log(this.bannerList)
      })
    }
  }
  </script>
  
  <style scoped>
  .el-carousel__item {
    height: 400px;
    min-width: 1200px;
  }
  
  .el-carousel__item img {
    height: 400px;
    margin-left: calc(50% - 1920px / 2);
  }
  
  .el-carousel__item h3 {
    color: #475669;
    font-size: 18px;
    opacity: 0.75;
    line-height: 300px;
    margin: 0;
  }
  
  .el-carousel__item:nth-child(2n) {
    background-color: #99a9bf;
  }
  
  .el-carousel__item:nth-child(2n+1) {
    background-color: #d3dce6;
  }
  </style>

components.header.vue

<template>
  <div class="header">
    <div class="slogan">
      <p>老男孩IT教育 | 帮助有志向的年轻人通过努力学习获得体面的工作和生活</p>
    </div>
    <div class="nav">
      <ul class="left-part">
        <li class="logo">
          <router-link to="/">
            <img src="../assets/img/luffy_city.jpg" alt="" style="width: 48px;height:48px">
          </router-link>
        </li>
        <li class="ele">
          <span @click="goPage('/free-course')" :class="{active: url_path === '/free-course'}">免费课</span>
        </li>
        <li class="ele">
          <span @click="goPage('/actual-course')" :class="{ active: url_path === '/actual-course' }">实战课</span>
        </li>
        <li class="ele">
          <span @click="goPage('/light-course')" :class="{ active: url_path === '/light-course' }">轻课</span>
        </li>
      </ul>

      <div class="right-part">
        <div v-if="!username">
          <span @click="put_login">登录</span>
          <span class="line">|</span>
          <span @click="put_register">注册</span>
        </div>
        <div v-else>
          <span><img :src="this.$cookies.get('icon') " alt="" style="width: 48px;height:48px;margin: 10px;" @click="goicon"></span>
          <span>{{username}}</span>
          <span class="line">|</span>
          <span @click="logout">注销</span>
        </div>
        <Login v-if="is_login" @close="close_login" @go="put_register"></Login>
        <Register v-if="is_register" @close="close_register" @go="put_login"></Register>
        <Icon v-if="is_icon" @close="close_icon"></Icon>
      </div>
    </div>
  </div>

</template>
  
<script>
import Login from '@/components/Login.vue'
import Register from '@/components/Register.vue'
import Icon from '@/components/Icon.vue'
export default {
  name: "Header",
  data() {
    return {
      url_path: sessionStorage.url_path || '/',
      is_login: false,
      is_register: false,
      is_icon:false,
      username:'',
      
    }
  },
  methods: {

    goPage(url_path) {
      // 已经是当前路由就没有必要重新跳转
      if (this.url_path !== url_path) {
        // 传入的参数,如果不等于当前路径,就跳转
        this.$router.push(url_path)
      }
      sessionStorage.url_path = url_path;
    },
    //跳转登陆关闭注册
    put_login() {
      this.is_login = true;
      this.is_register = false;
    },
    //跳转注册关闭登陆
    put_register() {
      this.is_login = false;
      this.is_register = true;
    },
    //关闭登陆
    close_login() {
      this.is_login = false;
      this.username=this.$cookies.get('username')

    },
    //关闭注册
    close_register() {
      this.is_register = false;
    },
    //注销功能 删除本地cookies和将用户名置空即可
    logout(){
      this.$cookies.remove('username')
      this.$cookies.remove('token')
      this.$cookies.remove('icon')
      this.username=''
    },
    //打开头像框查看
    goicon(){this.is_icon = true;},
    close_icon(){this.is_icon = !this.is_icon}

  }, components: { Login, Register ,Icon}
  ,
  created() {
    sessionStorage.url_path = this.$route.path
    this.url_path = this.$route.path
    //取出cookies中的username提供给组件判断是否有值有值显示用户名和注销
    this.username=this.$cookies.get('username')
  }
}
</script>
  
<style scoped>
.header {
  background-color: white;
  box-shadow: 0 0 5px 0 #aaa;
}

.header:after {
  content: "";
  display: block;
  clear: both;
}

.slogan {
  background-color: #eee;
  height: 40px;
}

.slogan p {
  width: 1200px;
  margin: 0 auto;
  color: #aaa;
  font-size: 13px;
  line-height: 40px;
}

.nav {
  background-color: white;
  user-select: none;
  width: 1200px;
  margin: 0 auto;

}

.nav ul {
  padding: 15px 0;
  float: left;
}

.nav ul:after {
  clear: both;
  content: '';
  display: block;
}

.nav ul li {
  float: left;
}

.logo {
  margin-right: 20px;

}

.ele {
  margin: 0 20px;
}

.ele span {
  display: block;
  font: 15px/36px '微软雅黑';
  border-bottom: 2px solid transparent;
  cursor: pointer;
}

.ele span:hover {
  border-bottom-color: orange;
}

.ele span.active {
  color: orange;
  border-bottom-color: orange;
}

.right-part {
  float: right;
}

.right-part .line {
  margin: 0 10px;
}

.right-part span {
  line-height: 68px;
  cursor: pointer;
}
</style>

首页中间样式的添加

使用element组件使用element组件

<template>
  <div class="home">
    <Header></Header>
    <Banner></Banner>
    <div class="course">
      <el-row>
        <el-col :span="6" v-for="(o, index) in 8" :key="o" class="course_detail">
          <el-card :body-style="{ padding: '0px' }">
            <img src="https://img1.baidu.com/it/u=2806336810,4108315549&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=666"
                 class="image">
            <div style="padding: 14px;">
              <span>好看的美女</span>
              <div class="bottom clearfix">
                <time class="time">价格999</time>
                <el-button type="text" class="button">查看美女联系</el-button>
              </div>
            </div>
          </el-card>
        </el-col>
      </el-row>
    </div>
    <div ><img src="https://img0.baidu.com/it/u=2527001186,1884851821&fm=253&fmt=auto&app=138&f=JPG?w=1295&h=500" alt=""
              style="padding-left: 28px"></div>
    <Footer></Footer>
  </div>
</template>

<script>
import Header from '@/components/Header'
import Banner from '@/components/Banner'
import Footer from '@/components/Footer'

export default {
  name: 'HomeView',
  data() {
    return {}
  },
  components: {
    Header, Banner, Footer
  }
}
</script>

<style scoped>
.time {
  font-size: 13px;
  color: #999;
}

.course_detail {
  padding: 50px;
}

.bottom {
  margin-top: 13px;
  line-height: 12px;
}

.button {
  padding: 0;
  float: right;
}

.image {
  width: 100%;
  display: block;
}

.clearfix:before,
.clearfix:after {
  display: table;
  content: "";
}

.clearfix:after {
  clear: both
}
</style>

8.登陆注册功能设计编写

image

# 1账号密码手机号登陆
# 2 手机验证码登陆
# 3发送手机验证码
# 4 注册手机验证码
# 5 创建登陆组件和注册功能组件
# 6 在头部组件中绑定号点击事件一点击就显示登陆和注册功能,两个只有一个会显示可以切换,两个组件都是全局的默认是不显示,点击就显示
# 7 在登陆组件中写点击事件朝后端服务器发请求
# 8 通过后端返回的数据判断是否登陆成功

components.Login.vue

<template>
    <div class="login">
        <div class="box">
            <i class="el-icon-close" @click="close_login"></i>
            <div class="content">
                <div class="nav">
                    <span :class="{ active: login_method === 'is_pwd' }"
                        @click="change_login_method('is_pwd')">密码登录</span>
                    <span :class="{ active: login_method === 'is_sms' }"
                        @click="change_login_method('is_sms')">短信登录</span>
                </div>
                <el-form v-if="login_method === 'is_pwd'">
                    <el-input placeholder="用户名/手机号/邮箱" prefix-icon="el-icon-user" v-model="username" clearable>
                    </el-input>
                    <el-input placeholder="密码" prefix-icon="el-icon-key" v-model="password" clearable show-password>
                    </el-input>
                    <el-button type="primary" @click="usernamelogin">登录</el-button>
                </el-form>
                <el-form v-if="login_method === 'is_sms'">
                    <el-input placeholder="手机号" prefix-icon="el-icon-phone-outline" v-model="mobile" clearable
                        @blur="check_mobile">
                    </el-input>
                    <el-input placeholder="验证码" prefix-icon="el-icon-chat-line-round" v-model="sms" clearable>
                        <template slot="append">
                            <span class="sms" @click="send_sms">{{ sms_interval }}</span>
                        </template>
                    </el-input>
                    <el-button type="primary" @click="mobilelogin">登录</el-button>
                </el-form>
                <div class="foot">
                    <span @click="go_register">立即注册</span>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
export default {
    name: "Login",
    data() {
        return {
            username: '',
            password: '',
            mobile: '',
            sms: '',
            login_method: 'is_pwd',
            sms_interval: '获取验证码',
            is_send: false,

        }
    },
    methods: {
        close_login() {
            this.$emit('close')
        },
        go_register() {
            this.$emit('go')
        },
        change_login_method(method) {
            this.login_method = method;
        },
        check_mobile() {
            if (!this.mobile) return;
            if (!this.mobile.match(/^1[3-9][0-9]{9}$/)) {
                this.$message({
                    message: '手机号有误',
                    type: 'warning',
                    duration: 1000,
                    onClose: () => {
                        this.mobile = '';
                    }
                });
                return false;
            }
            this.is_send = true;
        },
        send_sms() {

            if (!this.is_send) return;
            this.is_send = false;
            let sms_interval_time = 60;
            this.sms_interval = "发送中...";
            this.$axios.post('http://127.0.0.1:8000/api/v1/user/user/send_sms/', { mobile: this.mobile }).then(response => {
                console.log(response.data)
                if (response.data.code !== 100) { this.$message.warning(response.data.msg) }
            })
            let timer = setInterval(() => {
                if (sms_interval_time <= 1) {
                    clearInterval(timer);
                    this.sms_interval = "获取验证码";
                    this.is_send = true; // 重新回复点击发送功能的条件
                } else {
                    sms_interval_time -= 1;
                    this.sms_interval = `${sms_interval_time}秒后再发`;
                }
            }, 1000);
        }

        ,
        //用户密码登陆功能
        usernamelogin() {
            //用户名或密码为空弹警告信息并结束函数
            if (!this.username | !this.password) {
                this.$message.warning('用户名和密码不能为空')
                return
            }
            //发送登陆请求
            this.$axios.post('http://127.0.0.1:8000/api/v1/user/user/login/', { username: this.username, password: this.password }).then(response => {

                if (response.data.code == 100) {
                    //登陆成功将用户头像token存到本地
                    //销毁登陆组件
                    console.log(response.data)
                    this.$cookies.set('token', response.data.token)
                    this.$cookies.set('icon', response.data.icon)
                    this.$cookies.set('username', response.data.username)
                    this.$emit('close')
                } else {
                    this.$message.error(response.data.msg)
                }

            })
        },
        //手机验证码登陆功
        mobilelogin() {
            if (!this.mobile && !this.sms) {
                this.$message.error('手机号和验证码不能为空')
                return
            }



            this.$axios.post('http://127.0.0.1:8000/api/v1/user/user/mobile_login/', { mobile: this.mobile, code: this.sms }).then(response => {

                if (response.data.code == 100) {
                    //登陆成功将用户头像token存到本地
                    //销毁登陆组件
                    console.log(response.data)
                    this.$cookies.set('token', response.data.token)
                    this.$cookies.set('icon', response.data.icon)
                    this.$cookies.set('username', response.data.username)
                    this.$emit('close')
                } else {
                    this.$message.error(response.data.msg)
                }

            })
        }
    }
}
</script>

<style scoped>
.login {
    width: 100vw;
    height: 100vh;
    position: fixed;
    top: 0;
    left: 0;
    z-index: 10;
    background-color: rgba(0, 0, 0, 0.3);
}

.box {
    width: 400px;
    height: 420px;
    background-color: white;
    border-radius: 10px;
    position: relative;
    top: calc(50vh - 210px);
    left: calc(50vw - 200px);
}

.el-icon-close {
    position: absolute;
    font-weight: bold;
    font-size: 20px;
    top: 10px;
    right: 10px;
    cursor: pointer;
}

.el-icon-close:hover {
    color: darkred;
}

.content {
    position: absolute;
    top: 40px;
    width: 280px;
    left: 60px;
}

.nav {
    font-size: 20px;
    height: 38px;
    border-bottom: 2px solid darkgrey;
}

.nav>span {
    margin: 0 20px 0 35px;
    color: darkgrey;
    user-select: none;
    cursor: pointer;
    padding-bottom: 10px;
    border-bottom: 2px solid darkgrey;
}

.nav>span.active {
    color: black;
    border-bottom: 3px solid black;
    padding-bottom: 9px;
}

.el-input,
.el-button {
    margin-top: 40px;
}

.el-button {
    width: 100%;
    font-size: 18px;
}

.foot>span {
    float: right;
    margin-top: 20px;
    color: orange;
    cursor: pointer;
}

.sms {
    color: orange;
    cursor: pointer;
    display: inline-block;
    width: 70px;
    text-align: center;
    user-select: none;
}
</style>

components.Register.vue

<template>
    <div class="register">
        <div class="box">
            <i class="el-icon-close" @click="close_register"></i>
            <div class="content">
                <div class="nav">
                    <span class="active">新用户注册</span>
                </div>
                <el-form>
                    <el-input placeholder="手机号" prefix-icon="el-icon-phone-outline" v-model="mobile" clearable
                        @blur="check_mobile">
                    </el-input>
                    <el-input placeholder="密码" prefix-icon="el-icon-key" v-model="password" clearable show-password>
                    </el-input>
                    <el-input placeholder="验证码" prefix-icon="el-icon-chat-line-round" v-model="sms" clearable>
                        <template slot="append">
                            <span class="sms" @click="send_sms">{{ sms_interval }}</span>
                        </template>
                    </el-input>
                    <el-button type="primary" @click="mobileregister">注册</el-button>
                </el-form>

                <div class="foot">
                    <span @click="go_login">立即登录</span>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
export default {
    name: "Register",
    data() {
        return {
            mobile: '',
            password: '',
            sms: '',
            sms_interval: '获取验证码',
            is_send: false,
        }
    },
    methods: {
        //关闭注册组件
        close_register() {
            this.$emit('close', false)
        },
        //前往登陆
        go_login() {
            this.$emit('go')
        },
        //校验手机号是否注册
        check_mobile() {
            if (!this.mobile) return;
            if (!this.mobile.match(/^1[3-9][0-9]{9}$/)) {
                this.$message({
                    message: '手机号有误',
                    type: 'warning',
                    duration: 1000,
                    onClose: () => {
                        this.mobile = '';
                    }
                });
                return false;
            }
            //判断手机号是否存在失去焦点立刻发送请求校验手机号是否存在
            this.$axios.get('http://127.0.0.1:8000/api/v1/user/user/getmobile/?mobile=' + this.mobile).then(response => {
                if (response.data.code == 100) {
                    this.$message({
                        message: '手机号已注册,请前往登陆',
                        type: 'error'
                    });
                    this.mobile = ''
                    return
                }
            })
            this.is_send = true;
        },
        // 发送短信功能
        send_sms() {
            if (!this.is_send) return;
            this.is_send = false;
            let sms_interval_time = 60;
            this.sms_interval = "发送中...";
            this.$axios.post('http://127.0.0.1:8000/api/v1/user/user/send_sms/', { mobile: this.mobile }).then(response => { if (response.data.code !== 100) { this.$message.warning(response.data.msg) } })
            let timer = setInterval(() => {
                if (sms_interval_time <= 1) {
                    clearInterval(timer);
                    this.sms_interval = "获取验证码";
                    this.is_send = true; // 重新回复点击发送功能的条件
                } else {
                    sms_interval_time -= 1;
                    this.sms_interval = `${sms_interval_time}秒后再发`;
                }
            }, 1000);
        },
        //用户注册功能
        mobileregister() {
            if (!this.mobile) {
                this.$message.error('手机号忘填了')
                return
            }
            if (!this.password) {
                this.$message.error('密码不能为空')
                return
            }
            if (!this.sms) {
                this.$message.error('验证码不能为空')
                return
            }
            this.$axios.post('http://127.0.0.1:8000/api/v1/user/user/register/', { mobile: this.mobile, password: this.password, code: this.sms }).then(response => {

                if (response.data.code == 100) {
                    this.$emit('go')//注册成功触发登陆事件直接跳转
                } else {
                    this.$message.error(response.data.msg)  //失败弹出失败提示
                }

            })

        }
    }
}
</script>

<style scoped>
.register {
    width: 100vw;
    height: 100vh;
    position: fixed;
    top: 0;
    left: 0;
    z-index: 10;
    background-color: rgba(0, 0, 0, 0.3);
}

.box {
    width: 400px;
    height: 480px;
    background-color: white;
    border-radius: 10px;
    position: relative;
    top: calc(50vh - 240px);
    left: calc(50vw - 200px);
}

.el-icon-close {
    position: absolute;
    font-weight: bold;
    font-size: 20px;
    top: 10px;
    right: 10px;
    cursor: pointer;
}

.el-icon-close:hover {
    color: darkred;
}

.content {
    position: absolute;
    top: 40px;
    width: 280px;
    left: 60px;
}

.nav {
    font-size: 20px;
    height: 38px;
    border-bottom: 2px solid darkgrey;
}

.nav>span {
    margin-left: 90px;
    color: darkgrey;
    user-select: none;
    cursor: pointer;
    padding-bottom: 10px;
    border-bottom: 2px solid darkgrey;
}

.nav>span.active {
    color: black;
    border-bottom: 3px solid black;
    padding-bottom: 9px;
}

.el-input,
.el-button {
    margin-top: 40px;
}

.el-button {
    width: 100%;
    font-size: 18px;
}

.foot>span {
    float: right;
    margin-top: 20px;
    color: orange;
    cursor: pointer;
}

.sms {
    color: orange;
    cursor: pointer;
    display: inline-block;
    width: 70px;
    text-align: center;
    user-select: none;
}
</style>

components.icom.vue

<template>
    <div class="login">
        <div class="box">
            <i class="el-icon-close" @click="close_icon"></i>
            <img class="img" :src="this.$cookies.get('icon')" alt="">

        </div>
    </div>
</template>

<script>
export default {
    name: "Icon",
    methods: {
        close_icon() {
            this.$emit('close')
        },
    }
}
</script>

<style scoped>
.login {
    width: 100vw;
    height: 100vh;
    position: fixed;
    top: 0;
    left: 0;
    z-index: 10;
    background-color: rgba(0, 0, 0, 0.3);
}

.box {
    width: 400px;
    height: 420px;
    background-color: white;
    border-radius: 10px;
    position: relative;
    top: calc(50vh - 210px);
    left: calc(50vw - 200px);
}
.el-icon-close {
    position: absolute;
    font-weight: bold;
    font-size: 20px;
    top: 10px;
    right: 10px;
    cursor: pointer;
    color:rgb(#888888);
}

.img {
    width: 400px;
    height: 420px;
}
</style>
posted @ 2022-11-23 22:53  懒羊羊A  阅读(30)  评论(0)    收藏  举报