资源免费提供,欢迎访问!
官方中文api:https://vuejs.bootcss.com/guide/
创建基础文件:index.html、style.css、app.js
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="https://cdn.jsdelivr.net/npm/vue">script>
<title>Vuetitle>
head>
<body>
<div id="vue-app">
<h1>{
{ name }}h1>
<p>{
{ greet("name") }}p>
<p>
<a :href="website">跳转a>
p>
<p v-html="websiteTag">
p>
div>
body>
<script src="app.js">script>
html>
注意:
用于加载vue
//—
{ { name }}
{ { greet("name") }}
//实例化vue对象
new Vue({
el: "#vue-app", //elemenr,注入一个容器
data() {
//返回容器的对象
return {
name: "Tommy",
echat: "20",
website: "https://www.baidu.com",
websiteTag: '跳转'
}
},
methods: {
// // 第一个中写法,准备一个方法
// greet: function () {
// return "Good night " + this.name;
// }
//第二种写法,准备一个方法
greet(time) {
//使用反引号,使用变量都得用${}
return `Good ${
time} ${
this.name}`;
}
},
})
注意:
el: “#vue-app”, //elemenr,注入一个容器
后只能在这个容器里获取防护ide值
暂时没有用到
new Vue({
el: "#vue-app",
data() {
return {
age: 10,
x: 0,
y: 0
}
},
methods: {
// 准备一个加一的方法
add(v) {
this.age += v;
},
subtract(v) {
this.age -= v;
},
// 改变鼠标获取xy
updateXY(event) {
//这里注意调用该方法不能写成updateXY(),他会误以为你没有给参数,得写成updateXY
this.x = event.offsetX;
this.y = event.offsetY;
},
// 监听键盘按下的方法
dow() {
alert("你按下了键盘后并且按了alt键+enter键")
}
},
})
注意方法里调用属性值,使用this.属性名
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="https://cdn.jsdelivr.net/npm/vue">script>
<link rel="stylesheet" href="sytle.css">
<title>dome02title>
head>
<body>
<div id="vue-app">
<p>
我的年龄 {
{ age }}
p>
<button @click.once="subtract(1)">减一年button>
<button v-on:click="add(1)">加一年button>
<div id="mainDiv" v-on:mousemove="updateXY">
x:{
{ x }},y:{
{ y }}
div>
<input type="text" placeholder="输入名字" @keydown.atl.enter="dow()">
div>
<script src="app.js">script>
body>
html>
注意:
事件绑定 v-on:,简写为@
调用mousemove方法不能updateXY(),
.once得一些修饰符,下面有说到
@keydown.atl.enter:
keydown:监听按下键盘
.alt.enter:按下alt键+enter键触发方法
#mainDiv {
width: 300px;
height: 300px;
border: 1px solid sienna;
text-align: center;
}
.stop
- 调用 event.stopPropagation()
。.prevent
- 调用 event.preventDefault()
。.capture
- 添加事件侦听器时使用 capture 模式。.self
- 只当事件是从侦听器绑定的元素本身触发时才触发回调。.{keyCode | keyAlias}
- 只当事件是从特定键触发时才触发回调。.native
- 监听组件根元素的原生事件。.once
- 只触发一次回调。.left
- (2.2.0) 只当点击鼠标左键时触发。.right
- (2.2.0) 只当点击鼠标右键时触发。.middle
- (2.2.0) 只当点击鼠标中键时触发。.passive
- (2.3.0) 以 { passive: true }
模式添加侦听器new Vue({
el: "#vue-app",
data() {
return {
name: "",
age: ""
}
},
methods: {
getAge() {
//这里使用$refs获取传入的对象age里的value并赋给属性age,也能实现双向数据绑定
this.age = this.$refs.age.value;
}
},
// watch是用来监听属性只改变,只建议用来使用调式代码.
watch: {
age(v, o) {
console.log("age的改变:新值:" + v + ",原始值:" + o);
}
},
})
注意:
&refs:获取ref传入的对象
watch是用来监听属性只改变,只建议用来使用调式代码.
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="https://cdn.jsdelivr.net/npm/vue">script>
<title>dome03title>
head>
<body>
<div id="vue-app">
<input type="text" v-model="name">
<p>
{
{ name }}
p>
<input type="text" ref="age" @keydown="getAge()">
<p>
{
{ age }}
p>
div>
<script src="app.js">script>
body>
html>
注意:
使用v-model来实现双向数据绑定,一般只在:input,select,textarea。
使用ref和$refs获取对象也能实现双向数据。
v-model的修饰符
v-model.lazy 只有在input输入框发生一个blur时才触发
v-model.trim 将用户输入的前后的空格去掉
v-model.number 将用户输入的字符串转换成number
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.jsdelivr.net/npm/vue">script>
<title>dome04title>
head>
<body>
<div id="vue-app">
<button @click="a++">Add abutton>
<button @click="b++">Add bbutton>
<p>A:{
{ a }}p>
<p>B:{
{ b }}p>
<p>age+A :{
{ addA }}p>
<p>age+B :{
{ addB }}p>
div>
<script src="app.js">script>
body>
html>
注意:
调用computed方法不能带有();
new Vue({
el: "#vue-app",
data() {
return {
a: 0,
b: 0,
age: 0
}
},
// methods: { //methods只要数据发生改变就回调用
// addA() {
// console.log("执行了addA");
// // return this.a + this.age;
// },
// addB() {
// console.log("执行了addB");
// // return this.b + this.age;
// }
// },
computed: {
//computed属于计算属性,只有调用该方法才会执行
//但每个方法一定有返回值
addA() {
console.log("执行了addA");
return this.a + this.age;
},
addB() {
console.log("执行了addB");
return this.b + this.age;
}
},
})
注意:
如果使用methods只要属性有改变方法,将会全部调用。
computed调用时一定有返回值。
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.jsdelivr.net/npm/vue">script>
<title>dome05title>
<link rel="stylesheet" href="sytle.css">
head>
<body>
<div id="vue-app">
<button :class="btSytle" @click="isColor=!isColor">修改样式button>
div>
<script src="app.js">script>
body>
html>
注意:
:class绑定样式,使用isColor改变属性值
new Vue({
el: "#vue-app",
data() {
return {
isColor: false
}
},
// 一般动态改变样式,使用计算属性方法
computed: {
//准备改变属性的计算属性方法
btSytle() {
return {
bt1: this.isColor
};
}
},
})
注意:
一般改变样式都使用计算属性方法。
btSytle返回一个class对象绑定 {样式名(id,class,Tag):属性值}
.bt1 {
background: wheat;
}
.bt2 {
background: red;
}
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.jsdelivr.net/npm/vue">script>
<title>dome06title>
head>
<body>
<div id="app-vue">
条件1 <button @click="isShow=!isShow">{
{ isShow }}button>
条件2 <button @click="isShow2=!isShow2">{
{ isShow2 }}button>
<p v-if="isShow">
显示if
p>
<p v-else-if="isShow2">
显示else if
p>
<p v-else>
显示else
p>
<p v-show="isShow">
显示v-show
p>
div>
<script src="app.js">script>
body>
html>
注意:
v-if与v-show的区别:
v-if:直接把标签去掉删掉
v-show:display: none;隐藏
new Vue({
el: "#app-vue",
data() {
return {
isShow: false,
isShow2: true
}
},
})
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.jsdelivr.net/npm/vue">script>
<title>dome07title>
head>
<body>
<div id="app-vue">
<div v-for="(user,index) in users">
<p>
{
{ index }}名字{
{ user.name }}年龄:{
{ user.age }}
p>
div>
<hr>
<template v-for="user in users">
<template v-for="(val,key) in user">
<p>
key:{
{ key }},val:{
{ val }}
p>
template>
template>
div>
<script src="app.js">script>
body>
html>
注意:
div与template容器使用v-for的区别:
div会遍历容器,template只遍历内容
v-for遍历对象(val,key)顺序不能改
new Vue({
el: "#app-vue",
data() {
return {
users: [{
name: "小米",
age: 16
},
{
name: "小明",
age: 20
},
{
name: "小猪",
age: 19
},
{
name: "小王",
age: 18
},
]
}
},
})
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.jsdelivr.net/npm/vue">script>
<title>dome09title>
head>
<body>
<div id="app-vue1">
<p>
{
{ title }}
p>
<p>
<Greeting>Greeting>
p>
div>
<div id="app-vue2">
{
{ title }}
<p>
{
{ getApp2 }}
p>
div>
<script src="app.js">script>
body>
html>
注意:
调用全局控件:
// 全局变量
let data = {
name: "名字",
}
// 全局控件
Vue.component("Greeting", {
//html模板
template: "全局控件取全局变量:{
{ data.name }}
",
//也可返回一个对象
data() {
return {
}
}
})
const vue1 = new Vue({
el: "#app-vue1",
data() {
return {
title: "第一个标题"
}
},
methods: {
},
})
new Vue({
el: "#app-vue2",
data() {
return {
title: "第二个标题"
}
},
computed: {
getApp2() {
return vue1.title;
}
}
})
注意:
全局变量定义在外面即可.
全局控件定义时给名,并在template里写入模板.
在容器app2想调用app1中的属性值,得实例化app1,并直接用实例化名"."点出来。
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.jsdelivr.net/npm/vue">script>
<script src="https://unpkg.com/axios/dist/axios.min.js">script>
<title>dome10title>
head>
<body>
<div id="app-vue">
fetch <button @click="getFetch()">使用get获取数据button>
<button @click="postFetch()">使用post获取数据button><br>
axios <button @click="getAxios()">获取get数据button> <button @click="postAxios()">获取post数据button>
div>
<script src="app.js">script>
body>
html>
注意:
使用axios必须添加cdn:
//
new Vue({
el: "#app-vue",
data() {
return {
todo: {
title: "",
completed: false
}
}
},
methods: {
getFetch() {
//使用fetch获取数据
const l = fetch("https://api.ooopn.com/yan/api.php")
.then((res) => {
return res.json(); //返回一个json数据
})
.then((res) => {
console.log(res); //获取json数据
})
.catch((e) => {
//请求失败
console.log("请求失败")
})
},
postFetch() {
//使用post访问
fetch("http://jsonplaceholder.typicode.com/posts", {
method: "POST",
body: JSON.stringify(this.todo),
headers: {
"Content-type": "application/json"
}
}).then((res) => {
return res.json();
}).then((res) => {
console.log(res)
}).catch((e) => {
console.log("请求失败")
})
},
// 使用axios
getAxios() {
axios.get("https://api.ooopn.com/yan/api.php")
.then((res) => {
console.log(res.data);
})
.catch((e) => {
console.log("请求失败!")
})
},
postAxios() {
axios.post("http://jsonplaceholder.typicode.com/posts", this.todo)
.then((res) => {
console.log(res.data);
})
.catch((e) => {
console.log("请求失败!")
})
}
},
})
注意:
Fetch:
get:第一个then负责返回一个json数据,后面的then才是对象
post:在bodyl里添加json对象参数,headers负责指定类型,catch里请求失败的回调
axios:
get:无需那么复杂直接.get第一个then里返回的数据.data就是对象,catch请求失败的回调
post:无需那么复杂直接.post第二个参数就是json对象参数,然后then返回的数据.data就是对象了,catch请求失败的回调.
下载nodejs:https://nodejs.org/en/
安装node.js后在cmd里使用命令下载VUE脚手架
检查node.js安装是否成功
node -v
npmm -v
在cmd里使用命令下载vue/cli 3一定要3
npm install -g @vue/cli
注意:如果下载较慢配置改错taobao镜像国内的就快了
npm config set registry https://registry.npm.taobao.org --global
npm config set disturl https://npm.taobao.org/dist --global
检测:
vue --versoin
npm.taobao.org/网站里:
npm install -g cnpm --registry=https://registry.npm.taobao.org
检测:
cnpm --version
vue create vuecli-demo(vuecli-demo是项目名)
选中:Manually select features(手动创建)
选中:Babel (按空格选择)
选中:In package.json(管理我们用的包)
输入:n不是模板名,使用自己的名字。
进入项目
cd 项目名/
启动项目:
npm run serve
module.exports = {
root: true,
env: {
node: true
},
extends: [
'plugin:vue/essential',
//'@vue/standard'
],
parserOptions: {
parser: 'babel-eslint'
},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
}
}
注意:
删掉’@vue/standard’即可。
进入ui图形化操作模式
vue ui
创建项目:点击项目–选择好路径创建即可。
第一次可以选择手动
选择Choose Vue versin、Babel、Router(其他的看需求)
去掉(Linter/Formatter)代码严谨
创建项目
运行项目:任务 serve运行即可。
安装插件:点击插件-----添加插件搜搜安装后配置即可—重写运行。
全是命令行
# vuecli-demo01
## Project setup
```
npm install //安装项目的依赖包
```
### Compiles and hot-reloads for development
```
npm run serve //启动项目并编译
```
### Compiles and minifies for production
```
npm run build //对项目打包
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).
{
"name": "vuecli-demo01",
"version": "0.1.0",
"private": true,
//当前项目的启动方式:serve可以修改,但修改后npm run 修改后的值
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build"
},
//项目依赖
"dependencies": {
"core-js": "^3.6.4",
"vue": "^2.6.11"
},
//项目插件
"devDependencies": {
"@vue/cli-plugin-babel": "~4.2.0",
"@vue/cli-service": "~4.2.0",
"vue-template-compiler": "^2.6.11"
},
"browserslist": [
"> 1%",
"last 2 versions"
]
}
项目提供
//对vue处理
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
忽略文件,为了更好的提交重要文件。
public文件夹
favicon.icon
网站图标
index.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">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %>title>
head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.strong>
noscript>
<div id="app">div>
body>
html>
主页:
vue容器
node_modules
所有插件存放的地方。
注意:
收到别人项目,或发给别人项目,是没有node_modules文件的。
需要自己使用命令通过package.json提供参数下载回来:
cnpm install
sec文件夹
assets文件夹:静态文件,css,js…
components文件夹:包含的都是组件
<template>
<div class="hello">
<h1>{
{ msg }}h1>
<p>
For a guide and recipes on how to configure / customize this project,<br>
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentationa>.
p>
<h3>Installed CLI Pluginsh3>
<ul>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babela>li>
ul>
<h3>Essential Linksh3>
<ul>
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docsa>li>
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Foruma>li>
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chata>li>
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twittera>li>
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">Newsa>li>
ul>
<h3>Ecosystemh3>
<ul>
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-routera>li>
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuexa>li>
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtoolsa>li>
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loadera>li>
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vuea>li>
ul>
div>
template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
script>
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
style>
App.vue:根组件
main.js:逻辑入口点
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
注意:
vue先入index其次进入main.js
.$mount(’#app’):最后放再#app容器中
{
{ msg }}
遍历数组
{
{ user }}
注意:
遍历数组一定得加key值而且是唯一的。
import Vue from 'vue'
import App from './App.vue'
// 注册全局组件
// 1.引入组件
import Users from './components/Users'
// 2.注册全局组件
Vue.component("users", Users)
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
Hello组件
Users组件
{
{title}}
{
{ msg }}
遍历数组
名字:{
{ user.name }}
年龄:{
{ user.age }}
{
{footer}}
Users组件
{
{ msg }}
遍历数组
{
{ user }}
在style里写一个scoped标志值在当前页面使用,一般都这样使用。
如果不加可能会只要导入的都使用了。
Users组件
注意:
App.vue中准备数据users,
引用组件时绑定数据
:users=“users”,users可以随便取赋值给的是值
{
{ msg }}
遍历数组
名字:{
{ user.name }}
年龄:{
{ user.age }}
注意:
传入的strnig 、number、boolean都是传入值。
传入的array、object都是引用的。
值:修改哪个值,哪个值会变。
引用:引用的是指针对象,修改一个全部都修改。
{
{title}}
methods: {
btTitle(){
// 在这里如果要修改父容器的值,得注册事件修改
// this.title = "修改"//这样直接修改会报错
this.$emit("titleUpdata","通过注册事件修改后的值"); //这样修改父容器的值就不会错了。
}
},
添加修改title的事件
methods: {
updateTitle(title){
this.title = title;
}
},
使用注册的事件:titleUpdata
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rZBwMK61-1590412890570)(E:\Typora_text\images\vue1.png)]
export default {
name: 'HelloWorld',
data() {
return {
title:"Vue Componrnts Demo"
}
},
// 测试生命周期
beforeCreate() {
alert("进入了beforeCreate了,data还没实例化。")
},
created() {
alert("进入了creaed了,实例化了data了")
},
beforeMount() {
alert("进入了beforeMount了,页面准备挂载还没显示")
},
mounted() {
alert("进入了mounted了,页面已经显示了。")
},
beforeUpdate() {
alert("进入了beforeUpdate了,页面准备刷新数据和页面。")
},
updated() {
alert("进入了updated了,页面数据和页面刷新完毕。")
},
beforeDestroy() {
alert("进入了beforeDestroy了,页面准备销毁")
},
destroyed() {
alert("进入了destroyed了,页面销毁完毕。")
},
}
{
{title}}
注意:
内容可以指定slot,也可以不指定。
{
{title}}
注意
slot可以理解占位,如果没有name,它会把父类引用里的全部显示。
slot的样式问题:无论在父类还是子类都能获取元素
slot的获取值问题:它只能获取父类的data里的值
Fragment1:
Fragment1:
{
{title}}
Users组件
注意:
components通过:is引入组件,但引入的组件有个缓存的问题。如果你切换组件,输入框的内容降消失。
加上keep-alive后就是添加了缓存机制。
添加模板:
vue create 项目名
选中Manually select fatures
使用空格选中你需要的插件
选中需要的:我—ESLint + Standard config等等
选择 Lint on save保存 刚的选择
选择In dedicated config files
选择y设置为模板,输入你的模板名
删除模板:
win在用户文件夹里找到.vuerc文件删除需要删除的即可,保存
添加:
vue add 插件
选择默认,然后默认
你执行npm run serve时,对应的环境就是开发环境;
你执行npm run build时,对应的环境就是生产环境。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WhRM0yE1-1590412890572)(E:\Typora_text\images\vue2.png)]
设置启动模式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-88XwoPal-1590412890573)(E:\Typora_text\images\vue3.png)]
VUE_APP_URL=http://localhost:8080
这里我们使用开发环境
{
{ url }}
注意:
添加新得env文件一定得重启vue
通过data实例化出url使用process.env.VUE_APP_URL获取env里得值。
引用url即可。
首先添加全局启动插件
npm install -g @vue/cli-service-global
启动即可:
vue serve Test.vue(vue界面)
进入ui图形化操作模式
vue ui
创建项目:点击项目–选择好路径创建即可。
运行项目:任务 serve运行即可。
安装插件:点击插件-----添加插件搜搜安装后配置即可—重写运行。
module.exports = {
"transpileDependencies": [
"vuetify"
],
//这个是4.0后写法
publicPath: process.env.NODE_ENV === 'production' ?
'./' : '/', //访问目录
outputDir: "dist2", //打包后输出得目录名:npm run build
assetsDir: "assets", //静态资源目录(js,css,img,fonts)
lintOnSave: false, //是否eslint保存检测,有效值:true||false||error
// 网络配置
devServer: {
open: true, //在运行自动打开浏览器
host: "localhost", //主机号
port: 8081, //端口号
https: false, //是否以https模式启动
hotOnly: false, //热更新(启动)
//跨域配置:暂时不报错:When `proxy` in package.json is an object, each `context` object must have a `target` property specified as a url string
// proxy: {
// '/api': {
// target: 'http://www.baidu.com/',
// pathRewrite: {
// '^/api': ''
// },
// changeOrigin: true, // target是域名的话,需要这个参数,
// secure: false, // 设置支持https协议的代理
// },
// '/api2': {
// "api": "api"
// }
// }
}
把项目做处理(删除没必要的文件与代码)。
初始化文件:git init
查看添加状态:git status
修改配置:
添加文件:git add .
提交文件:git commit -m “描述”
推送远程仓库:
import Vue from 'vue'
import VueRouter from 'vue-router'
import Login from '../components/Login.vue'
Vue.use(VueRouter)
const routes = [
//访问
{
path: '/login',
component: Login
},
//重置-/*dcv.binojpkl[]/\*
{
path: "/",
redirect: "/login"
}
]
const router = new VueRouter({
routes
})
export default router
import Vue from 'vue'
import {
Button
} from 'element-ui'
import {
Form,
FormItem
} from 'element-ui'
import {
Input
} from 'element-ui'
Vue.use(Button)
Vue.use(Form)
Vue.use(FormItem)
Vue.use(Input)
<template>
<div class="login_mainDiv">
<div class="login_center">
<div class="login_topImg">
<img src="../assets/logo.png" />
div>
<el-form class="login_form">
<el-form-item label-width="0px">
<el-input>el-input>
el-form-item>
<el-form-item label-width="0px">
<el-input>el-input>
el-form-item>
<el-form-item class="loginBts">
<el-button type="primary">登陆el-button>
<el-button type="info">重置el-button>
el-form-item>
el-form>
div>
div>
template>
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import './plugins/element.js'
// 导入全局的Css
import './assets/css/mainCss.css'
// 导入配置axios
import axios from 'axios'
axios.defaults.baseURL = "https://v1.hitokoto.cn/" //给axios配置访问头
Vue.prototype.$http = axios //给vue的http配置访问头
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App)
}).$mount('#app')
注意:
我们测试访问头设置头https://v1.hitokoto.cn/
import Vue from 'vue'
import {
Button
} from 'element-ui'
import {
Form,
FormItem
} from 'element-ui'
import {
Input
} from 'element-ui'
// 导入el的弹窗
import {
Message
} from 'element-ui'
Vue.use(Button)
Vue.use(Form)
Vue.use(FormItem)
Vue.use(Input)
// 全局挂载el的弹窗
Vue.prototype.$message = Message;
注意:
Vue.prototype. m e s s a g e = M e s s a g e ; 全 局 挂 载 , 后 可 以 使 用 t h i s . message = Message;全局挂载,后可以使用this. message=Message;全局挂载,后可以使用this.message直接调用里的方法
登陆
重置
注意:
我们使用的是el-模式特别注意表单的结构。
使用$refs就可以获取表单了,然后调用表单里的方法。
本次测试const res = await this.$http.get("", this.loginForm);没有访问尾,只要访问通过就算登陆成功
//登陆成功给seesionStorage里存入值以来验证是否登陆过
window.sessionStorage.setItem("isLogin", this.loginForm.user);
//并跳转页面
this.$router.push({ path: "/home" });
注意:
sessionStorage用来验证是否登陆,一般服务器给。
this.$router.push进行跳转
一定设置路由,一定把App.vue里设置视图
注意:
在这里不能直接写组件,写上即可
之后使用路由来跳转。
import Vue from 'vue'
import VueRouter from 'vue-router'
import Login from '@/components/Login.vue'
import Home from '@/components/Home.vue'
Vue.use(VueRouter)
const routes = [
// 登陆
{
path: '/login',
name: 'login',
component: Login,
meta: {
title: '登录页'
},
},
{
path: '/',
redirect: "/login",
component: Login,
meta: {
title: '登录页'
},
},
// 主页
// 登陆
{
path: '/home',
name: 'home',
component: Home,
meta: {
title: '主页'
},
},
]
const router = new VueRouter({
routes
})
export default router
注意:
这是vuecli4的写法
@是转换
import Vue from 'vue'
import VueRouter from 'vue-router'
import Login from '@/components/Login.vue'
import Home from '@/components/Home.vue'
Vue.use(VueRouter)
const routes = [
// 登陆
{
path: '/login',
name: 'login',
component: Login,
meta: {
title: '登录页'
},
},
{
path: '/',
redirect: "/login",
component: Login,
meta: {
title: '登录页'
},
},
// 主页
// 登陆
{
path: '/home',
name: 'home',
component: Home,
meta: {
title: '主页'
},
},
]
const router = new VueRouter({
routes
})
//路由权限跳转
router.beforeEach((to, from, next) => {
//to 将要访问的路径
//from 代表哪个路径访问来的,
//next 是一个函数:next()放行,next("/xx")强制跳转
if (to.path == "/login") {
next(); //如果是登陆界面就放行
return;
}
//获取sesstion里的值
const sesstion = window.sessionStorage.getItem("isLogin");
console.log(sesstion)
if (sesstion == null) {
next("/login"); //如果是空就强制跳转到login页
alert("请登陆后重试!")
} else
next(); //否则直接放行
})
export default router
注意:
beforeEach方法是router专门做访问权限的。
to 将要访问的路径
from 代表哪个路径访问来的,
next 是一个函数:next()放行,next("/xx")强制跳转
axios.interceptors.request.use(config=>{
//为请求头对象,添加token验证
config.headers.Authorization = window.sessionStorage.getIntem("isLogin");
return config;
})
注意:
在调用axios之前回调用interceptors.request.use。
在之前我们提交一个Authorization
写在main.js里
home 页面
退出用户
注意:
window.sessionStorage.clear(); //清空sessionStorage
this.$router.push("/login"); //跳转访问
查看分支:git branch
查看提交状态:git status
添加: git add .
提交: git commit -m “提交描述”
切换回master主分支:git checkout master
合并: git merge login(分支名)
上传:git push(这个是第二次上传可以这样简写)
把login分支推送github:git push -u origin login(云端的分支名)
新建一个.prettierrc
{
"semi":false, //取消双引号
"singleQuote":true //使用单引号
}
注意:
如果又语法规则错误,在.eslintrc.js里的rules对象里添加保存的规则赋值为0取消规则
列:
{
‘xxxx’:0
}
我们使用element-ui
自己在src里创建一个plugic文件夹里的element.js
最后的到main.js里导入文件夹。
import Vue from 'vue'
import {
Button,
Form,
FormItem,
Input,
Message,
Container,
Header,
Aside,
Main
} from 'element-ui'
Vue.use(Button)
Vue.use(Form)
Vue.use(FormItem)
Vue.use(Input)
Vue.use(Container)
Vue.use(Header)
Vue.use(Aside)
Vue.use(Main)
// 全局挂载el的弹窗
Vue.prototype.$message = Message;
电商平台
退出
Aside
Main
注意:
我们使用的element样式编写的架构。
justify-content样式使用:
flex-start 默认值。项目位于容器的开头。 flex-end 项目位于容器的结尾。 center 项目位于容器的中心。 space-between 项目位于各行之间留有空白的容器内。 space-around 项目位于各行之前、之间、之后都留有空白的容器内。 initial 设置该属性为它的默认值。请参阅 initial。 inherit 从父元素继承该属性。请参阅 inherit。
import Vue from 'vue'
import {
Button,
Form,
FormItem,
Input,
Message,
Container,
Header,
Aside,
Main,
Menu,
Submenu,
MenuItem
} from 'element-ui'
Vue.use(Button)
Vue.use(Form)
Vue.use(FormItem)
Vue.use(Input)
Vue.use(Container)
Vue.use(Header)
Vue.use(Aside)
Vue.use(Main)
Vue.use(Menu)
Vue.use(Submenu)
Vue.use(MenuItem)
// 全局挂载el的弹窗
Vue.prototype.$message = Message;
电商平台
退出
|||
{
{ item.authName}}
{
{ chiItem.name }}
Main
注意:
slot="title"时element里的样式,不加则看不到文字效果.
这里我们模拟自己数据。
我们拿数据进行for来渲染布局:这里只要注意使用对象的遍历。
el-menu特别属性
- background-color:菜单项的背景
- text-color:菜单项文字颜色
- active-text-color:菜单项文件点击后的颜色
- unique-opened:只能打开一个菜单项
- collapse:是否收起,使用默认是false没有收起,ture收起
- collapse-transition:是否开启折叠动画
import welcome from '@/components/Welcome.vue'
{
path: '/home',
name: 'home',
component: Home,
meta: {
title: '主页'
},
//home的子路由
children: [{
path: "/welcome",
component: welcome
}],
redirect: "/welcome" //刚进入home发送/welcome
},
//---------
//------------
{
id: 0,
authName: "用户管理",
children: [{ id: "0-1", name: "用户列表", path: "/users" }],
icon: "el-icon-user-solid"
},
//-----------
注意:
default-active:给的值就是激活高亮的菜单项
@click=“onMenu = chiItem.path”:点击后把onMenu赋值
首页
用户管理
用户列表
添加用户
注意:
使用el的分栏
row里:gutter:是col之间的距离,
col里:span是栅格占据的列数,列添加el表格
tbale的:data:是绑定数据对象,border添加边框线,stripe隔行变色
comlumn的是头标签,prop:是绑定data对象里的属性,如果设置 这里的slot-scope是获取当前对象的值scope.row就是值得对象
使用scope.row点出想要获取当前数据对象的属性
//--------------------------
//在data()里添加,自定义校验数据
// 自定义数据验证规则:邮箱
var checkEmail = (rule, value, ch) => {
// 正则验证邮箱
const reg = /^([\.a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-])+/
if (reg.test(value)) {
//合法邮箱
return ch()
}
ch(new Error("请输入合法的邮箱!"))
}
// 自定义数据验证规则:手机
var checkPhone = (rule, value, ch) => {
// 正则验证手机
const reg = /^[1][3,4,5,7,8,9][0-9]{9}$/
if (reg.test(value)) {
//合法手机
return ch()
}
ch(new Error("请输入合法的手机!"))
}
//准备数据
addFormRules: {
//添加数据对象,的检测数据
name: [
{
required: true,
message: "请输入用户名",
trigger: "blur"
},
{ min: 3, max: 10, message: "用户名长度:3-10字符", trigger: "blur" }
],
pwd: [
{
required: true,
message: "请输入用户密码",
trigger: "blur"
},
{ min: 6, max: 15, message: "用户密码长度:6-15字符", trigger: "blur" }
],
email: [
{
required: true,
message: "请输入用户邮箱",
trigger: "blur"
},
{
validator: checkEmail,
trigger: "blur"
}
],
// 调用自定义的数据校验:
//validator指定校验的对象,trigger:焦点触发
phone: [
{
required: true,
message: "请输入用户手机",
trigger: "blur"
},
{
validator: checkPhone,
trigger: "blur"
}
]
}
}
注意:
点击添加的对话框!
dialog里title:提示标题,:visible.sync是否打开对话框,width:宽度
表单区
form里:model绑定数据,rules:数据检测对象,ref:添加后的对象传入ref
formItem里label:是输入框开头文字,prop:是传入rules对象的属性,@close:是关闭后的回调(这里不需要)
MessageBox
Vue.prototype.$confirm = MessageBox.confirm;
//删除用户方法
deleteUser(data) {
// 点击el的是否弹出框:type指定小图标的样式
//返回值是promise可以使用.then来获取或asyns+await
this.$confirm("此操作将永久删除该用户, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
// 点击确定的时候,如果发生错误,他会自动执行catch
.then(() => {
this.FUserList.splice(data.id, 1)
this.$message({
type: "success",
message: "删除成功!"
})
})
//点击取消
.catch(() => {
this.$message({
type: "info",
message: "已取消删除"
})
})
}
注意:
点击el的是否弹出框:type指定小图标的样式
返回值是promise可以使用.then来获取或asyns+await点击确定的时候,如果发生错误,他会自动执行catch
添加路由
Rights.vue
首页
权限管理
权限列表
一级权限
二级权限
三级权限
注意:
操作差不多
//----
//分配权限
getAllRole() {
this.isRoles = true
},
alloRights() {
this.isRoles = false
let s = ""
// getCheckedNodes是tree里的方法,获取选中节点的id
for (let i = 0; i < this.$refs.treeRef.getCheckedNodes().length; i++) {
s += this.$refs.treeRef.getCheckedNodes()[i].$treeNodeId + ","
}
this.$message.success(s)
}
注意:
tree的使用
show-checkbox:是否可选择,data:数据,props显示的对象
treProps: { label: “name”, chidren: “chidren” },
default-expand-all:默认展开所有节点
node-key:指定每个节点的唯一id
default-expanded-keys:默认显示勾选节点,提供一个数组即可获取选中节点的id
this.$refs.treeRef.getCheckedNodes()
一级
二级
三级
编辑
删除
注意:
//导入插件:vue-table-with-tree-grid
import TreeTable from 'vue-table-with-tree-grid’
//注册:vue-table-with-tree-grid
Vue.component(“tree-table”, TreeTable)
表格:vue-table-with-tree-grid的插件:https://github.com/MisterTaki/vue-table-with-tree-grid
data:绑定数据,
columns:绑定列的数据,
selection-type:是否显示复选框
expand-type:是否位展开行,注意展开与分组是不一样的
show-index:是否显示数据索引,index-text:数据索引的名称
boder:是否显示竖向边框级联选择器
options:数据源 ,
@change:选中发生变化得回调
Props:{
label指定选项标签为选项对象的某个属性值
value指定选项的值为选项对象的某个属性值
children指定选项的子选项为选项对象的某个属性值
expandTrigger:触发
}
clearable:是否支持清空
change-on-select:是否可以选中一级级联
…后面都是控件技术省略
打包:可以在ui里运行build包,也可以运行命令:npm run build
操作后会导出一个dist文件(项目文件)
这就代表打包成功
运行:在dist文件同级目录创建一个app.js文件
//导入express const express = require('express') const app = express() //托管的静态资源 app.use(express.static('./dist')) app.listen(80, () => { console.log("服务器启动成功!:http://127.0.0.1") })
在该目录初始化node
npm init -y
安装express插件管理项目
npm i express -S
最后启动项目
node .\app.js
插件名:transform-remove-console
在babeLconfig.js里可以判断是否打包运行然后加入插件
无论是element组件还是echart插件都可以使用导入.
具体百度
懒加载:可以减少加载控件的压力,需要哪个控件就记载哪个。
1:安装开发依赖@babel/plugin-syntax-dynamic-import
2:babel.config.js中声明插件
3:将路由改为这种加载格式:
const Foo = () => import(/* webpackchunkName: “group-foo” */ ‘./Foo.vue’)
(Foot是名称,import里/里是分组/,‘里是组件’)文档:参考链接:https://router.vuejs.org/zh/guide/advanced/lazy-loading.html
app.js中导入插件:const compression = require(‘comression’) app.use(compression)
----进入https://fressl.cn官网,选择域名与品牌
----输入自己的邮箱并选择相关选择
----验证dns(在域名管理后台添加TXT记录)
----验证通过后,下载SSL证书(full_chain.pem公钥;prvate.key私钥)
const https = require('https')
const fs = require('fs')
const options={
cret:'fs.readFileSync('./full_chain.pem')',key:'fs.readFileSync('./private.key')'}
https.createServer(optoins,app).listen(443)
pm2:关闭运行终端依旧可以运行项目
----安装插件 npm i pm2 -g
----pm2 start 脚本(./app.js) --name 自定义启动项目名
----查看所有运行项目:pm2 ls
----重启项目:pm2 restart 自定义名称
----停止项目:pm2 stop 自定义名称
----删除项目:pm2 delete 自定义名称
//const API_PROXY = 'https://bird.ioliu.cn/v1/?url=' //代理接口
"https://bird.ioliu.cn/v1/?url=" +接口 //拼接即可
ns:数据源 ,
@change:选中发生变化得回调
Props:{
label指定选项标签为选项对象的某个属性值
value指定选项的值为选项对象的某个属性值
children指定选项的子选项为选项对象的某个属性值
expandTrigger:触发
}
clearable:是否支持清空
change-on-select:是否可以选中一级级联
–>
:options=“cateData”
:props="{ expandTrigger: ‘hover’,label:‘name’,checkStrictly: true }"
@change=“cateChange”
clearable
>
> 注意:
>
> **//导入插件:vue-table-with-tree-grid**
>
> **import TreeTable from 'vue-table-with-tree-grid'**
>
> **//注册:vue-table-with-tree-grid**
>
> **Vue.component("tree-table", TreeTable)**
>
> 表格:vue-table-with-tree-grid的插件:https://github.com/MisterTaki/vue-table-with-tree-grid
> data:绑定数据,
> columns:绑定列的数据,
> selection-type:是否显示复选框
> expand-type:是否位展开行,注意展开与分组是不一样的
> show-index:是否显示数据索引,index-text:数据索引的名称
> boder:是否显示竖向边框
>
> 级联选择器
> options:数据源 ,
> @change:选中发生变化得回调
> Props:{
> label指定选项标签为选项对象的某个属性值
> value指定选项的值为选项对象的某个属性值
> children指定选项的子选项为选项对象的某个属性值
> expandTrigger:触发
> }
> clearable:是否支持清空
> change-on-select:是否可以选中一级级联
....后面都是控件技术省略
### 4、项目的打包与优化。
#### 4.1、打build包并运行项目
> 打包:可以在ui里运行build包,也可以运行命令:npm run build
>
> 操作后会导出一个dist文件(项目文件)
>
> 这就代表打包成功
>
> 运行:在dist文件同级目录创建一个app.js文件
>
> ```java
> //导入express
> const express = require('express')
> const app = express()
> //托管的静态资源
> app.use(express.static('./dist'))
> app.listen(80, () => {
> console.log("服务器启动成功!:http://127.0.0.1")
> })
> ```
>
> 在该目录初始化node
>
> npm init -y
>
> 安装express插件管理项目
>
> npm i express -S
>
> 最后启动项目
>
> node .\app.js
#### 4.2、优化项目
##### 4.2.1、打包后去掉console打印
> 插件名:transform-remove-console
>
> 在babeLconfig.js里可以判断是否打包运行然后加入插件
##### 4.2.2、使用externals减少打包后文件大小
> 无论是element组件还是echart插件都可以使用导入.
>
> 具体百度
##### 4.2.3、设置路由懒加载
> 懒加载:可以减少加载控件的压力,需要哪个控件就记载哪个。
>
> 1:安装开发依赖@babel/plugin-syntax-dynamic-import
>
> 2:babel.config.js中声明插件
>
> 3:将路由改为这种加载格式:
>
> const Foo = () => import(/* webpackchunkName: "group-foo" */ './Foo.vue')
> (Foot是名称,import里/*里是分组*/,'里是组件')
>
> 文档:参考链接:https://router.vuejs.org/zh/guide/advanced/lazy-loading.html
##### 4.2.4、compressoin 减少传输文件的大小
> app.js中导入插件:const compression = require('comression') app.use(compression)
##### 4.2.5、以https启动项目
+ 申请SSL证书
> ----进入https://fressl.cn官网,选择域名与品牌
> ----输入自己的邮箱并选择相关选择
> ----验证dns(在域名管理后台添加TXT记录)
> ----验证通过后,下载SSL证书(full_chain.pem公钥;prvate.key私钥)
+ 导入整数并启动https服务器
```js
const https = require('https')
const fs = require('fs')
const options={cret:'fs.readFileSync('./full_chain.pem')',key:'fs.readFileSync('./private.key')'}
https.createServer(optoins,app).listen(443)
pm2:关闭运行终端依旧可以运行项目
----安装插件 npm i pm2 -g
----pm2 start 脚本(./app.js) --name 自定义启动项目名
----查看所有运行项目:pm2 ls
----重启项目:pm2 restart 自定义名称
----停止项目:pm2 stop 自定义名称
----删除项目:pm2 delete 自定义名称
//const API_PROXY = 'https://bird.ioliu.cn/v1/?url=' //代理接口
"https://bird.ioliu.cn/v1/?url=" +接口 //拼接即可