Vue入门

Vue入门,第1张

Vue:前后端分离

构建用户界面的渐进式框架,自底向上逐层应用

soc:关注度分离原则

MVVM:双向数据绑定

第一个Vue程序

官方教程Vue.js (vuejs.org)

理解成是一个不停监听页面的ajax

idea需要安装Vue.js插件

安装 — Vue.js (vuejs.org)

Vue在线cdn

<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>

放在head中的JS代码会在页面加载完成之前就读取,

而放在body中的JS代码,会在整个页面加载完成之后读取

DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Titletitle>
head>
<body>
  
  <div id="vue">
    {{message}}
  div>

  <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js">script>
  <script>
      <!-- ViewModel层 -->
      var vue = new Vue({
        			<!--键值之间 必须有空格,就像yml的语法一样 -->
        			<!--绑定id为vue的元素 -->
              el: "#vue",
              data: {
                  <!-- Model层 -->
                  message: "Hello Vue!"
              }
          })
  script>

body>
html>

基本语法

Vue.js 模板语法 | 菜鸟教程 (runoob.com)

所有的属性写法,全部都是key-value键值对,用yml的语法思想来理解vue

v-bind

属性绑定vue数据指令

v-bind:“message” 相当于{{message}}

<div id="vue">
  <span v-bind:title="message">
    鼠标悬停后,可看到message的信息
  span>
div>

导入链接

DOCTYPE html><html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml">

判断

<div id="vue">
  <span v-if="message === 'A'">Aspan>
  <span v-else-if="message === 'B'">Bspan>
  <span v-else>Cspan>
div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js">script>
<script>
  let vue = new Vue({
    el: "#vue",
    data: {
      message: "D"
    }
  })
script>
循环
<div id="vue">
  
  <li v-for="(item,index) in items">
    {{item}}
  li>
div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js">script>
<script>
  let vue = new Vue({
    el: "#vue",
    data: {
      items: ["java", "html", "mysql", "redis"]
    }
  })
script>

<li v-for="(item,index) in items">
  {{item}} -- {{index}}
li>

变种

<div id="vue">
  <span v-for="item in items">
    {{item.message}}
  span>
div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js">script>
<script>
  let vue = new Vue({
    el: "#vue",
    data: {
      items: [
        {message: "java"},
        {message: "html"},
        {message: "mysql"},
        {message: "redis"}
      ]
    }
  })
script>

java--0
html--1
mysql--2
redis--3

v-model双向数据绑定

从此开始,vue.js的引入放入了head中

<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js">script>

head>

vue会忽略checked,select的值,只取vue的data中的值

<div id="vue">
  
  <select v-model="items">
    <option disabled>请选择option>
    <option>1option>
    <option>2option>
    <option>3option>
  select>

  <span>选中了{{items}}span>

div>

<script>
  let vue = new Vue({
    el: "#vue",
    data: {
      items: ""
    }
  })
script>


methods事件
<div id="vue">
  
  <button value="点我一下" v-on:click="test">button>
div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js">script>
<script>
  let vue = new Vue({
    el: "#vue",
    data: {
      items: ["java", "html", "mysql", "redis"]
    },
    methods: {
      test: function (){
        <!--取值vue data中的items-->
          for (let item in this.$data.items) {
            alert(item)
          }
      }//test
    }//method
  })
script>
computed计算属性

computed把结果缓存成一个值

<div id="vue">
  
  <span>computed:{{getTime}}span>
  <span>methods:{{getTime1()}}span>

div>

<script>
  let vue = new Vue({
    el: "#vue",
    //computed把结果缓存成一个值,全部都能被methods替代
    computed: {
      getTime() {
        return "时间戳" + Date.now();
      }
    },
    //当重名时,默认调用methods
    methods: {
      getTime1: function () {
        return Date.now();
      }
    }

  })
script>

在控制台可以看到,computed是将值缓存到了本地

vue.getTime
'时间戳1652064179289'
  
//不刷新页面,多次运行,结果一样
vue.getTime
'时间戳1652064179289'



vue.getTime1()
1652064259827

//methods会刷新数据
vue.getTime1()
1652064266181

Axios异步通信框架

在线cdn

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

Vue - 生命周期详解 - 简书 (jianshu.com)

info中的格式:可以不写,但不要写错

<div id="vue">
  <span>城市:{{info.address.city}}span>
  <a :href="info.url">网址a>
div>

