Vue.js基础应用笔记

vue.js 笔记

菜鸟教程http://www.runoob.com/vue2/vue-template-syntax.html

中文官方文档https://cn.vuejs.org/v2/guide/index.html#%E7%BB%84%E4%BB%B6%E5%8C%96%E5%BA%94%E7%94%A8%E6%9E%84%E5%BB%BA

中文API文档:https://cn.vuejs.org/v2/api/

vue安装

菜鸟教程http://www.runoob.com/vue2/vue-install.html

Vue.js目录结构

img

目录解析

目录/文件 说明
build 项目构建(webpack)相关代码
config 配置目录,包括端口号等。我们初学可以使用默认的。
node_modules npm 加载的项目依赖模块
src 这里是我们要开发的目录,基本上要做的事情都在这个目录里。里面包含了几个目录及文件:assets: 放置一些图片,如logo等。components: 目录里面放了一个组件文件,可以不用。App.vue: 项目入口文件,我们也可以直接将组件写这里,而不使用 components 目录。main.js: 项目的核心文件。
static 静态资源目录,如图片、字体等。
test 初始测试目录,可删除
.xxxx文件 这些是一些配置文件,包括语法配置,git配置等。
index.html 首页入口文件,你可以添加一些 meta 信息或统计代码啥的。
package.json 项目配置文件。
README.md 项目的说明文档,markdown 格式

vue 单文件方式

  • 单文件就是以*.vue结尾的文件,最终通过webpack也会编译成*.js在浏览器运行
  • 内容:<template></template>+<script></script>+<style></style>
    • template 中只能有一个根节点2.x
    • script中按照export default(配置)来写
    • style中可以设置scoped属性,让其值在template中生效

以单文件的方式启动

-vue-loader,vue-template-compiler,

import Vue from 'Vue';
import App from './app.vue';

new Vue(){
    
    
	el:'#app',
    render:function(create){
    
    
        	return create(APP);   
        	//App包含template/script/style,最终生成DOM结构
   		}    
};

Vue介绍

2014年诞生,2013年react ,09年angular.js

作者:尤雨溪

核心概念:组件化 双向数据流(基于ES5中的defineProperty来实现的),IE9才支持

angular核心:模块化 双向数据绑定(脏检测:–一个数组($watch)

框架对比建议学完vue在比较

双向数据流

1:js内存属性发生改变,影响页面的变化

2:页面的改变,影响js内存属性的变化

vue 初步使用

插值

文本插值:数据绑定最常见的形式就是使用{ {…}}(双大括号)的文本插值

HTML:使用v-html指令用于输出html代码

**属性:**HTML属性中的值应使用v-bind指令。示例:

**表达式:**vue.js都提供了完全的javascript表达式支持

<div id='app'>
    {
   
   {5+5}}</br>
	{
   
   {ok?'YES':'NO'}}</br>
	{
   
   {message.split('').reverse().join('')}}
	<div v-bind:id="'list-' +id">菜鸟教程</div>
</div>
<script>
    new Vue({
     
     
        el:'#app',
        data:{
     
     
            ok:true,
            message:'RUNOOB',
            id:1
        }
    })
</script>

指令

* v-text 是元素的innerText只能在双标签中使用
* v-html 是元素的innerHtml不能包含 双花括号
* v-if 元素是否移除
* v-show 元素是否显示或隐藏
* v-model 双向数据绑定
* v-bind是单向数据绑定,js内存改变影响页面
	v-bind:class  v-bind:value	v-bind:href
    简写 :class :value :href
* v-on 绑定事件的方法
	v-on:事件名=‘表达式||函数名’
	简写:‘@事件名=“表达式||函数名”’
	函数名如果没有参数,可以省略() 只给一个函数名称
    声明组件内函数,在export default这个对象的根属性加上methods属性
    	-key是函数名 值是函数体
    在export default这个对象的根属性加上data属性,其是一个函数返回一个对象
    -对象的属性是我们初始化的变量的名称
* 凡是在template中使用变量或者函数,不需要加this
* 在script中使用就需要加上this
* v-for的使用
	可以单独使用操作数组(item,index)
    可以使用操作对象(value,key,index)
    

指令是带有**v-**前缀的特殊属性

指令用于在表达式的值改变时,将某些行为应用到DOM上,如下例子

用户输入 -数据双向绑定

在 input 输入框中我们可以使用 v-model 指令来实现双向数据绑定:

<div id="app">
    <p>{
   
   { message }}</p>
    <input v-model="message">
</div>
    
<script>
new Vue({
     
     
  el: '#app',
  data: {
     
     
    message: 'Runoob!'
  }
})
</script>

v-model 指令用来在 inputselecttextcheckboxradio 等表单控件元素上创建双向数据绑定,根据表单上的值,自动更新绑定的元素的值。

按钮的事件我们可以使用 v-on 监听事件,并对用户的输入进行响应。

缩写

Vue.js 为两个最为常用的指令提供了特别的缩写:

  • v-bind缩写

    <!-- 完整语法 -->
    <a v-bind:href="url"></a>
    <!-- 缩写 -->
    <a :href="url"></a>
    
  • v-on缩写

    <!-- 完整语法 -->
    <a v-on:click="doSomething"></a>
    <!-- 缩写 -->
    <a @click="doSomething"></a>
    

组件化应用构建

组件系统是 Vue 的另一个重要概念,因为它是一种抽象,允许我们使用小型、独立和通常可复用的组件构建大型应用。仔细想想,几乎任意类型的应用界面都可以抽象为一个组件树:

<div id="app-7">
  <ol>
    <!--
      现在我们为每个 todo-item 提供 todo 对象
      todo 对象是变量,即其内容可以是动态的。
      我们也需要为每个组件提供一个“key”,稍后再
      作详细解释。
    -->
    <todo-item
      v-for="item in groceryList"
      v-bind:todo="item"
      v-bind:key="item.id"
    ></todo-item>
  </ol>
</div>

<!------------------------>
Vue.component('todo-item', {
  props: ['todo'],
  template: '<li>{
   
   { todo.text }}</li>'
})

var app7 = new Vue({
  el: '#app-7',
  data: {
    groceryList: [
      { id: 0, text: '蔬菜' },
      { id: 1, text: '奶酪' },
      { id: 2, text: '随便其它什么人吃的东西' }
    ]
  }
})
<!------------输出------------>
<!--
1.蔬菜
2.奶酪
3.随便其他什么人吃的东西
-->

与自定义元素的关系

你可能已经注意到 Vue 组件非常类似于自定义元素——它是 Web 组件规范的一部分,这是因为 Vue 的组件语法部分参考了该规范。例如 Vue 组件实现了 Slot APIis 特性。但是,还是有几个关键差别:

  1. Web Components 规范已经完成并通过,但未被所有浏览器原生实现。目前 Safari 10.1+、Chrome 54+ 和 Firefox 63+ 原生支持 Web Components。相比之下,Vue 组件不需要任何 polyfill,并且在所有支持的浏览器 (IE9 及更高版本) 之下表现一致。必要时,Vue 组件也可以包装于原生自定义元素之内。
  2. Vue 组件提供了纯自定义元素所不具备的一些重要功能,最突出的是跨组件数据流、自定义事件通信以及构建工具集成。

父子组件使用(父传子)

  • 父和子,使用的是父,被用的是子
  • 父需要声明子组件,引入子组件对象,声明方式如下
import 子组件对象 from './xxx.vue'new Vue({
    
    
    componets:{
    
    
        组件名:子组件对象
    }
})
  • 全局组件,使用更为方便,不需要声明,直接用
  • 在main.js中引入一次,在main.js中使用用‘vue.component(‘组件名,组件对象’)’
  • 所有的组件都可以直接通过组件名使用

父传子

  • 父组件通过子组件的属性将值进行传递 方式有2:

    • 常量 : prop1=‘常量值’
    • 变量: :prop2=‘变量名’
  • 子组件需要声明

    • 根属性 props:[‘prop1’,‘prop2’]
    • 在页面中直接使用{ {prop1}}
    • 在js中应该如何使用prop1? this.prop1获取

子传父

子传父的思想是通过自定义事件来传递

connecor.js

//作为连接器的文件
import Vue from 'vue';

export default new Vue();

App.vue

<template>
  <!--只能有一个根节点-->
  <div>
    <vue-sub></vue-sub>
    <!--开始监听监听-->
    <button @click="listener">监听儿子打电话</button>
  </div>
</template>

<script>
  import connector from './connector';
  import vueSub from './components/vueSub'
  export default {
    
    
    //配置
    //类似socope.xxx ='初始化'
    data() {
    
    
      return {
    
    }
    },
    methods:
      {
    
    
        listener(){
    
    
            //需要使用connector.$on()方法
            //第一个参数相当于暗号、第二个参数是回调函数
            //参数的值是接受到的信息。
          connector.$on('phone',(msg)=>{
    
    
            console.log(msg);
          })
        }
      },
    //声明使用哪些组件.全局组件不用声明
    components: {
    
    
        //明确用到哪些组件
      vueSub
    }
  }