<script>
  let vue = new Vue({
    el: "#vue",
    //该函数返回组件实例的 data 对象
    data(){
      return {
        info: {
          //数值可以不写,但是格式必须相同
          url: null,
          address: {
            city: null
          }
        }
      }
    },
    //vue数据挂载html模板完成后,做ajax的钩子函数,只会执行一次
    mounted(){
      //get实例:用response.data读取文件中的果断json数据,响应给info属性
      axios.get("data/data.json").then(response=>(this.info = response.data));
    }
  })
script>

前端页面闪烁的问题解决方案


Vue.component组件

props中的属性名不能大写

<div id="vue">
  
  <child v-for="item in items" v-bind:children="item">child>
div>

<script>
  //组件名,组件实体
  Vue.component("child",{
    //传参
    props: ['children'],
    //模板
    /**
     * html标签及其中内容 最后都会变成小写
     * 但是vue区分大小写
     */
    template: "{{children}}"
  })

  let vue = new Vue({
    el: "#vue",
    data: {
      items: ["java","mysql","html"]
    }
  })
script>
插槽
<div id="vue">

  <child>
    <slot1 slot="slot1" v-for="item in items" :item="item">slot1>
    <slot2 slot="slot2" v-for="(item,index) in items" :index="index">slot2>
  child>
div>

<script>
  Vue.component("child",{
    template: "\
\
\
  "
  })

  //插槽1接收item数据
  Vue.component("slot1",{
    props: ['item'],
    template: "元素:{{item}}---"
  })

  //插槽2接收index数据
  Vue.component("slot2",{
    props: ['index'],
    template: "索引:{{index}}"
  })


  let vue = new Vue({
    el: "#vue",
    data: {
      items: ["java","mysql","html"]
    }
  })
script>
事件分发

实现功能:插槽中有个按纽,可以删除元素,但是删除的却是Vue实例中的对象元素

根据双向绑定原则,用前端来中介Vue实例和组件间的互相调用

vue.js中this.$emit的理解

<div id="vue">

  
  
  <father v-on:test="removeItem(index)">

    <child slot="child" v-for="(item,index) in items" :index="index">child>
  father>
div>

<script>

  Vue.component("father",{
    //@click:绑定vue的点击单击监听
    template: "\
								\
								\
  						 \
							",
    methods: {
    remove: function (index){
    /**
     把remove事件分发下去,传递参数index
     当remove执行时,子级就会告知父级:触发自定义事件test,也就是Vue实例中的removeItem事件
     */
    this.$emit("test",index);
  }

  }

  })

  Vue.component("child",{
    props: ['index'],
    template: "{{index}}"
  });

  let vue = new Vue({
    el: "#vue",
    data: {
      items: ["java","mysql","html"]
    },
    methods: {
      removeItem: function (index){
        //从index位开始删除,一次删除一位
        //可以增,删,改
        this.$data.items.splice(index,1);
      }
    }

  })
script>

splice使用https://blog.csdn.net/qq_44921114/article/details/108608851


Vue-cli(脚手架)

node.js 理解成maven

使用阿里定制的cnpm命令行工具代替默认的npm,输入以下代码

安装成功之后,以后安装依赖包的方式和npm的是一样的,只是npm的命令换成是cnpm就可以了。

 npm install -g cnpm --registry=https://registry.npm.taobao.org

检查是否安装成功:

 $ cnpm -v

C:\Users\林木\AppData\Roaming\npm 包存放路径

出错了话,node.js会告诉怎么解决,直接执行他告诉你的代码就行

vue list查看可以用的包

安装vue-cli

第一个vue-cli程序

npm ERR! enoent ENOENT: no such file or directory, open ‘D:\package.json‘


Webpack静态模块打包器

异步加载模块,可以并行加载多个模块

理解成:把es6规范的前端项目,打包成es5规范

VUE-CLI Webpack安装使用

第一个webpack程序

新建一个只有.idea的空项目

hello.js相当于java自定义类

//暴露一个sayHi方法给外界
exports.sayHi = function () {
    //到时会在页面上写字
    document.write("Hello webpack!");
}

main.js程序主入口

//在当前目录下引入hello.js
var hello = require("./hello");
hello.sayHi();

webpack.config.js:主配置文件,webpack4.0后文件名要是webpack.config.js

//把模块导出去
module.exports = {
    //入口:从哪里读取
    entry: "./modules/main.js",
    //输出到哪里
    output: {
        filename: "./js/bundle.js"
    }
}

控制台运行 webpack 打包,然后会自动生成一个dist目录

测试页面引入生成的js文件,就是相当于引入hello.js

<script src="dist/js/bundle.js">script>

webpack : 无法加载文件 D:\nodejs\node_global\webpack.ps1,因为在此系统上禁止运行脚本

ERROR in Entry module not found: Error: Can’t resolve ‘./src’ in XXX的一个解决方案

webpack --watch热部署


Vue-router

理解成**@RequestMapping**

VueRouter路由安装使用

安装vue-router,保存到dev环境下,也就是config目录下

cnpm install vue-router --save-dev

在一个vue项目下

自定义组件

Content.vue

<template>
<h1>Hello Vue-Router!This is my first VueContent.h1>
template>

<script>
//导出一个组件,名叫Content,也相当于命名当前组件为Content
export default {
  name: "Content"
}
script>


<style scoped>

style>

Main.vue

<template>
  <h1>Hello Vue-Router!h1>
template>

<script>
export default {
  name: "Main"
}
script>

<style scoped>

style>

官方习惯把各种配置文件都叫index.js

router目录下的index.js

//导入文件和模块(从node_modules中导入),名字随意
import Vue from "vue"
import VueRouter from "vue-router"
import Main from "../components/Main"
import Content from "../components/Content";

//上面的Vue实例安装路由(添加插件)
Vue.use(VueRouter)

//将路由实例化并导出
export default new VueRouter({
  routes: [
    {
      //地址栏输入路径后,将跳转到Content组件
      path: "/content",
      name: "Content",
      component: Content
    },
    {
      path: "/main",
      component: Main
    }
  ]
})

main.js Vue项目的主配置文件

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'

//自动扫描目录下的index.js文件
import router from './router/index'

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',

  //使用路由,也相当于导入所有路由
  router,
  components: { App },
  template: ''
})

App.vue 项目的主界面

<template>
  <div id="app">

    
    
    <router-link to="/main">首页router-link>
    <router-link to="/content">内容页router-link>

    
    <router-view>router-view>
  div>

template>

<script>

export default {
  name: 'App'
}
script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
style>

npm run dev 运行打包项目

VueRouter报错:Uncaught TypeError: Object(…) is not a function


整合ElementUI

//安装element-ui
cnpm i element-ui -S

//安装依赖
cnpm install

//安装SASS加载器( 强化 CSS 的辅助工具 ,强化CSS功能)
cnpm install sass-loader node-sass --save-dev

npm run dev

去element-ui官网,复制他们的代码

ElementLogin.vue(自定义登录组件)

<template>
  <div>
    <el-form ref="loginForm" :model="form" :rules="rules" label-width="80px" class="login-box">
      <h3 class="login-title">欢迎登录h3>
      <el-form-item label="账号" prop="username">
        <el-input type="text" placeholder="请输入账号" v-model="form.username"/>
      el-form-item>
      <el-form-item label="密码" prop="password">
        <el-input type="password" placeholder="请输入密码" v-model="form.password"/>
      el-form-item>
      <el-form-item>
        <el-button type="primary" v-on:click="onSubmit('loginForm')">登录el-button>
      el-form-item>
    el-form>

    <el-dialog
        title="温馨提示"
        :visible.sync="dialogVisible"
        width="30%"
        :before-close="handleClose">
      <span>请输入账号和密码span>
      <span slot="footer" class="dialog-footer">
        <el-button type="primary" @click="dialogVisible = false">确 定el-button>
      span>
    el-dialog>
  div>
template>

<script>
export default {
  name: "Login",
  data() {
    return {
      form: {
        username: '',
        password: ''
      },

      // 表单验证,需要在 el-form-item 元素中增加 prop 属性
      rules: {
        username: [
          {required: true, message: '账号不可为空', trigger: 'blur'}
        ],
        password: [
          {required: true, message: '密码不可为空', trigger: 'blur'}
        ]
      },

      // 对话框显示和隐藏
      dialogVisible: false
    }
  },
  methods: {
    onSubmit(formName) {
      // 为表单绑定验证功能
      this.$refs[formName].validate((valid) => {
        if (valid) {
          // 使用 vue-router 路由到指定页面,该方式称之为编程式导航
          this.$router.push("/main");
        } else {
          this.dialogVisible = true;
          return false;
        }
      });
    }
  }
}
script>

<style lang="scss" scoped>
.login-box {
  border: 1px solid #DCDFE6;
  width: 350px;
  margin: 180px auto;
  padding: 35px 35px 15px 35px;
  border-radius: 5px;
  -webkit-border-radius: 5px;
  -moz-border-radius: 5px;
  box-shadow: 0 0 25px #909399;
}

.login-title {
  text-align: center;
  margin: 0 auto 40px auto;
  color: #303133;
}
style>

配置router

//导入element-ui模块,和css文件
import Element from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'

import ElementLogin from "../components/ElementLogin";

Vue.use(Element);

export default new VueRouter({
    routes: [
        {
            path: "/login",
            component: ElementLogin
        }
    ]
})