</script>

vueSub.vue

<template>
  <p>
    <input type="text" v-model="msg">
    <button @click="call(msg)">儿子组件:回电话给老爸</button>
  </p>
</template>

<script>
  import connector from '../connector';
  export default {
    
    
    data() {
    
    
      return {
    
    
        msg:'吃鸡滴滴'
      }
    },
    methods: {
    
    
      call(msg){
    
    
          //使用connector.$emit来回复信息
          //第一个参数相当于约定的暗号。第二个参数是回复过去的信息
        connector.$emit('phone','儿子回复:'+msg);
      }
    }
  }
</script>

vue深入

重点

  • vue组件的使用
  • 组件间通信
  • vue-router使用
  • vue-resource发起http请求
  • axios

过滤器

content| 过滤器 ,vue中没有提供相关的内置过滤器,但是可以自定义过滤器

组件内的过滤器+ 全局过滤器

​ -组件内的过滤器就是options中的一个filters的属性(一个对象)

​ +多个key就是不同过滤器名,多个value就是与key对应的过滤方式函数体

​ -Vue.filter(名,fn)

<template>
  <div class="secondDay">
    请输入内容
    <input type="text" v-model="msg">
    {
    
    {
    
    msg | reverse}}

  </div>
</template>

<script>
  export default {
    
    
    data(){
    
    
      return{
    
    
        msg:'请输入内容'
      }
    },
    methods:{
    
    

    },
    filters:{
    
    
      reverse(msg){
    
    
        return msg.split("").reverse().join('');
      }
    }
  }
</script>

总结

​ 全局:范围大,权利小

​ 组件内:范围小,如果出现同名权力大

获取DOM元素

  • 前端框架就是为了减少DOM操作,但是特定情况下,也给我们留了后门

  • 在指定的元素上,添加ref=“名称A”

  • 在获取的地方加上this.$refs.名称A

    • 如果ref放在原生DOM元素上,获取的数据就是原生的DOM对象

      • 可以直接操作
    • 如果ref放在了组件对象上,获取的就是组件对象

      • 获取的DOM对象,通过this. r e f s . 名 称 A . refs.名称A. refs.A.el,进行操作
    • 对应的事件

      • created 完成了数据的初始化,此时还未生成DOM,无法操作DOM
      • mounted将数据已经装载到了DOM上,可以操作DOM

mint-ui

  • 饿了么,element-ui在pc端使用

  • 移动端版本,mint-ui

  • https://mint-ui.github.io/#!/zh-cn

  • 使用

    • 如果是全部安装的方式

      • 1,在template中可以直接使用组件标签
      • 2.在script中必须要声明,也就是引入组件对象(按需加载)
    • 示例代码

      • import MintUi from 'mint-ui';
        
        import 'mint-ui/lib/style.css';
        Vue.use(MintUi);
        

vue-router

  • 前端路由核心就是锚点值得改变,根据不同的值,渲染指定DOM位置的不同数据

  • ui-router:锚点值改变,如何获取模板?

  • vue中,模板数据不是通过ajax请求,而是调用函数获取到模板内容

  • 核心:锚点值改变

  • 只要看到vue开头,就知道必须Vue.use

  • vue的核心插件:

    • -vue-router路由
    • vuex管理全局共享数据
  • 使用方式

    • 下载‘npm i vue-router -S’

    • 在main.js中引入

      • import VueRouter from 'vue-router';
        
    • 安装插件 ‘Vue.use(VueRouter)’;

    • 创建路由对象并配置路由规则

      • let router = new VueRouter({
                  
                  
            routes:[
                {
                  
                  path:'/home',component:Home}
            ]
        });
        
    • 将其路由对象传递给Vue的示例,options中

      • options中加入 ‘router:router’
    • 留坑

      <router-view></router-view>
      

命名路由

  • 需求,通过a标签点击,做页面数据的跳转

  • 使用router-link标签

    • 1直接写地址

      • <router-link to='/beijing'>去北京</rount-link>
        
    • 2使用命名的方式-方便维护

      • <router-link :to="{name:bj}">去北京</router-link>
        
      • 更利于维护,如果修改了path,只修改路由配置中的path,该a标签会根据修改后的值生成href属性