main.js改变App.vue的生成方式为适配Element

new Vue({
  el: '#app',

  router,
  //ES6的写法,就是生成一个叫App的节点,挂载到根节点上.
  //https://www.jianshu.com/p/0ea899e233a9
  render: h => h(App)

})

App.vue使用组件

<template>
  <div id="app">
    <router-link to="/login">登录router-link>

    <router-view>router-view>

  div>

template>

运行发布npm run dev

报错解决

Module build failed: TypeError: this.getOptions is not a function 安装node-Sass报错

或者官方会告诉你用哪个版本Module build failed: Error: Node Sass version 7.0.1 is incompatible with ^4.0.0.

cnpm install sass-loader@4.0.0 --save-dev

自动生成网站,文档 文档化 (docsify.js.org)


路由嵌套

就是在将一个组件 放到 另一个组件下

index.js

export default new VueRouter({
  routes: [
    {
      path: "/main",
      component: Main,

      //路由嵌套,最后访问/login时,必须是在/main下
      children: [
        {
          path: "/login",
          component: ElementLogin
        }
      ]
    }
})

main.vue

<template>
  
  <div>
    <h1>Hello Vue-Router!h1>

    <router-link to="/login">登录router-link>
    <router-view>router-view>
  div>
template>
参数传递及重定向

取值时,所有的元素必须被标签包裹

App.vue


<router-link :to="{name:'login',params:{id:1}}">登录router-link>

路由index.js

routes: [{
    //访问路径时必须携带有id的参数
    path: "/login/:id",
    name: "login",    
    component: ElementLogin
  }
]

直接接收参数

<h1>{{$route.params.id}}h1>
props父子传参

index.js

name: "login",
//允许传递参数
//当 props 设置为 true 时,route.params 将被设置为组件的 props。
props: true,

在被跳转页面中用props接收对应的参数,可直接使用

<h1>{{id}}h1>

export default {
  name: "Login",
  props: ['id'],

push传递表单参数

登录页面在导出中携带页面表单中的参数

export default {
  name: "Login",
  data() {
    return {
      form: {
        username: '',
        password: ''
      },

      // 表单验证,需要在 el-form-item 元素中增加 prop 属性
      rules: {
        username: [
          {required: true, message: '账号不可为空', trigger: 'blur'}
        ],
        password: [
          {required: true, message: '密码不可为空', trigger: 'blur'}
        ]
      },

      // 对话框显示和隐藏
      dialogVisible: false
    }
  },
  methods: {
    onSubmit(formName) {
      // 为表单绑定验证功能
      this.$refs[formName].validate((valid) => {
        if (valid) {
          // 使用 vue-router 路由到指定页面,该方式称之为编程式导航
          //到达指定页面时携带参数
          this.$router.push("/main/"+this.form.username);
        } else {
          this.dialogVisible = true;
          return false;
        }
      });
    }
  }
}

index.js路由中配置参数列表

path: "/main/:name",
props: true,
component: Main

使用

<template>
  <div>
    <h1>{{name}}</h1>
  </div>
</template>

<script>
export default {
  name: "Main",
  props: ['name']
}
</script>
重定向
routes: [{
    path: "/element",
    component: ElementLogin
  }, {
    path: "/login",
    name: "login",
    props: true,
    //重定向
    redirect: "/element"
  }
]

全局路由和路由钩子 全局路由404
//当在所有path中都不能匹配时,跳转
path: "/*",
component: Main
路由模式

hash:路径带#符号

history:路径不带#符号

路由的index.js

export default new VueRouter({
    mode: "history",
    routes: [
钩子函数及axios

vue-axios|axios中文网 | axios (axios-js.com)

测试目录一般叫mock,放在static目录下

安装axios模块:cnpm install axios,cnpm install vue-axios

导入axios模块

import Axios from "axios"
import VueAxios from "vue-axios"

//必须先绑定VueAxios,再是Axios
Vue.use(VueAxios,Axios)
export default {
  name: "Main",
  beforeRouteEnter: (to, from, next)=>{
    console.log("进入路由之前");

    //vm实现调用methods中的方法后再放行
    next(vm => {
      vm.getData();
    });
  },
  beforeRouteLeave: (to, from, next)=>{
    console.log("进入路由之后");
    next();
  },
  methods: {
    getData: function (){

      //get方式请求文件
      this.axios({
        method: "get",
        url: "../../../static/mock/data.json"
      }).then(function (response){
        //会请求到的数据封装到response中
        console.log(response);
      })
    }

  }

}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/945332.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-18
下一篇 2022-05-18

发表评论

登录后才能评论

评论列表(0条)

保存