router-link对象方式传递参数

  • 在vue-router中,有两大对象被挂载到了实例this

  • r o u t e r ( 只 读 , 具 备 信 息 的 对 象 ) , router(只读,具备信息的对象), router()router(具备动能的函数)

  • 查询字符串

    • 1:去哪里

      • //detail是一个组件名。index是放在for循环的index。这里只给出部分代码
        <router-link :to="{name:'detail',query:{id:index}}">xxx</router-link>
        
        
    • 2:导航(查询字符串path不用改)

      ‘{name:‘detail’,path:’/detail’,组件}’

      
      
    • 3,去了干嘛,获取路由参数(要注意是query还时params和对应id名)

  • path方式

    • 1:去哪里

      • <router-link :to="{name:'detail',params:{id:index}}">xxx</router-link>
        
    • 2,导航(path方式需要在路由规则上加/:xxx)

      • ‘{name:‘detail’,path:’/detail/:id’,组件}’
    • 去了干嘛,获取路由参数(要注意是query还是params和对应的id名)

      • this.$route.params.id
        
代码示范

main.js中的路由配置

let router = new VueRouter({
    
    
  //routes
  routes: [
    //一个个对象
    {
    
    name:'list', path: '/list', component: List},

    //使用query的方式传递参数,不需要修改路由。
    // {name:'detail',path: '/detail', component: Detail}
    //使用params的方式传递参数,需要修改路由规则
    {
    
    name:'detail',path: '/detail/:id', component: Detail}
  ]
});

list.vue中的部分代码

<template>
  <div>
    <ul>
      <li v-for="(hero ,index ) in heros" :key="index">
        {
    
    {
    
    hero.name}}
        <router-link :to="{name:'detail',query:{id:index}}">查看</router-link>
      </li>
    </ul>

    第二种查询方法==================
    <ul>
      <li v-for="(hero ,index ) in heros" :key="index">
        {
    
    {
    
    hero.name}}
        <router-link :to="{name:'detail',params:{id:index}}">查看</router-link>
      </li>
    </ul>
  </div>
</template>

<script>
  export default {
    
    
    data(){
    
    
      return {
    
    
        heros:[{
    
    name:'李白'},{
    
    name:'花木兰'}]
      }
    }
  }
</script>

在detail.vue中的部分代码

<template>
  <div>
    查看的英雄的ID{
    
    {
    
    msg}}
  </div>
</template>

<script>
  export default {
    
    
    data(){
    
    
      return{
    
    
        msg:''
      }
    },
    methods:{
    
    

    },
    filters:{
    
    
    },
    created(){
    
    
      //创建DOM之前,可以获得从上个页面传过来的参数
      this.msg=this.$route.query;
      if (this.$route.params){
    
    
        this.msg=this.$route.params;
      }
    }
  }
</script>

vue-resource(了解)

  • 官方团队开发。但已经不维护了
  • 有axios代替

代码示例

created(){
    
    
  //get请求
    this.$http.get('url').then(res=>{
    
    
        this.data=res.body.message;
    },err=>{
    
    
        console.log(err);
    });
      //post请求
    this.$http.post('url',{
    
    key:'value'},{
    
    emulateJSON:true}).then(res=>{
    
    
        this.data=res.body.message;
    },err=>{
    
    
        console.log(err);
    })


}

axios

使用

import Axios from 'axios'
Vue.prototype.$axios = Axios//挂载

代码示例

执行get请求
// 为给定 ID 的 user 创建请求
axios.get('/user?ID=12345')
  .then(function (response) {
    
    
    console.log(response);
  })
  .catch(function (error) {
    
    
    console.log(error);
  });

// 可选地,上面的请求可以这样做
axios.get('/user', {
    
    
    params: {
    
    
      ID: 12345
    }
  })
  .then(function (response) {
    
    
    console.log(response);
  })
  .catch(function (error) {
    
    
    console.log(error);
  });
执行post请求
axios.post('/user', {
    
    
    firstName: 'Fred',
    lastName: 'Flintstone'
  })
  .then(function (response) {
    
    
    console.log(response);
  })
  .catch(function (error) {
    
    
    console.log(error);
  });
执行多个并发请求

特点:只有两个都请求成功才成功

function getUserAccount() {
    
    
  return axios.get('/user/12345');
}

function getUserPermissions() {
    
    
  return axios.get('/user/12345/permissions');
}

axios.all([getUserAccount(), getUserPermissions()])
  .then(axios.spread(function (acct, perms) {
    
    
    // 两个请求现在都执行完成
  }));

axios API

可以通过向 axios 传递相关配置来创建请求

axios(config)
// 发送 POST 请求
axios({
    
    
  method: 'post',
  url: '/user/12345',
  data: {
    
    
    firstName: 'Fred',
    lastName: 'Flintstone'
  }
});
axios(url[, config])
// 发送 GET 请求(默认的方法)
axios('/user/12345');

解决跨域问题

这里以访问豆瓣Top250为例,直接访问如下

this.$axios.get("http://api.douban.com/v2/movie/top250")
.then(res=>{
    
    
	console.log(res)
})
.catch(err=>{
    
    
	console.log(err)
})

Step1:配置BaseUrl

main.js中,配置下我们访问的Url前缀:

import Vue from 'vue'
import App from './App'
import Axios from 'axios'

Vue.prototype.$axios = Axios
Axios.defaults.baseURL = '/api'
Axios.defaults.headers.post['Content-Type'] = 'application/json';

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
    
    
  el: '#app',
  components: {
    
     App },
  template: '<App/>'
})

关键代码是:Axios.defaults.baseURL = '/api',这样每次发送请求都会带一个/api的前缀。

Step2:配置代理

修改config文件夹下的index.js文件,在proxyTable中加上如下代码:

'/api':{
    
    
    target: "http://api.douban.com/v2",
    changeOrigin:true,
    pathRewrite:{
    
    
        '^/api':''
    }
}

Step3:修改请求Url

修改刚刚的axios请求,把url修改如下:

this.$axios.get("/movie/top250")
.then(res=>{
    
    
	console.log(res)
})
.catch(err=>{
    
    
	console.log(err)
})

Step4:重启服务

重启服务后,此时已经能够访问了:

原理:

因为我们给url加上了前缀/api,我们访问/movie/top250就当于访问了:localhost:8080/api/movie/top250(其中localhost:8080是默认的IP和端口)。

在index.js中的proxyTable中拦截了/api,并把/api及其前面的所有替换成了target中的内容,因此实际访问Url是http://api.douban.com/v2/movie/top250。

拦截器

  • 过滤,在每一次请求与响应中,添油加醋
  • axios.interceptors.request.use(fn) 在请求之前
  • function (config){config.headers={xxx};return config} config相当于options对象
  • 默认设置defaults范围广,权利小
    • Axios.defaults.header={…}
  • 单个请求的设置 get(rul,options),范围小,权利中
  • 拦截器,范围广,权利大(请求的最后一层)

token(扩展)

  • cookie 和 session的机制,cookie自动带一个字符串
  • cookie只在浏览器
  • 移动端原生应用,也可以使用http协议,1:可以加自定义的投,原生应用没有cookie
  • 对于三端来讲,tooken可以作为cookie
  • 对拦截器的使用在这里插入图片描述

监视数据变化

  • watch可以对(单个)变量进行监视,也可以深度监视
  • 如果需求是对于10个变量进行监视?
  • 计算属性computed可以监视多个值,并且指定返回数据,并且可以显示在页面
  • 都是options中的根属性
    • watch监视单个
    • computed可以监视多个this相关属性值的改变,如果和原值一样就不会出发函数的调用,并且可以返回对象

对引用类型需要深度监视

watch
在这里插入图片描述

实例生命周期钩子

每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。

比如 created 钩子可以用来在一个实例被创建之后执行代码:

new Vue({
data: {
a: 1
},
created: function () {
// this 指向 vm 实例
console.log('a is: ’ + this.a)
}
})
// => “a is: 1”
也有一些其它的钩子,在实例生命周期的不同阶段被调用,如 mounted、updated 和 destroyed。生命周期钩子的 this 上下文指向调用它的 Vue 实例。

不要在选项属性或回调上使用箭头函数,比如 created: () => console.log(this.a) 或 vm.$watch(‘a’, newValue => this.myMethod())。因为箭头函数是和父级上下文绑定在一起的,this 不会是如你所预期的 Vue 实例,经常导致 Uncaught TypeError: Cannot read property of undefined 或 Uncaught TypeError: this.myMethod is not a function 之类的错误。

生命周期图示

下图展示了实例的生命周期。你不需要立马弄明白所有的东西,不过随着你的不断学习和使用,它的参考价值会越来越高。

Vue 实例生命周期

扩展

Object.freeze() 方法可以冻结一个对象。一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。此外,冻结一个对象后该对象的原型也不能被修改。freeze() 返回和传入的参数相同的对象。

猜你喜欢

转载自blog.csdn.net/mxl00z/article/details/88621509
今日推荐