Vue core tutorial
Among the three front-end frameworks, Vue is the most popular and React is the most popular;
1, Vue basic knowledge
Vue official website
1) English official website: https://vuejs.org/
2) Chinese official website: https://cn.vuejs.org/
Vue overview
Vue (pronunciation / vju) ː/, Similar to view) is a progressive framework for building user interfaces. Unlike other large frameworks, Vue is designed to be applied layer by layer from bottom to top. Vue's core library only focuses on view layers, which is not only easy to start, but also easy to integrate with third-party libraries or existing projects. On the other hand, when combined with modern tool chains and various supporting class libraries, Vue can also provide drivers for complex single page applications.
Vue. The goal of JS is to achieve responsive data binding and combined view components through as simple an API as possible. In short: dynamically build the user interface and dynamically display the background data in the front-end page.
Vue.js is built with the idea of data-driven and componentization.
Vue.js Author: you Yuxi (a Chinese American former Google Engineer):
You Yuxi is Vue.js The author of the framework, HTML5 edition Clear Build people. He believes that the future App The trend is lightweight and refined. Applications that can solve problems are good applications. In the context of the era of mobile Internet, the opportunities for individual developers are in four aspects: low threshold, low cost, cross device and multi platform. You Yuxi graduated from Fudan high school in Shanghai, completed his university studies in the United States and graduated from Colgate University,Later in Parsons Obtained by the school of design Design & Technology Master of Arts, currently working in New York Google Creative Lab. 2014 In February, a front-end development library was developed Vue.js. Vue.js Is build Web Interface JavaScript Library is a simple API Provide efficient data binding and flexible component system. 2016 On September 3, 2003, in Nanjing JSConf Up, Vue Author you Yuxi officially announced his joining Alibaba Weex You Yuxi said he would join the team as a technical consultant Weex Team to do Vue and Weex of JavaScript runtime Integration, the goal is to make everyone use Vue Our syntax spans three ends(Desktop applications/Web application/mobile phone App). More:https://baike.baidu.com/item/%E5%B0%A4%E9%9B%A8%E6%BA%AA/2281470?fr=aladdin
What is a progressive framework
So what does progressive framework mean? Before we explain this word, we need to understand the question "what is framework?"
In the initial front-end development, in order to complete a task, we first use js to obtain DOM elements from HTML files, then add events, and finally carry out a series of JS programming operations. Let's call this development method "DOM flow". The development method of "DOM flow" seems very simple and practical, but with the continuous change of business requirements, your trouble will come, and the whole code will become more and more chaotic and unable to maintain.
For example, suppose there is a demand that a picture can record the number of clicks when it is clicked. This seems very simple. According to the development method mentioned above, it should be done soon. Next, there is a slight change in the demand. It is required to have two pictures. When they are clicked respectively, they can record their click times. This time it seems very simple. Just copy and paste the original code. So what will you do when this demand becomes five pictures? It's better to simply copy and paste, which can completely meet this requirement, but you will feel very uncomfortable, because your code becomes very bloated and there are many repeated processes, but it seems to be within your tolerance. At this time, the demand has changed slightly. Five photos record the number of clicks respectively, but it seems to take up too much space to list five pictures separately. Now only one picture position needs to exist, and the clicked pictures can be switched by selecting the button. At this time, you may run away, because to complete this seemingly small change, most of the code you originally wrote may need to be deleted, or even completely emptied, and written from scratch. What's more depressing is that even if you have the patience to rewrite this demand, once there is a new demand, you may have to start again. This is just a simple task to record the number of clicks. It seems that there are great problems in the development method of "DOM flow". In the real development, the complex business logic and huge amount of code are unbearable for "DOM flow".
In order to deal with the above problems, the developers reorganized the organizational structure of the code and divided the JS code into three parts: data (M), view (V) and logic control (*). The data section only contains data content, the view section only changes the style, and the logic control is responsible for connecting the view section with the data section and the corresponding logic, as shown in the figure below. The benefits of this code structure organization are obvious. When the requirements change, only the corresponding sections need to be changed. Let's take the need to record the number of image clicks mentioned above as an example. This is the reorganized code demo. You can see that the code becomes clear and easy to understand, and you can also imagine adding some more requirements to see the degree of code changes.
Code demo:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>messi-show</title> <style> #show { margin-left: 250px; margin-top: 20px; } .pic { width: 400px; height: 300px; } .messi-show { display: inline-block; margin-left: 30px; width: 30px; border: solid 1px red; cursor: pointer; text-align: center; cursor: pointer; } </style> </head> <body> <ul class="messi"> <li class="messi-show" id="mm">1</li> <li class="messi-show" id="mm">2</li> <li class="messi-show" id="mm">3</li> <li class="messi-show" id="mm">4</li> <li class="messi-show" id="mm">5</li> </ul> <div id="show"> <span class="name"></span> <P class="count"></P> <img class="pic" src="" alt=""> </div> <script> window.onload = function () { var data = { admin: false, name: ["First one", "Second sheet", "Third sheet", "Sheet 4", "Sheet 5"], url: ["ad0.jpg", "ad1.jpg", "ad2.jpg", "ad3.jpg", "ad4.jpg"], num: [0, 0, 0, 0, 0] }; var controller = { getshow: function (index) { var name = data.name[index]; var url = data.url[index]; var num = data.num[index]; view.rendershow(name, url, num); }, addnum: function (srcid) { var index = (data.url).indexOf(srcid); data.num[index] = (data.num[index]) + 1; view.rendernum((data.num[index])); }, init: function () { view.init(); } }; var view = { init: function () { var list = document.getElementsByClassName('messi-show'); this.show = document.getElementById('show'); this.pic = this.show.getElementsByClassName('pic')[0]; this.count = this.show.getElementsByClassName('count')[0]; for (var i = 0; i < list.length; i++) { list[i].addEventListener("click", (function (copyi) { return function () { controller.getshow(copyi); }; })(i)); } this.pic.addEventListener("click", function (e) { var srcid = e.target.attributes.src.value; controller.addnum(srcid); }); view.rendershow("First one", "ad0.jpg", "0"); }, renderlist: function () { }, rendershow: function (name, url, num) { this.pic.src = url; var showname = this.show.getElementsByClassName('name')[0]; showname.innerHTML = name; this.count.innerHTML = num; }, rendernum: function (num) { this.count.innerHTML = num; } }; controller.init(); }; </script> </body> </html>
It is suggested that the image can be saved directly from the wechat (p107gmog-252077, image capture from the wechat)
In fact, this development method is what we often call MV * mode, and MVC, MVVM, MVP[2] are all derivatives of MV *. In fact, the name of the mode is not important. When you understand the purpose of this code organization structure, you will understand that these modes are essentially the same thing, so that there will be no direct connection between data and view. In fact, at this point, you should know the reasons for the defects of "DOM flow". In "DOM flow", we actually treat DOM as a Model. We directly obtain data from DOM, and then change DOM to update the view. In fact, the view and Model are mixed together, and the code organization is naturally messy and difficult to maintain.
This MV * code organization has gradually evolved into the so-called framework. An important reason for choosing to use the framework in team development is that the organizational structure of the code set in advance by the framework makes the code of the actual development project relatively clear, so there is no need to worry about the overall confusion of the code due to the negligence or unique coding habits of someone in the team. In fact, Bootstrap is not a tool to beautify the interface, but a tool to beautify the framework. Jquery does not involve the structure and organization of code, but simplifies some repeated operations (such as DOM operation, Ajax operation, etc.) and solves compatibility, so it is only a JS library for convenient operation.
Now, with the code organization of MV *, we have robust code that can respond to changes in requirements. In the process of using, developers gradually find that when dealing with the demand of frequent data update, we are always doing the same work - obtaining DOM and updating the view according to the new data. These tasks are tedious and repetitive, which essentially consumes the energy of developers. In order to solve this problem, the MVVM framework based on MV * pattern was born - Knockout. It uses the form of an instance to transfer the content of the model layer into the so-called view model of the instance, and uses the binding method to complete the two-way binding between the view model and the view. When the data in the view mode changes, the view changes, and vice versa. This description of Knockout may be a little abstract. After all, there is no code, but at least you know that Knockout framework can complete the corresponding update of the view after data update for us, as shown in the figure below.
[the external link image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-ljPgyHe1-1619407373079)(images / wechat screenshot _20201025211055.png)]
You may wonder why you haven't used a framework with such advanced concepts and functions, or even heard of it before. This is because Knockout surpassed its era when it was born. Remember the reason why MVVM framework came into being at the beginning of this paragraph - to deal with the need for frequent data updates. At that time, most of the front-end pages only involved static display and simple interaction, and there were no frequent data changes. Using Jquery is enough. In this way, Knockout was not popular at that time, but this framework still exists. You can go and have a look if you are interested, and it's easy to get started. Until recent years, with the increasing demand for frequent changes in data, people began to pay attention to the concept of automatically updating views.
Vue is one of many frameworks that inherit this idea. As shown in the following figure, in the Vue instance with a responsive system, the DOM State is only a mapping of the data State, that is, UI=VM(State). When the State on the right side of the equation changes, the UI of the page display will change accordingly. When many people first started Vue, they felt it was easy to use. That's why. However, it should be noted that Vue's core positioning is not a framework, and the design does not fully follow the MVVM mode. It can be seen that there are only two parts in the figure: State and view. Vue's core function emphasizes the mapping from State to interface, and does not pay attention to the structure and organization of code. Therefore, when only using its core functions, it is not a framework, It is more like a view template engine, which is why Vue developers name it with pronunciation similar to view.
[the external link image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-ZpKcNp5r-1619407373081)(images / wechat screenshot _20201025211242.png)]
Now let's look at the meaning of "progressive". As mentioned above, the core function of Vue is a view template engine, but this does not mean that Vue cannot become a framework. As shown in the figure below, all components of Vue are included here. On the basis of declarative rendering (view template engine), we can build a complete framework by adding component system, client routing and large-scale state management. More importantly, these functions are independent of each other. You can choose other components arbitrarily on the basis of core functions, not necessarily all of them. It can be seen that the so-called "progressive" is actually the use of Vue, and also reflects the design concept of Vue
[the external link image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-rmwPq6e9-1619407373084)(images / wechat screenshot _20201025211316.png)]
As for the "progressive" explanation, I saw a good answer on knowledge, which was also praised by the designers of Vue. This answer is from a good perspective, mainly from the comparison with React and Angular.
In my opinion, the meaning of progressive representation is to advocate the least.
Each framework will inevitably have its own characteristics, which will have certain requirements for users. These requirements are claims. Claims are strong and weak. Its strength will affect the use mode in business development.
For example, Angular is strongly advocated in both versions. If you use it, you must accept the following things:
-Its modular mechanism must be used - its dependency injection must be used - and its special form must be used to define components (this is inevitable for every view framework)
Therefore, Angular is highly exclusive. If your application doesn't start from scratch, but needs to constantly consider whether to integrate with other things, these ideas will bring some troubles.
For example, React also has some ideas. Its ideas are mainly the idea of functional programming. For example, you need to know what side effects are, what pure functions are, and how to isolate side effects. It seems less invasive than Angular, mainly because it is soft invasion.
Vue may not be as good as React or Angular in some aspects, but it is gradual and has no strong proposition. You can use it to implement one or two components on the original large system when jQuery is used; You can also use it to develop the whole family bucket, when it is used by Angular; You can also use its view to match the whole lower layer designed by yourself. You can use the concept of OO and design pattern in the place of underlying data logic, or functional formula. It's just a lightweight view, only doing what you should do, not what you shouldn't do, that's all.
The meaning of gradualism is that I don't do more than my duty.
Another understanding is: Vue library is composed of core library and a series of related plug-ins; The core library is relatively lightweight and can realize some basic functions; We can only use the core functions of Vue. If we need some other functions, we can add other plug-ins based on the core library;
Data driven
Vue is an MVVM framework. DOM is a natural mapping of data. The traditional mode is to request data from the model through Ajax request, and then manually trigger the DOM to pass in the data modification page. In Vue, Directives encapsulates the view. When the data in the model changes, Vue will modify the DOM through the Directives instruction. At the same time, the DOM Listener is also used to monitor the view. When the DOM changes, it will be monitored to change the model and realize the two-way binding of data.
[the external link image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-D6nDMNT3-1619407373085)(images / wechat screenshot _20201025212457.png)]
Componentization
Componentization realizes the extension of HTML elements and encapsulates the available code. Each independent visual / interactive area on the page is regarded as a component; Each component corresponds to a project directory, and various resources required by the component are maintained nearby under this directory; A page is just a container for components. Components can be nested and combined freely to form a complete page.
[the external link image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-uR9qIMDf-1619407373086)(images / wechat screenshot _20201025212711.png)]
Comparison of three mainstream frameworks
Angular
[the external link image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-NL9RBRdc-1619407373094)(images / wechat screenshot _20201025214007.png)]
Angular It is an excellent front end JS Framework, which has been used Google Among a variety of products. It has the following features: 1.Good application structure 2.Bidirectional data binding 3.instructions 4.HTML Template 5.Can be embedded, injected and tested advantage: 1. The template has powerful functions and comes with extremely rich angular Instructions. 2. It is a relatively complete front-end framework, including services, templates, two-way data binding, modularization, routing, filters, dependency injection and other functions; 3. You can use a custom instruction more than once in a custom item. 4. ng Modularity is boldly introduced Java Some things (dependency injection) can easily write reusable code, which is very helpful for agile development teams. 5. angularjs It is developed by Internet giant Google, which also means that he has a solid foundation and community support. Disadvantages: 1. angular It's easy to get started, but there are many concepts after going deep, Difficult to understand in learning. 2. Document examples are very few, The official documents basically only write api, Not a single example, Most of the time, it's how to use it google Yes, Or ask directly misko,angular Author of. 3. yes IE6/7 Compatibility is not particularly good, It can be used jQuery Write your own code and solve some problems. 4. There are few best practice tutorials on the application of instructions, angular It's actually very flexible, If you don't look at the use principles of some authors,It's easy to write four different codes, for example js Medium or like jQuery I have a lot of ideas dom operation. 5. DI Dependency injection if code compression needs to display declarations.
React
[the external link image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-VwC5LcpB-1619407373096)(images / wechat screenshot _20201025214942.png)]
React come of Facebook Internal project for erection Instagram And open source in May 2013. React With high performance and simple code logic, more and more people have begun to pay attention to and use it. It has the following features: 1.Declarative design: React Using the declaration paradigm, applications can be easily described. 2.High efficiency: React Pass on DOM The simulation minimizes the interaction with DOM Interaction of. 3.Flexibility: React It can work well with known libraries or frameworks. advantage: 1. Fast: in UI During rendering, React Through virtual DOM To realize the actual DOM Local update of. 2. Cross browser compatibility: Virtual DOM It helps us solve the cross browser problem and provides us with standardized services API,Even in IE8 There's no problem in it. 3. Modularity: write independent modularity for your program UI Components, so that when one or some components have problems, they can be easily isolated. 4. One way data flow: Flux Is a tool for JavaScript The architecture of one-way data layer is created in the application, which follows React View library development Facebook conceptualization. 5. Isomorphic and pure javascript: Because the crawler of search engine depends on the server response rather than JavaScript The execution of pre rendering your application helps search engine optimization. 6.Good compatibility: such as using RequireJS To load and package, and Browserify and Webpack Suitable for building large applications. They make difficult tasks less daunting. Disadvantages: React Itself is just a V It's not a complete framework, so if you want a complete framework for a large project, you basically need to add it ReactRouter and Flux To write large applications.
Vue
Vue You Yuxi is a build data-driven Web The interface library is not exactly a framework, it focuses on V(view)View layer. It has the following features: 1.Concise coding, Small volume, High operation efficiency, Suitable for mobile/PC End development 2.Bidirectional data binding 3.instructions 4.Plug-in, which only focuses on UI, Can be easily introduced vue Plug in or other third library development projects 5.follow MVVM pattern advantage: 1.Simple: the official document is very clear, which is better than Angular Easy to learn. 2.Fast: asynchronous batch mode update DOM. 3.Composition: combine your applications with decoupled, reusable components. 4.Compact:~18kb min+gzip,And no dependency. 5.Powerful: expressions do not need to declare dependent derivable properties (computed properties). 6.Module friendly: you can NPM,Bower or Duo Install, do not force all your code to follow Angular The use scenario is more flexible. Disadvantages: 1.newborn: Vue.js It's a new project, No angular So mature. 2.The impact is not great: google After a while, it's about Vue.js The diversity or richness is less than that of some other well-known libraries. 3.I won't support it IE8
Three mainstream frameworks
1) Vue draws lessons from angular's template and data binding technology
2) Vue draws lessons from react's componentization and virtual DOM technology
Vue extension
vue-cli
vue-cli It's an official release vue.js Project scaffolding, use vue-cli Can be created quickly vue project github Address: https://github.com/vuejs/vue-cli
vue-resource/axios
stay Vue When the front and back end of the project interact, the early Vue Version use Vue-resource The plug-in obtains data from the background. from Vue2.0 And then no more vue-resource Update, but recommended axios.
vue-resource
Vue.js The plug-in provides the use of XMLHttpRequest or JSONP conduct Web A service that requests and processes responses. vue-resource image jQuery of $.ajax,Used for data interaction. Mainly used for sending ajax Request. characteristic: 1.Small size, about 12 after compression kb 2.Support mainstream browsers, except IE9 following 3.support Promiss API and URL Templates 4.Interceptors are supported. Interceptors are global and can do some things before and after sending requests.
axios
characteristic: 1.Send in browser XMLHttpRequests request 2.stay node.js Send in http request 3.support Promiss API 4.Interceptor requests and responses 5.Transform request and response data 6.Cancel request 7.Automatic conversion JSON data 8.Client support protects against CSRF/XSRF attack
vue-router
Vue Router yes Vue.js The official routing manager. It and Vue.js The core of deep integration makes it easy to build single page applications. The functions include: nested routing/View table; Modular, component-based routing configuration; Routing parameters, queries, wildcards; be based on Vue.js View transition effect of transition system; Fine grained navigation control; With automatic activation CSS class Links to; HTML5 Historical mode or hash Mode, in IE9 Automatic degradation in; Custom scroll bar behavior.
vuex
Vuex It's designed for Vue It adopts centralized storage to manage the state of all components of the application, and ensures that the state changes in a predictable way with corresponding rules. In short, Vuex Use the form similar to global object to manage the common data of all components. If you want to modify the data of this global object, you must follow Vuex Modify in the way provided (you can't modify in your own way at will).
vue-lazyload
Pictures are a key point of website optimization, and lazy loading of pictures is a better method. jquery There are also many plug-ins for lazy loading of pictures vue Lazy picture loading plug-in ---- vue-lazyload.
vue scroller
Vue Scroll bar is Vonic UI A basic component of. For smooth scrolling, pull-down refresh and infinite load components. vonic One based on vue.js and ionic Stylized UI Framework, which is used to quickly build mobile end single page applications, is very simple.
mint-ui
Mint UI be based on Vue.js Mobile terminal of UI Component library
element-ui
element-ui be based on vue of UI Component library(PC end),A set of Web-based for developers, designers and product managers Vue 2.0 Desktop component library
MVC and MVVM
MVC and MVVM are two common front-end architecture patterns, which are abstracted and separated to solve a certain kind of problem. An architecture pattern can also derive many design patterns to solve different problems.
Features in MVC and MVVM:
- Similarities: where M refers to MODEL and V refers to VIEW
- Differences: the only difference between the two architectures is the link between MV s.
MVC
MVC architecture refers to MODEL-VIEW-CONTROLLER, which is the abbreviation of MODEL VIEW CONTROLLER. MVC allows the user to change the response mode of VIEW input without changing the VIEW. The user's VIEW operation is handed over to the CONTROLLER for processing. In response to the event of VIEW, the CONTROLLER calls the interface of MODEL to operate the data. As long as the MODEL changes, Update the response to the relevant VIEW.
If the native HTML+CSS+JS is used as a metaphor, it can be compared to the user operating through the HTML (VIEW) layer, and JS (CONTROLLER) monitors the changes of the VIEW through event monitoring, and then interacts with the data through AJAX (MODEL) (receiving and sending to the server). The data is updated.
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-iTItatn7-1619407373097)(images/mvc.jpg)]
M is the model layer of data, which mainly deals with the curd of data, including create, update, retrieve and delete
The V view layer is used as the front-end page
C control layer business logic layer, including routing, login and logoff
MVC is a software design paradigm. It organizes code by separating business logic, data and interface display, and gathers business logic into one component. It does not need to rewrite business logic while improving and customizing interface and user interaction. MVC is uniquely developed to map the traditional input, processing and output functions in a logical graphical user interface structure.
MVVM
VM here refers to VM
The biggest difference between MVVM and MVC model is that it realizes the automatic update of view and model, that is, when the properties of model are changed, we no longer operate DOM manually, but the view layer corresponding to the changed properties will be changed automatically. Because in MVVM, the view does not know the existence of the model, and the model and ViewModel do not observe the view. This low coupling mode improves the reusability of the code.
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-wiwgziEi-1619407373098)(images/clip_image005.jpg)]
MVVM is a front-end concept, which comes from MVC. It just replaces C with VM. The core idea is to divide each page into M,V and VM, in which VM is the core of MVVM idea; Because VM is the scheduler between M and V. The idea of MVVM is used in the front-end page, mainly to make our development more convenient, because MVVM provides two-way binding of data. Note: the two-way binding of data is provided by VM.
2, Vue basic usage
install
compatibility
Vue does not support IE8 and below because Vue uses ECMAScript 5 features that IE8 cannot emulate. But it supports all ECMAScript 5 compatible browser.
Semantic version control
The functions and behaviors that Vue publishes in all its projects follow Semantic version control . For unpublished or internally exposed behaviors, the changes will be described in Release notes Yes.
Update log
Latest stable version: 2.6.12
For the update log of each version, see GitHub.
Direct introduction with script <
Download it directly and introduce it with the < script > tag. Vue will be registered as a global variable (similar to jQuery and layer).
Don't use compressed versions in the development environment, or you'll lose all common error related warnings!
Development version: contains complete warning and debugging modes
Production version: warning removed, 33.30KB min+gzip
CDN
For prototyping or learning, you can use the latest version as follows:
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
For the production environment, we recommend linking to a specific version number and build file to avoid unexpected damage caused by the new version:
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script>
If you use native ES Modules, there is also a build file compatible with ES Modules:
<script type="module"> import Vue from 'https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.esm.browser.js' </script>
You can cdn.jsdelivr.net/npm/vue Browse the source code of NPM package.
Vue can also unpkg and cdnjs (the version update of cdnjs may lag slightly).
Please confirm your understanding Different build versions And use the production environment version in your published site to put Vue JS to Vue min.js. This is a smaller build that can bring a faster experience than in a development environment.
NPM
NPM installation is recommended when building large applications with Vue. NPM can communicate well with webpack or Browserify Module packer. At the same time, Vue also provides supporting tools for development Single file component.
# Latest stable version $ npm install vue
Command line tool (CLI)
Vue provides a Official CLI , quickly build complex scaffolds for single page application (SPA). It provides batteries included build settings for modern front-end workflow. It takes only a few minutes to run, with hot reloading, lint verification on save, and builds available in the production environment.
First experience
Vue. The core of JS is a system that allows the use of concise template syntax to declaratively render data into DOM:
code
Introduce Vue through < script > tag JS, Vue will be registered as a global variable.
This is equivalent to adding a Vue constructor in the browser's memory, and then you can create an instance of Vue in the web page. Each Vue application starts by creating a new Vue instance with Vue function:
<div id="app"> <!-- {{}}The usage of is called interpolation expression --> {{ message }} </div>
<script src="js/vue.js"></script> <!-- When we introduce vue.js after,Will put Vue Register as a global variable; --> <script> // vue global variable is used to create vue instance object; vue instance object is the VM in our MVVM // The Vue constructor needs to pass a configuration object // What does VM do? Monitor the change of View data, and then modify the data of Model; The Model data is changed and fed back to the View const vm = new Vue({ // VM instances are equivalent to VM view models // el - > element, let vue instance object manage and control an html element, and define the id selector of the element in el el: "#app", // Data is the data needed to store the view data: { message: "Hello Vue" } }) </script>
We have successfully created the first Vue application! It looks very similar to rendering a string template, but Vue does a lot of work behind it. Now that the data and DOM have been associated, everything is responsive. How do we confirm? Open your browser's JavaScript console (which opens on this page) and modify VM Message, you will see that the above example is updated accordingly.
Note that we no longer interact directly with HTML. A Vue application mounts it to a DOM element (in this case #app) and then takes full control of it. That HTML is our entry, but the rest will happen inside the newly created Vue instance.
Although it does not fully follow the MVVM model, Vue's design is also inspired by it. Therefore, the variable name VM (short for ViewModel) is often used in official documents to represent Vue instances.
Through the instructions provided by Vue, it is convenient to render the data to the page, and programmers no longer operate DOM elements manually. In fact, frameworks such as Vue do not encourage us to manually operate DOM elements
[practice]
There are the following product information:
var shopData={ goodsName:"Glory 9", price:"1888", soldCount:1500 }
Try to load the data in the web page using Vue
<div> <ul> <li> <h3>Trade name</h3><b>xxx element</b><span>Sold xxx piece</span > </li> </ul> </div>
[summary]
-
#app is our v
-
The Vue object from new is the scheduler VM in MVVM
-
There are both v and vm. What about model
-
It is the data of the data attribute, which is specially used to save the data of the page
When a Vue instance is created, it adds all the properties in the data object to the Vue's responsive system. When the values of these properties change, the view will produce a "response", that is, the match is updated to the new value.
Vue developer tools debugging
When using Vue, we recommend installing it on your browser Vue Devtools . It allows you to review and debug Vue applications in a more friendly interface.
1. Drag the Chorme plug-in to the Chorme extension program;
2. In the extension program, the Vue plug-in is fixed and displayed
3. Vue menu item will be displayed in the developer tool
[the external link image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-dF8tO7IG-1619407373099)(images / wechat screenshot _20201027151446.png)]
4. You can see the data in memory in the tool
[the external link image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-79RwPLum-1619407373100)(images / wechat screenshot _20201027151551.png)]
Understand Vue's MVVM
The following figure not only summarizes the MVVM pattern (Model View view Model), but also describes the MVVM pattern in Vue How ViewModel interacts with View and Model in JS.
[the external chain picture transfer fails, and the source station may have anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-yWHzjpa1-1619407373102)(images/%E5%BE%AE%E4%BF%A1%E6%88%AA%E5%9B%BE_20201025224354.png)]
ViewModel is Vue JS, which is a Vue instance. Vue instances act on an HTML element, which can be the body element of HTML or an element with an id specified.
ViewModel is bidirectional binding.
After creating the ViewModel, how is bidirectional binding achieved?
Core idea:
DOM Listeners and Data Bindings are two tools, which are the key to realizing two-way binding.
From the View side, the DOM Listeners tool in the ViewModel will help us monitor the changes of DOM elements on the page. If there are changes, change the data in the Model;
From the Model side, when we update the data in the Model, the Data Bindings tool will help us update the DOM elements in the page.
Template syntax
Vue.js uses an HTML based template syntax that allows developers to declaratively bind the DOM to the data of the underlying Vue instance. All Vue JS templates are legal HTML, so they can be parsed by standard browsers and HTML parsers.
In the underlying implementation, Vue compiles the template into a virtual DOM rendering function. Combined with the response system, Vue can intelligently calculate how many components need to be re rendered and minimize the number of DOM operations.
If you are familiar with virtual DOM and prefer the original power of JavaScript, you can also write render functions directly without templates and use optional JSX syntax.
Element data binding
Interpolation expression
The most common form of data binding is text interpolation using "Mustache" syntax (double braces):
<span>Message: {{ msg }}</span>
The Mustache tag will be replaced with the value of msg property on the corresponding data object. Whenever the msg property on the bound data object changes, the content of the interpolation will be updated.
But there is a drawback. When the network is slow, the web page is still loading Vue JS, which causes Vue to have no time to render. At this time, the page will display the Vue source code. We can use the v-cloak instruction to solve this problem.
<!--view--> <div id="root"> <h1 v-cloak>{{msg}}</h1> </div> <script type="text/javascript"> var vm = new Vue({ el: "#root", data: { msg: "Hello Vue" } }) </script>
In simple projects, using the v-cloak instruction is a good way to solve the screen flicker. In this case, we only need to use the empty webp route element in the project, but we only need to use the empty webp route element in the project.
By using the v-once instruction, you can also perform one-time interpolation. When the data changes, the content of the interpolation will not be updated. But please note that this will affect other data binding on this node:
<span v-once>This will not change: {{ msg }}</span>
v-text
Update the textContent of the element. If you want to update the textContent of a part, you need to use {Mustache}} interpolation.
The specific usage is to add a v-text attribute to an element in the mount point, and the attribute value is an attribute of data in the instance;
<div id="root"> <!-- Equivalent to{{}} --> <p v-text="msg"></p> <p v-text="htmlMsg"></p> </div> <script type="text/javascript"> var vm = new Vue({ el: "#root", data: { msg: "Hello Vue", htmlMsg: "<span>Hello Vue</span>" } }) </script>
v-html
The interpolation expression / v-text interprets the data as plain text rather than HTML code. In order to output real HTML, you need to use v-html
<div id="root"> <p>Use interpolation expressions: {{ rawHtml }}</p> <p>use v-html instructions: <span v-html="rawHtml"></span></p> </div> <script type="text/javascript"> var vm = new Vue({ el: "#root", data: { rawHtml: "<span style='color:red'>Hello Vue</span>" } }) </script>
Attribute data binding
Mustache syntax cannot be used on HTML attribute s. In this case, you should use the v-bind instruction:
grammar
<div v-bind:id="dynamicId"></div>
code
Dynamically bind URLs to hyperlinks or images;
<div id="root"> <!-- The following two grammars are wrong,Vue Parsing failed --> <!-- <a href="{{linkUrl}}">use Baidu Search</a> <img src="{{imgUrl}}" alt=""> --> <a v-bind:href="linkUrl">use Baidu Search</a> <img v-bind:src="imgUrl" alt=""> </div> <script type="text/javascript"> var vm = new Vue({ el: "#root", data: { linkUrl: "https://www.baidu.com", imgUrl: "https://cn.vuejs.org/images/logo.png" } }) </script>
For Boolean attribute s (their existence means the value is true), v-bind works slightly differently. In this example:
<div id="root"> <button v-bind:disabled="isButtonDisabled">Button</button> </div> <script type="text/javascript"> var vm = new Vue({ el: "#root", data: { // isButtonDisabled: true isButtonDisabled: fasle } }) </script>
If the value of isButtonDisabled is null, undefined, or false, the disabled attribute will not even be included in the rendered < button > element.
Using JavaScript expressions
So far, in our template, we have only bound simple property key values. But in fact, for all data bindings, Vue JS provides full JavaScript expression support.
code
<div id="root"> {{ number + 1 }} {{ ok ? 'YES' : 'NO' }} {{ message.split('').reverse().join('') }} {{like.toUpperCase()}} <div v-bind:id="'list-' + id"></div> </div> <script type="text/javascript"> var vm = new Vue({ el: "#root", data: { number: 100, ok: true, message: "I love you!", like: "i like Web", id: "demo" } }) </script>
Vue will be parsed as the data of these expressions under the scope of JavaScript. One limitation is that each binding can only contain a single expression, so the following examples will not take effect.
<!-- This is a statement, not an expression --> {{ var a = 1 }} <!-- Flow control will not take effect, please use ternary expression --> {{ if (ok) { return message } }}
Template expressions are placed in sandboxes and can only be accessed A whitelist of global variables , such as Math and Date. You should not attempt to access user-defined global variables in template expressions.
Event binding
Add attribute command for element: v-on: event name = "method name", and the method needs to be defined in the methods attribute in Vue configuration
code
<div id="root"> <h1 v-on:click="clickHandle1" v-cloak>{{msg1}}</h1> <h1 v-on:click="clickHandle2" v-cloak>{{msg2}}</h1> </div> <script type="text/javascript"> // Requirement: click h1 to convert the words inside into uppercase var vm = new Vue({ el: "#root", data: { msg1: "hello world!", msg2: "javascript" }, methods: { clickHandle1: function () { this.msg1 = this.msg1.toUpperCase(); }, clickHandle2: function () { this.msg2 = this.msg2.toUpperCase(); } } }) </script>
In the original knowledge, the DOM is operated when the web page content is changed, but the DOM is not operated in vue. When the data changes, the vm module of vue framework will automatically process and display it to the view layer.
abbreviation
As a visual cue, the v-prefix is used to identify Vue specific attribute s in the template. When you're using Vue When JS adds dynamic behavior to existing tags, the v-prefix is very helpful. However, for some frequently used instructions, it will feel cumbersome to use. At the same time, when building all templates managed by Vue Single page application (SPA - single page application) The v-prefix also becomes less important. Therefore, Vue provides specific abbreviations for the two most commonly used instructions, v-bind and v-on:
v-bind abbreviation
<!-- Complete grammar --> <a v-bind:href="url">...</a> <!-- abbreviation --> <a :href="url">...</a>
v-on abbreviation
<!-- Complete grammar --> <a v-on:click="doSomething">...</a> <!-- abbreviation --> <a @click="doSomething">...</a>
They may look slightly different from normal HTML, but: and @ are legal characters for attribute names and can be correctly parsed in all Vue enabled browsers. Also, they do not appear in the final rendered markup. Abbreviation grammars are completely optional, but as you learn more about their role, you'll be glad to have them.
summary
In a vue instance:
The mount point is bound by the el attribute
The data model is provided by data
The method collection is provided by the methods property.
In vue environment, it is not DOM oriented programming, but data oriented programming
Calculate properties and listeners
Calculation properties
The expressions in the template are very convenient, but they are designed for simple operations. Putting too much logic in the template will make the template too heavy and difficult to maintain. For example:
<div id="root"> {{ message.split('').reverse().join('') }} </div> <script type="text/javascript"> new Vue({ el: "#root", data: { message:"Hello VUE" } }) </script>
In this place, templates are no longer simple declarative logic. You have to look for a while to realize that here is the flipped string of the variable message you want to display. When you want to reference the flipped string here multiple times in the template, it will be more difficult to deal with.
Therefore, for any complex logic, you should use computational properties.
Basic example
Personal understanding: calculate an attribute, which will become the attribute of data.
<div id="root"> <p>original message: "{{ message }}"</p> <p>The inverse string obtained by calculating the attribute: "{{ reversedMessage }}"</p> </div> <script type="text/javascript"> new Vue({ el: "#root", data: { message: "Hello" }, computed: { // Calculate the getter of the property reversedMessage() { //`this ` points to the vm instance return this.message.split('').reverse().join('') } } }) </script>
Here we declare a calculation property reversedMessage. The function we provide will be used as the property VM getter function of reversedMessage:
console.log(vm.reversedMessage) // => 'olleH' vm.message = 'Goodbye' console.log(vm.reversedMessage) // => 'eybdooG'
You can open the browser console and modify the VM in the example by yourself. vm. The value of reversedmessage always depends on VM The value of message.
You can bind the calculation property in the template as you bind the ordinary property. Vue knows VM Reversedmessage depends on VM Message, so when VM When message changes, all dependent VMS The binding of reversedmessage will also be updated. And the best thing is that we have created this dependency declaratively: the getter function that calculates the attribute has no side effects, which makes it easier to test and understand.
<div id="root"> <p>Full name: "{{ fullName }}"</p> <p>full name: "{{ firstName }}" , name: "{{lastName}}"</p> </div> <script type="text/javascript"> const vm = new Vue({ el: "#root", data: { firstName: 'Zhang', lastName: 'Sanfeng' }, computed: { fullName: function () { return this.firstName + this.lastName } } }) </script>
Calculate attribute cache vs method
You may have noticed that we can achieve the same effect by calling methods in expressions.
<div id="root"> <p>Reverse string: "{{ reversedMessage() }}"</p> </div> <script type="text/javascript"> const vm = new Vue({ el: "#root", data: { message: "Hello" }, // In component methods: { reversedMessage() { //`this ` points to the vm instance return this.message.split('').reverse().join('') } } }) </script>
We can define the same function as a method rather than a calculated attribute. The final result of the two methods is exactly the same. However, the difference is that the calculated attributes are cached based on their responsive dependencies. They are re evaluated only when the relevant responsive dependencies change. This means that as long as the message has not changed, multiple accesses to the reversedMessage calculation property will immediately return the previous calculation result without executing the function again.
This also means that the following calculated properties will not be updated because of date Now() is not a responsive dependency:
computed: { now: function () { return Date.now() } }
In contrast, whenever a re rendering is triggered, the calling method will always execute the function again.
Why do we need caching? Suppose we have A computing attribute A with high performance overhead, which needs to traverse A huge array and do A lot of calculations. Then we may have other computational properties that depend on A. If there is no cache, we will inevitably execute A's getter many times! If you don't want to have A cache, use method instead.
Calculate the setter of the property
By default, there is only getter for calculating properties, but you can also provide a setter when necessary:
<div id="root"> <p>Full name: "{{ fullName }}"</p> <p>full name: "{{ firstName }}" , name: "{{lastName}}"</p> </div> <script type="text/javascript"> const vm = new Vue({ el: "#root", data: { firstName: 'Zhang', lastName: 'Sanfeng' }, computed: { fullName: { // getter get: function () { return this.firstName + this.lastName }, // setter set: function (newValue) { this.firstName = newValue.substr(0, 1); this.lastName = newValue.substr(1); } } } }) </script>
Now run the console: VM Fullname = "Zhang Xiaoming", setter will be called, VM Firstname and VM LastName will be updated accordingly.
Note: the calculation attribute is not difficult to use, but the difficulty is that you don't know when to use the calculation attribute; When a value we need is calculated from the data in data (depending on the data in data), we need to use the calculation attribute; The advantages are: if the data associated with the calculation attribute changes, the calculation attribute will also change; Cache computing attributes to improve efficiency;
Listener
Although computed properties are more appropriate in most cases, sometimes a custom listener is required. This is why Vue provides a more general way to respond to changes in data through the watch option. This approach is most useful when asynchronous or expensive operations need to be performed when data changes.
When the binding data inside the mount point changes, if we need to execute some handlers to process the business logic, we can use the listener watch attribute of vue.
code
For example, we want to add the listening function to the first name and last name, that is, when the input content changes, the number of changes will be displayed in the web page.
<div id="root"> surname: <input type="text" v-model="firstName"/> <br> name: <input type="text" v-model="lastName"/> <p>Full name: "{{ fullName }}"</p> <p>full name: "{{ firstName }}" , name: "{{lastName}}"</p> <p>It happened {{num}} Secondary change</p> </div> <script type="text/javascript"> let vm = new Vue({ el: "#root", data: { firstName: 'Zhang', lastName: 'Sanfeng', num:0 }, computed: { fullName: { // getter get: function () { return this.firstName + this.lastName }, // setter set: function (newValue) { this.firstName = newValue.substr(0,1); this.lastName = newValue.substr(1); } } }, watch:{ //When the name changes, do something firstName:function(){ return this.num++; }, lastName:function(){ return this.num++; } } }) </script>
[exercise] use vue to make calculator
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-ud3ju8Xg-1619407373103)(images/clip_image053.jpg)]
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-KD6Wrq23-1619407373104)(images/clip_image055.jpg)]
Class is bound to Style
The class list and inline style of operation elements are a common requirement of data binding. Because they are all strings, we only need to calculate the result through the expression: v-bind. However, string splicing is cumbersome and error prone. Therefore, when using v-bind for class and style, Vue JS has been specially enhanced. In addition to string, the type of expression result can also be object or array.
Bind HTML Class
Object syntax
We can pass an object to v-bind:class to dynamically switch class:
<div id="root"> <div v-bind:class="{ active: isActive }"></div> </div> <script type="text/javascript"> new Vue({ el: "#root", data: { isActive:true } }) </script>
The above syntax indicates that the existence of active class will depend on whether the data attribute isActive is true or false.
You can dynamically switch multiple classes by passing in more fields in the object. In addition, the v-bind:class instruction can also coexist with the ordinary class attribute. When there are the following templates:
<div class="static" v-bind:class="{ active: isActive, 'text-danger': hasError }"> </div>
And the following data:
data: { isActive: true, hasError: false }
The result is rendered as:
<div class="static active"></div>
When isActive or hasError changes, the class list will be updated accordingly. For example, if the value of hasError is true, the class list will change to "static active text danger".
The bound data object does not need to be defined inline in the template:
<div v-bind:class="classObject"></div>
data: { classObject: { active: true, 'text-danger': false } }
The rendering result is the same as above. We can also bind a calculated property of the return object here. This is a common and powerful pattern:
<div id="root"> <div v-bind:class="classObject"></div> </div> <script type="text/javascript"> new Vue({ el: "#root", data: { isActive: true, error: null }, computed: { classObject: function () { return { active: this.isActive && !this.error, 'text-danger': this.error && this.error.type === 'fatal' } } } }) </script>
Array syntax
We can pass an array to v-bind:class to apply a class list:
<div id="root"> <div v-bind:class="[activeClass, errorClass]"></div> </div> <script type="text/javascript"> new Vue({ el: "#root", data: { activeClass: 'active', errorClass: 'text-danger' } }) </script>
Render as:
<div class="active text-danger"></div>
If you also want to switch class es in the list according to conditions, you can use ternary expression:
<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
Writing this way will always add errorClass, but only add activeClass if isActive is true.
However, it is cumbersome to write this when there are multiple conditional class es. Therefore, object syntax can also be used in array syntax:
<div v-bind:class="[{ active: isActive }, errorClass]"></div>
Used on components
This chapter requires you to have a certain understanding of Vue components. Of course, you can skip here and look back later.
When using class property on a custom component, these classes will be added to the root element of the component. Classes that already exist on this element will not be overwritten.
For example, if you declare this component:
Vue.component('my-component', { template: '<p class="foo bar">Hi</p>' })
Then add some class es when using it:
<my-component class="baz boo"></my-component>
The HTML will be rendered as:
<p class="foo bar baz boo">Hi</p>
The same applies to class es with data binding:
<my-component v-bind:class="{ active: isActive }"></my-component>
When isActive is true, HTML will be rendered as:
<p class="foo bar active">Hi</p>
Use inline style
Object syntax
``The object syntax of v-bind:style ` is very intuitive - it looks very much like CSS, but it's actually a JavaScript object. CSS property names can be named with camel case or kebab case (remember to enclose them in quotation marks):
<div id="root"> <div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"> Hello EveryOne </div> </div> <script type="text/javascript"> new Vue({ el: "#root", data: { activeColor: 'red', fontSize: 30 } }) </script>
It is usually better to bind directly to a style object, which makes the template clearer:
<div v-bind:style="styleObject"></div>
data: { styleObject: { color: 'red', fontSize: '13px' } }
Similarly, object syntax is often used in conjunction with the calculated properties of the returned object.
Array syntax
The array syntax of v-bind:style can apply multiple style objects to the same element:
<div id="root"> <div v-bind:style="[baseStyles, overridingStyles]">Hello</div> </div> <script type="text/javascript"> new Vue({ el: "#root", data: { baseStyles: { color: 'red', fontSize: '30px' }, overridingStyles: { fontSize: '14px', background: "yellow" } } }) </script>
Auto prefix
When v-bind:style is used, it needs to be added Browser engine prefix CSS property, such as transform, Vue JS will automatically detect and add the corresponding prefix.
conditional rendering
v-if
The v-if instruction is used to render a piece of content conditionally. This content will only be rendered when the expression of the instruction returns the value of true.
We can assign Boolean value to v-if to realize the display and hiding of html elements
For example, if you want to hide an element in the mount point:
<div id="root"> <div v-if=false> Show or hide </div> </div>
In fact, the function of direct assignment is the same as that of the following structure:
<div id="root"> <div v-if="showHide"> Show or hide </div> </div> <script type="text/javascript"> let vm = new Vue({ el: "#root", data: { showHide:false } }) </script>
Now let's implement a requirement:
Click a button to show and hide an element in the mount point:
<div id="root"> <button type="button" @click="showHideMethod">Click display/hide</button> <div v-if="showHide" style="width: 220px;height: 120px;background: red;"> Show or hide </div> </div> <script type="text/javascript"> let vm = new Vue({ el: "#root", data: { showHide:false }, methods:{ showHideMethod(){ this.showHide = !this.showHide } } }) </script>
Use v-if conditional rendering groups on < template > elements
Because v-if is an instruction, it must be added to an element. But what if you want to switch multiple elements? At this point, you can treat a < template > element as an invisible wrap element and use v-if on it. The final render will not contain the < template > element.
<template v-if=true> <h1>Title</h1> <p>Paragraph 1</p> <p>Paragraph 2</p> </template>
v-else
You can use the v-else instruction to represent the "else block" of v-if:
<div id="root"> <div v-if="Math.random() > 0.5"> Random value greater than 0.5 </div> <div v-else> Random value less than or equal to 0.5 </div> <p v-if="sex == 'male'"> <input type="radio" name="sex" checked>male <input type="radio" name="sex">female </p> <p v-else> <input type="radio" name="sex">male <input type="radio" name="sex" checked>female </p> </div>
``The v-else element must follow the element with v-if or v-else-if ', otherwise it will not be recognized.
[exercise] create two div s, box1 and box2. When you click the button, switch back and forth the hiding and display of box1 and box2
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-p6N3Ce7D-1619407373106)(images/clip_image064.jpg)]
v-else-if
v-else-if, as the name suggests, acts as the "else if block" of v-if and can be used continuously:
<div id="root"> <div v-if="type === 'A'"> A </div> <div v-else-if="type === 'B'"> B </div> <div v-else-if="type === 'C'"> C </div> <div v-else> Not A/B/C </div> <h1>What is the result of your performance evaluation:</h1> <p v-if="score >=90 && score <= 100"> excellent </p> <p v-else-if="score >= 75 && score < 90"> good </p> <p v-else-if="score >= 60 && score < 75"> pass </p> <p v-else-if="score < 60 && score > 0"> fail, </p> <p v-else>Invalid score</p> </div> <script type="text/javascript"> let vm = new Vue({ el: "#root", data: { type:'D', score: 118 } }) </script>
Similar to v-else, v-else-if must also follow the element with v-if or v-else-if.
v-show
Another option for displaying elements based on conditions is the v-show instruction. The usage is roughly the same:
<h1 v-show="ok">Hello!</h1>
The difference is that elements with v-show are always rendered and retained in the DOM. V-show simply switches the CSS attribute display of an element.
Note that v-show does not support < template > elements or v-else.
v-if vs v-show
v-if is a "real" conditional rendering because it ensures that event listeners and subcomponents within the conditional block are properly destroyed and rebuilt during switching.
v-if is also lazy: if the condition is false at the initial rendering, nothing is done -- the conditional block does not start rendering until the condition first becomes true.
In contrast, v-show is much simpler -- no matter what the initial conditions are, elements are always rendered and simply switched based on CSS.
Generally speaking, v-if has higher switching overhead, while v-show has higher initial rendering overhead. Therefore, if you need to switch very frequently, it is better to use v-show; If the conditions rarely change at run time, it is better to use v-if.
Use v-if with v-for
Using both v-if and v-for is not recommended. Please refer to Style guide For more information.
When v-if is used with v-for, v-for has a higher priority than v-if. Please refer to List rendering Guide For details.
List rendering
When there are multiple data in the model that need to be displayed in the view, I can use the v-for instruction to operate
Use v-for to correspond an array to a group of elements
We can use the v-for instruction to render a list based on an array. The v-for instruction requires a special syntax in the form of item in items, where items is the source data array and item is the alias of the array element being iterated.
<div id="root"> <!--Method 1: General traversal--> <ul> <li v-for="item in goodsList">{{item}}</li> </ul> <!--Method 2: use:key Command to improve cycle efficiency--> <ul> <li v-for="item in goodsList" :key="item">{{item}}</li> </ul> <!--Method 3: more standard usage, embodiment of iterator--> <ul> <li v-for="(item,index) in goodsList" :key="index">{{item}}</li> </ul> </div> <script type="text/javascript"> var vm=new Vue({ el:"#root", data:{ goodsList:["millet","OPPO","Huawei","vivo","hammer","Jin Li","Meizu","360"] } }) </script>
In the v-for block, we can access the properties of all parent scopes. v-for also supports an optional second parameter, the index of the current item.
<div id="root"> <ul> <li v-for="(item,index) of goodsList" :key="item">{{praentMsg}} The first {{index+1}} name: {{ item}}</li> </ul> </div> <script type="text/javascript"> var vm=new Vue({ el:"#root", data:{ parentMessage:"Popular mobile phone", goodsList:["millet","OPPO","Huawei","vivo","hammer","Jin Li","Meizu","360"] } }) </script>
You can also use of instead of in as the separator, because it is closer to the syntax of JavaScript iterators:
<div v-for="item of items"></div>
Using objects in v-for
You can also use v-for to traverse the properties of an object.
<div id="root"> <h3>Class information:</h3> <ul> <li v-for="value in classes"> {{ value }} </li> </ul> </div> <script type="text/javascript"> var vm=new Vue({ el:"#root", data:{ classes: { title: 'Front end shift 41', teacher: 'Jimbo', beginTime: '2019-10-21' } } }) </script>
You can also provide the second parameter as property name (that is, key name):
<div id="root"> <h3>Class information:</h3> <ul> <li v-for="(value,name) in classes"> {{name}} - {{ value }} </li> </ul> </div>
You can also use the third parameter as an index:
<div id="root"> <h3>Class information:</h3> <ul> <li v-for="(value,name,index) in classes"> {{index}} : {{name}} - {{ value }} </li> </ul> </div>
When traversing an object, press object The results of keys () are traversed, but there is no guarantee that its results are consistent under different JavaScript engines.
v-for can also accept integers. In this case, it repeats the template the corresponding number of times.
Maintenance status
When Vue is updating the list of elements rendered using v-for, it defaults to the update in place policy. If the order of data items is changed, Vue will not move DOM elements to match the order of data items, but update each element in place and ensure that they are rendered correctly at each index position.
This default mode is efficient, but only applies to list rendered output that does not depend on subcomponent state or temporary DOM state (e.g. form input value).
In order to give Vue a hint so that it can track the identity of each node and reuse and reorder existing elements, you need to provide a unique key attribute for each item:
<div v-for="item in items" v-bind:key="item.id"> <!-- content --> </div>
It is recommended to provide key attribute when using v-for as much as possible, unless it is very simple to traverse the output DOM content, or deliberately rely on the default behavior to improve performance.
Because it is a general mechanism for Vue to identify nodes, key is not specifically associated with v-for. As we will see later in the guide, it has other uses.
Do not use non basic type values such as objects or arrays as v-for key s. Please use a value of string or numeric type.
For more detailed usage of key attribute, please move to API document of key.
Array update detection
Vue cannot detect changes in the array due to the following restrictions:
- When you use the index to set an array item directly, for example: VM items[indexOfItem] = newValue
- When you modify the length of the array, for example: VM items. length = newLength
for instance:
<div id="root"> <ul> <li v-for="(value,index) in items"> {{index}} - {{ value }} </li> </ul> </div> <script type="text/javascript"> var vm=new Vue({ el:"#root", data:{ items: ['a', 'b', 'c'] } }) </script>
Test via console:
vm.items[1] = 'x' // Not responsive vm.items.length = 2 // Not responsive
Change method
Vue wraps the change method of the array being listened on, so they will also trigger view updates. These wrapped methods include:
- push()
- pop()
- shift()
- unshift()
- splice()
- sort()
- reverse()
You can open the console and try to call the change method on the items array in the previous example. Like VM items. push('D').
In order to solve the first kind of problem, the following two methods can be implemented and VM Items [indexofitem] = newvalue has the same effect, and will also trigger status update in the responsive system:
// Vue.set Vue.set(vm.items, indexOfItem, newValue) // Array.prototype.splice vm.items.splice(indexOfItem, 1, newValue)
Case CRUD
Combined with interpolation expression, event binding and cyclic variables to realize simple CRUD;
<!-- CRUD --> <div id="app"> <ul> <!-- Query: traverse the data to View in --> <li v-for="(person,index) in persons"> {{ person.name }} - {{ person.age }} - <button @click="deletePerson(index)">delete</button> <!-- When you click the Modify button,Not only the modification interface should be displayed,Also display the data to be modified --> <button @click="showAndQuery(index)">modify</button> </li> </ul> <input type="text" v-model="newPerson.name"> <input type="text" v-model="newPerson.age"> <button @click="addPerson">add to</button> <div v-if="updateStatus"> <input type="text" v-model="updatePerson.name"> <input type="text" v-model="updatePerson.age"> <button @click="updatePersonMethod">Submit</button> </div> </div> <script src="../js/vue.js"></script> <script type="text/javascript"> var vm = new Vue({ el: '#app', data: { updateStatus: false, updateIndex: '', newPerson: { name: '', age: '' }, updatePerson: { name: '', age: '' }, persons: [{ name: 'Tom', age: 18 }, { name: 'Jack', age: 17 }, { name: 'Bob', age: 19 }, { name: 'Mary', age: 16 } ] }, methods: { addPerson() { this.persons.push({ name: this.newPerson.name, age: this.newPerson.age }) }, deletePerson(delIndex) { // delIndex parameter this.persons.splice(delIndex, 1) }, updatePersonMethod() { this.persons.splice(this.updateIndex, 1, this.updatePerson); this.updatePerson = { name: '', age: '' } this.updateStatus = false; }, showAndQuery(queryIndex) { this.updateIndex = queryIndex; this.updatePerson.name = this.persons[queryIndex].name; this.updatePerson.age = this.persons[queryIndex].age; this.updateStatus = true; } }, }) </script>
Replace array
Changing methods, as the name suggests, will change the original array that calls these methods. In contrast, there are also non change methods, such as filter(), concat(), and slice(). They do not change the original array, but always return a new array. When using the non change method, you can replace the old array with the new array:
vm.items = vm.items.filter(function (item) { return item > 18; })
You might think this will cause Vue to discard the existing Dom and re render the entire list. Fortunately, this is not the case. Vue implements some intelligent heuristic methods to maximize the reuse of DOM elements, so it is very efficient to replace the original array with an array containing the same elements.
Object update detection
Or because of JavaScript restrictions, Vue cannot detect the addition or deletion of object attributes:
var vm = new Vue({ data: { a: 1 } }) // `vm.a ` is now responsive vm.b = 2 // `vm.b ` not responsive
For instances that have been created, Vue does not allow dynamic addition of root level responsive properties. However, you can use Vue The set (object, propertyname, value) method adds responsive properties to nested objects. For example, for:
var vm = new Vue({ data: { userProfile: { name: 'Anika' } } })
You can add a new age attribute to the nested userProfile object:
Vue.set(vm.userProfile, 'age', 27)
Display filtered / sorted results
Sometimes we want to display the filtered or sorted version of an array without actually changing or resetting the original data. In this case, you can create a calculated property to return the filtered or sorted array.
For example:
<li v-for="n in evenNumbers">{{ n }}</li>
data: { numbers: [ 1, 2, 3, 4, 5 ] }, computed: { evenNumbers: function () { return this.numbers.filter(function (number) { return number % 2 === 0 }) } }
When the calculated attribute is not applicable (for example, in a nested v-for loop), you can use one method:
<ul v-for="set in sets"> <li v-for="n in even(set)">{{ n }}</li> </ul>
data: { sets: [[ 1, 2, 3, 4, 5 ], [6, 7, 8, 9, 10]] }, methods: { even: function (numbers) { return numbers.filter(function (number) { return number % 2 === 0 }) } }
Simple sorting using calculated attributes
<div id="root"> <h1>Original array</h1> <ul> <li v-for="n in numbers">{{n}}</li> </ul> <h1>Even elements in the original array(filter)</h1> <ul> <li v-for="n in evenNumbers">{{n}}</li> </ul> <h1>The result of sorting the original array</h1> <ul> <li v-for="n in sortNumbers">{{n}}</li> </ul> </div> <script src="../js/vue.js"></script> <script type="text/javascript"> var vm = new Vue({ el: "#root", data: { numbers: [12, 2, 36, 4, 51] }, computed: { evenNumbers() { // The first return is the array after the competition return this.numbers.filter(item => { // return the element that matches the result return item % 2 === 0; }) }, sortNumbers() { const arr = [...this.numbers]; return arr.sort(function (a, b) { // The following parameters minus the previous parameters are in descending order return b - a; }) } }, }) </script>
Comprehensive case
Click the button to sort the data in ascending or descending order; Retrieve user name data according to the input content;
<div id="app"> <input type="text" v-model="searchName"> <ul> <li v-for="(p, index) in filterPersons" :key="index"> {{index}}--{{p.name}}--{{p.age}} </li> </ul> <div> <button @click="setOrderType(2)">Ascending order of age</button> <button @click="setOrderType(1)">Age descending order</button> <button @click="setOrderType(0)">Original order</button> </div> </div> <script type="text/javascript" src="../js/vue.js"></script> <script type="text/javascript"> new Vue({ el: '#app', data: { searchName: '', orderType: 0, // 0 means no sorting, 1 means descending, and 2 means ascending persons: [{ name: 'Tom', age: 18 }, { name: 'Jack', age: 17 }, { name: 'Bob', age: 19 }, { name: 'Mary', age: 16 } ] }, computed: { filterPersons() { // Take out relevant data const { searchName, persons, orderType } = this let arr = [...persons] // Filter array if (searchName.trim()) { arr = persons.filter(p => p.name.indexOf(searchName) !== -1) } // sort if (orderType) { arr.sort(function (p1, p2) { if (orderType === 1) { // Descending order return p2.age - p1.age } else { // Ascending order return p1.age - p2.age } }) } return arr } }, methods: { setOrderType(orderType) { this.orderType = orderType } } }) </script>
Use value range in v-for
v-for can also accept integers. In this case, it repeats the template the corresponding number of times.
<div> <span v-for="n in 10">{{ n }} </span> </div>
Use v-for on < template >
Similar to v-if, you can also use < template > with v-for to loop render a piece of content containing multiple elements. For example:
<ul> <template v-for="item in items"> <li>{{ item.msg }}</li> <li class="divider" role="presentation"></li> </template> </ul>
Use v-for with v-if
Note that we do not recommend using v-if and v-for on the same element. More details are available Style guide.
When they are on the same node, v-for has a higher priority than v-if, which means that v-if will run repeatedly in each v-for loop. This priority mechanism is useful when you only want to render nodes for some items, as follows:
<li v-for="todo in todos" v-if="!todo.isComplete"> {{ todo }} </li>
The above code will render only the unfinished todo.
If your goal is to conditionally skip the execution of the loop, you can put v-if on the outer element (or < template >). For example:
<ul v-if="todos.length"> <li v-for="todo in todos"> {{ todo }} </li> </ul> <p v-else>No todos left!</p>
event processing
Listening events
You can use the v-on instruction to listen for DOM events and run some JavaScript code when triggered.
<div id="app"> <button v-on:click="counter += 1">Add 1</button> <p>The button was clicked {{ counter }} second.</p> </div> <script> const vm = new Vue({ el: '#app', data: { counter: 0 } }) </script>
Event handling method
However, many event processing logic will be more complex, so it is not feasible to write JavaScript code directly in v-on instructions. Therefore, v-on can also receive a method name that needs to be called.
<div id="app"> <!-- `greet` Is the method name defined below --> <button v-on:click="greet">Greet</button> </div> <script> const vm = new Vue({ el: '#app', data: { name: 'Vue.js' }, // Define methods in the 'methods' object methods: { greet() { // `this ` points to the current Vue instance in the method alert('Hello ' + this.name + '!') } } }) </script>
Method in inline processor
In addition to being directly bound to a method, you can also call the method in the inline JavaScript statement:
<div id="app"> <!-- When calling a method,Pass the specified parameter --> <button v-on:click="say('hi')">Say hi</button> <button v-on:click="say('what')">Say what</button> </div> <script> const vm = new Vue({ el: '#app', data: { }, methods: { say: function (message) { alert(message) } } }) </script>
Sometimes you also need to access the original DOM events in the inline statement processor. You can pass it into the method with the special variable $event:
<div id="app"> <!-- Click the button to get the label content and pop up --> <button @click="test1">test1</button> <button @click="test2('abc')">test2</button> <button @click="test3('abcd', $event)">test3</button> </div> <script> const vm = new Vue({ el: '#app', data: { }, methods: { // When binding events, no parameters are passed. By default, an Event represents an Event object; It can be used even if it is not explicitly declared test1(event) { alert(event.target.innerHTML) }, // When binding an event, if the parameter is passed, it must represent the value passed in test2(event) { alert(event) }, // If you need to pass parameters and use event objects, you must explicitly pass them in using $event test3(msg, event) { alert(msg + '---' + event.target.textContent) } } }) </script>
Event modifier
Calling event. in event handler Preventdefault() or event Stoppropagation () is a very common requirement. Although we can easily implement this in the method, a better way is that the method only has pure data logic, rather than dealing with DOM event details.
To solve this problem, Vue JS provides event modifiers for v-on. As mentioned earlier, modifiers are represented by the instruction suffix beginning with a dot.
- .stop
- .prevent
- .capture
- .self
- .once
- .passive
<!-- Prevent click events from continuing to propagate --> <a v-on:click.stop="doThis"></a> <!-- Submitting an event no longer reloads the page --> <form v-on:submit.prevent="onSubmit"></form> <!-- Modifiers can be concatenated --> <a v-on:click.stop.prevent="doThat"></a> <!-- Only modifiers --> <form v-on:submit.prevent></form> <!-- Use event capture mode when adding event listeners --> <!-- That is, events triggered by internal elements are processed here first, and then handed over to internal elements for processing --> <div v-on:click.capture="doThis">...</div> <!-- Only when event.target When the current trigger function is itself --> <!-- That is, the event is not triggered from an internal element --> <div v-on:click.self="doThat">...</div>
case
<div id="app"> <a href="http://www.baidu. Com "@click.prevent =" test4 "> Baidu Click</a> <div style="width: 200px;height: 200px;background: red" @click="test5"> <div style="width: 100px;height: 100px;background: blue" @click.stop="test6"></div> </div> </div> <script> const vm = new Vue({ el: '#app', data: { }, methods: { test4() { alert('Click the link,But the default behavior of hyperlinks is blocked!') }, test5() { alert('Outer layer Div') }, test6() { alert('Inner layer Div') }, } }) </script>
When using modifiers, order is important; The corresponding code will be generated in the same order. Therefore, use v-on: click prevent. Self will block all clicks, while v-on: click self. Prevent only blocks clicks on the element itself.
2.1.4 NEW
<!-- The click event will only be triggered once --> <a v-on:click.once="doThis"></a>
Unlike other modifiers that work only on native DOM events The once modifier can also be used in custom Component events Come on. If you haven't read the documentation on components, don't worry now.
Key modifier
When monitoring keyboard events, we often need to check the detailed keys. Vue allows v-on to add key modifiers when listening for keyboard events:
<!-- Only in `key` yes `Enter` Time call `vm.submit()` --> <input v-on:keyup.enter="submit">
You can directly add keyboardevent key ( https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values )Any valid key name exposed is converted to kebab case as a modifier.
<input v-on:keyup.page-down="onPageDown">
In the above example, the handler will only be in $event Called when key equals PageDown.
Key code
It is also allowed to use keyCode attribute:
<input v-on:keyup.13="submit">
In order to support old browsers if necessary, Vue provides aliases for most commonly used key codes:
- .enter
- .tab
- . delete (capture delete and backspace keys)
- .esc
- .space
- .up
- .down
- .left
- .right
case
<div id="app"> <!-- When press enter Key,Pop up the input content --> <input type="text" @keyup.13="test7"> <input type="text" @keyup.enter="test7"> </div> <script> const vm = new Vue({ el: '#app', data: { }, methods: { test7(event) { console.log(event.keyCode) alert(event.target.value) } } }) </script>
Form input binding
Basic usage
You can use the v-model instruction to create two-way data bindings on the < input >, < textarea > and < Select > elements of the form. It will automatically select the correct method to update the element according to the control type. Despite some magic, v-model is essentially just a grammar sugar. It is responsible for monitoring user input events to update data, and some special processing for some extreme scenarios.
``v-model will ignore the initial values of value, checked and selectedattribute of all form elements, and always take the data of Vue instance as the data source. You should declare the initial value in the data 'option of the component through JavaScript.
v-model internally uses different properties for different input elements and throws different events:
- text and textarea elements use value property and input events;
- checkbox and radio use checked property and change events;
- The select field takes value as a prop and change as an event.
Single line text
<!-- v-text v-html One way data binding,data The data inside has changed,The data of the page changes with. v-model Bidirectional data binding data The data inside has changed,The data of the page changes with. Page data changed,data It also changes --> <!-- Now there is a need when users are input When entering some values in the div It can display the input value in real time --> <div id="root" > <input type="text" v-model="inputMsg" placeholder="Please enter the content"/> <input type="text" v-model="inputMsg" /> <div id="showDiv"> {{inputMsg}} </div> </div> <script type="text/javascript"> var vm = new Vue({ //Mount point el:"#root", //element, indicating which element in the page needs to be managed through vue (el commonly referred to as mount point) //Model layer, data that can be used by mount point data:{ //Data managed by vue inputMsg:"" } }) </script>
Multiline text
<div id="root"> <span>The contents of the multiline text box are:</span> <p style="white-space: pre-line;">{{ multilineMsg }}</p> <br> <textarea v-model="multilineMsg" placeholder="Please enter the contents of the multiline text box" style="width: 300px;height: 120px;resize: none;"></textarea> </div> <script type="text/javascript"> new Vue({ el:"#root", data:{ multilineMsg:"" } }) </script>
Note: interpolation in the text area (< textarea > {{text} < / textarea >) does not take effect, so v-model should be used instead.
check box
Single check box, bound to Boolean:
<div id="root"> <input type="checkbox" id="checkbox" v-model="checked"> <label for="checkbox">{{ checked }}</label> </div> <script type="text/javascript"> new Vue({ el:"#root", data:{ checked:true } }) </script>
Multiple check boxes bound to the same array:
<div id="root"> <input type="checkbox" id="jack" value="Jack" v-model="checkedNames"> <label for="jack">Jack</label> <input type="checkbox" id="john" value="John" v-model="checkedNames"> <label for="john">John</label> <input type="checkbox" id="mike" value="Mike" v-model="checkedNames"> <label for="mike">Mike</label> <br> <span>Checked names: {{ checkedNames }}</span> </div> <script type="text/javascript"> new Vue({ el:"#root", data:{ checkedNames: [] } }) </script>
radio button
<div id="root"> <input type="radio" id="one" value="One" v-model="picked"> <label for="one">One</label> <br> <input type="radio" id="two" value="Two" v-model="picked"> <label for="two">Two</label> <br> <span>Picked: {{ picked }}</span> </div> <script type="text/javascript"> new Vue({ el:"#root", data:{ picked: '' } }) </script>
Selection box
Single choice
<div id="root"> <select v-model="selected"> <option disabled value="">Please select</option> <option>A</option> <option>B</option> <option>C</option> </select> <span>Selected: {{ selected }}</span> </div> <script type="text/javascript"> new Vue({ el:"#root", data:{ selected: '' } }) </script>
If the initial value of the v-model expression fails to match any of the options, < Select > elements are rendered as "unchecked". In iOS, this prevents the user from selecting the first option. Because in this case, iOS will not trigger the change event. Therefore, it is more recommended to provide a disabled option with a blank value as above.
When multiple selections are made (bound to an array):
<div id="root"> <select v-model="selected" multiple style="width: 50px;"> <option>A</option> <option>B</option> <option>C</option> </select> <br> <span>Selected: {{ selected }}</span> </div> <script type="text/javascript"> new Vue({ el:"#root", data:{ selected: [] } }) </script>
Dynamic options for rendering with v-for:
<div id="root"> <select v-model="selected"> <option v-for="option in options" v-bind:value="option.value"> {{ option.text }} </option> </select> <span>Selected: {{ selected }}</span> </div> <script type="text/javascript"> new Vue({ el: "#root", data: { selected: 'A', options: [{ text: 'One', value: 'A' }, { text: 'Two', value: 'B' }, { text: 'Three', value: 'C' } ] } }) </script>
Modifier
.lazy
By default, v-model synchronizes the value of the input box with the data after each input event is triggered (except above Input method (when combining text). You can add the lazy modifier to turn it into a change event_ After_ Synchronize:
<!-- In“ change"Sometimes not“ input"Update when --> <input v-model.lazy="msg" >
.number
If you want to automatically convert the user's input value to numeric type, you can add the number modifier to the v-model:
<input v-model.number="age" type="number">
This is often useful because even when type="number", the value of the HTML input element always returns a string. If this value cannot be parsed by parseFloat(), the original value is returned.
.trim
If you want to automatically filter the first and last white space characters entered by the user, you can add the trim modifier to the v-model:
<input v-model.trim="msg">
Effect of walking lantern
Click the move button to move the text content to the left, place the first text at the end of the text, and execute this effect again every 0.5 seconds; Click the stop button and the text stops moving.
The tips are as follows:
<div id="root"> <!-- Add event to button --> <button type="button" @click="start">Start walking the lantern</button> <button type="button" @click="stop">Stop the lantern</button> <h3>{{msg}}</h3> </div> <script type="text/javascript"> new Vue({ el: "#root", data: { msg: "No one has me, some people have me", interId: "" } }) </script>
Analysis and Implementation:
1. Bind click event to start button
2. In the time processing program of the button, write the business logic code: get the string of msg, then intercept the first character, and then put it at the end of the string;
3. Use setInterval() to store the business code of the second part and execute it repeatedly
Code implementation:
<div id="root"> <!-- Add event to button --> <button type="button" @click="start">Start walking the lantern</button> <button type="button" @click="stop">Stop the lantern</button> <h3>{{msg}}</h3> </div> <script type="text/javascript"> new Vue({ el: "#root", data: { msg: "No one has me, some people have me", interId: "" }, methods: { start() { this.interId = setInterval(() => { var firstStr = this.msg.substr(0, 1); var lastStr = this.msg.substr(1); this.msg = lastStr + firstStr; }, 500) }, stop() { clearInterval(this.interId) } } }) </script>
Life cycle of Vue instance
Life cycle overview
What is the life cycle? From the creation, running and destruction of Vue instances, there are always a variety of events. These events are called the life cycle.
When each Vue instance is created, it goes through a series of initialization processes -- for example, setting data listening, compiling templates, mounting the instance to the DOM and updating the DOM when the data changes, etc. At the same time, some functions called life cycle hooks will be run in this process, which gives users the opportunity to add their own code at different stages.
For example, the created hook can be used to execute code after an instance is created:
new Vue({ data: { a: 1 }, created: function () { // `this ` points to the vm instance console.log('a is: ' + this.a) } }) // => "a is: 1"
There are also other hooks that are invoked at different stages of the instance life cycle, such as mounted,updated and destroyed . The this context of the lifecycle hook points to the Vue instance that invokes it.
Do not use on option properties or callbacks Arrow function For example, created: () = > console Log (this. A) or VM$ watch('a', newValue => this.myMethod()). Because there is no this in the arrow function, this will be used as a variable to search the upper lexical scope until it is found, which often leads to Uncaught TypeError: Cannot read property of undefined or uncaught typeerror: this Mymethod is not a function.
Life cycle diagram
The following figure shows the life cycle of an instance. You don't need to understand everything immediately, but as you continue to learn and use it, its reference value will be higher and higher.
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-ckq8gFeJ-1619407373111)(images/lifecycle.png)]
Life cycle hook: that is, the life cycle function, that is, the alias of life cycle events.
Main life cycle function categories:
Lifecycle functions in the creation / initialization phase (4 functions):
Life cycle functions in the run / update phase (2 functions):
Life cycle function of destruction phase (2 functions):
beforeCreate()
After instance initialization, data observation and event configuration are called before. At this time, the option object of the component has not been created, and el and data have not been initialized. Therefore, methods, data, computed and other methods and data cannot be accessed.
Conclusion: beforeCreated lifecycle function: Elements in data, methods and DOM cannot be accessed
<div id="root"> {{msg}} </div> <script type="text/javascript"> new Vue({ el:"#root", data: { msg:"vuejs" }, methods:{ act(){ console.log(this.msg) } }, //When the beforeCreate() lifecycle function is executed, the data in data and methods has not been initialized beforeCreate(){ console.log(this.msg);//undefined this.act(); // Error: this act is not a function } }) </script>
created()
After the instance has been created, it is called. In this step, the instance has completed the following configuration: data observation, operation of properties and methods, callback of watch/event events, initialization of data data, and el has not. However, the mount phase has not yet started, and the $el attribute is not visible at present. This is a common life cycle, because you can call the methods in methods, change the data in data, and modify it. It can be reflected on the page through the responsive binding of vue, obtain the calculated attributes in calculated, etc. some people like to send ajax requests here. It is worth noting that, In this cycle, there is no method to intercept the instantiation process. Therefore, if some data must be obtained before entering the page, it is not suitable to send a request in this method. It is recommended to complete it in the component routing hook beforeRouteEnter.
<div id="root"> {{msg}} </div> <script type="text/javascript"> new Vue({ el:"#root", data: { msg:"vuejs" }, methods:{ act(){ console.log(this.msg) } }, //In the created() life cycle function, the data in data and methods have been initialized //If you call a method in methods or manipulate data, you must start with created at the earliest created(){ console.log(this.msg); //vuejs this.act(); //vuejs } }) </script>
beforeMount()
It is called before the mount starts, and the relevant render function is called for the first time (virtual DOM). The instance has completed the following configuration: compile the template, generate html from the data and template in data, and complete the initialization of el and data. Note that it has not been hung on the html page at this time.
<div id="root"> {{msg}} </div> <script type="text/javascript"> new Vue({ el:"#root", data: { msg:"vuejs" }, methods:{ act(){ console.log(this.msg) } }, //The beforeMount() life cycle function indicates that the mount point is not applied to the data if it runs before the mount //This stage indicates that the template has been edited in memory, but the template has not been rendered to the page. The content in the DOM has not been replaced, but some template strings have been written //data and methods can be accessed, but the exact dom value cannot be accessed beforeMount(){ var txt = document.getElementById("root").innerHTML; console.log(txt) //{{msg}} } }) </script>
mounted()
After mounting, that is, the HTML in the template is rendered into the HTML page. At this time, you can generally do some ajax operations, and mounted will only execute it once.
Once mounted is executed, it means that the entire Vue instance has been initialized. At this time, the component has left the creation phase and entered the running phase
<div id="root"> {{msg}} </div> <script type="text/javascript"> new Vue({ el:"#root", data: { msg:"vuejs" }, methods:{ act(){ console.log(this.msg) } }, //Indicates that the edited template in memory has been attached to the page, and the user can see the data rendered to the page //mounted() is the last function to declare the period of the instance creation cycle. When mounted is executed, it means that the instance has been created //You can access data and methods, and you can also get real dom data mounted(){ var txt = document.getElementById("root").innerHTML; console.log(txt) //vuejs } }) </script>
beforeUpdate()
When the data of the component or instance is changed, it will execute beforeUpdate immediately, and then vue's virtual dom mechanism will rebuild the virtual dom, compare it with the last virtual dom tree and re render it with diff algorithm. Generally, nothing is done.
During component operation, there are only two lifecycle functions beforeUpdate and updated.
At the execution time in BeforeUpdate (), the interface has not been updated. Has the data been updated?? Of course, it is updated, otherwise it will not activate beforeUpdate();
[case] modify the data and detect the execution time of beforeUpdate()
<div id="root"> <p>{{msg}}</p> <button type="button" @click="act">Click Modify msg Data</button> </div> <script type="text/javascript"> new Vue({ el:"#root", data: { msg:"vuejs" }, methods:{ act(){ console.log(this.msg+="!!!!!!") } }, //Conclusion: when executing beforeUpdate(), the data displayed in the page is still old, but the data of data is new, but it has not been rendered into the page beforeUpdate(){ console.log("data The data inside:"+this.msg); //Data in data: vuejs!!!!!! var txt = document.getElementById("root").querySelector('p').innerHTML; console.log("Data in page:"+txt) //Data in page: vuejs } }) </script>
beforeUpdate lifecycle function:
When the page is refreshed and the data is not changed, the function will not be executed. The function will be entered only after the data is changed;
Indicates that the data in the data has been updated, but only the vm in the memory has been updated and has not been updated to the dom tree;
You can access data, method and the latest value
The value of the element in dom can also be accessed, but the old value before the change is obtained;
vue instance is running
updated()
When the update is completed, execute updated. The data has been changed and dom is re render ed.
<div id="root"> <p>{{msg}}</p> <button type="button" @click="act">Click Modify msg Data</button> </div> <script type="text/javascript"> new Vue({ el:"#root", data: { msg:"vuejs" }, methods:{ act(){ console.log(this.msg+="!!!!!!") } }, //Conclusion: when updated is executed, the data and the data in the page are up to date updated(){ console.log("data The data inside:"+this.msg); //Data in data: vuejs!!!!!! var txt = document.getElementById("root").querySelector('p').innerHTML; console.log("Data in page:"+txt) //Data in the page: vuejs!!!!!! } }) </script>
updated lifecycle function:
The data representing data and dom tree are up-to-date
You can access the values of data, methods and dom elements, and you can access the latest values
vue instance is running
Beforedestruction() and destroyed()
After calling the $destroy method in some way, execute beforeDestroy immediately. Generally, do some aftercare work here, such as clearing timers, clearing non instruction bound events, and so on.
When the beforeDestory() method is executed, the Vue instance has entered the destruction phase from the running phase;
Data binding and monitoring of components... Only the empty dom shell is left after being removed. At this time, execute destroyed and do the aftermath work here
When beforeDestory() is executed, all data and methods, filters and instructions on the instance are available. At this time, the destruction process has not been really executed.
When the destroyed() method is executed, the filters, instructions and methods in the Vue component are unavailable.
Common life cycle methods:
created()/mounted(): send ajax requests and start asynchronous tasks such as timers
beforeDestory(): finish work, such as clearing the timer
Life cycle demonstration case
Demo: show or hide p elements every 1s when the page is opened;
Demo: execution process of life cycle function
<div id="test"> <button @click="destroyVue">destory vue</button> <p v-if="isShow">New Cape Education</p> </div> <script type="text/javascript"> new Vue({ el: '#test', data: { isShow: true }, beforeCreate() { console.log('beforeCreate()') }, created() { console.log('created()') }, beforeMount() { console.log('beforeMount()') }, mounted() { console.log('mounted()') // Perform asynchronous tasks this.intervalId = setInterval(() => { console.log('-----') this.isShow = !this.isShow }, 1000) }, beforeUpdate() { console.log('beforeUpdate()') }, updated() { console.log('updated()') }, beforeDestroy() { console.log('beforeDestroy()') // Perform closed work clearInterval(this.intervalId) }, destroyed() { console.log('destroyed()') }, methods: { destroyVue() { this.$destroy() } } }) </script>
Transition & Animation
summary
Vue provides application transition effects in many different ways when inserting, updating or removing DOM. Includes the following tools:
- Automatically apply class in CSS transition and animation
- You can use third-party CSS animation libraries, such as animate css
- Use JavaScript in the transition hook function to directly manipulate DOM
- You can use third-party JavaScript animation libraries, such as velocity js
Single element / component transition
Vue provides encapsulated components of transition. In the following cases, entry / exit transitions can be added to any element and component
- Conditional rendering (using v-if)
- Conditional display (using v-show)
- Dynamic component
- Component root node
Here is a typical example:
<div id="demo"> <button v-on:click="show = !show"> Toggle </button> <transition name="fade"> <p v-if="show">hello</p> </transition> </div>
new Vue({ el: '#demo', data: { show: true } })
/*Specifies the style during the transition*/ .fade-enter-active, .fade-leave-active { transition: opacity 1s; } /*Specifies the style when hidden*/ .fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ { opacity: 0; }
When inserting or deleting elements contained in the transition component, Vue will do the following:
- Automatically sniff whether CSS transition or animation is applied to the target element. If so, add / delete CSS class names at the right time.
- If the transition component provides JavaScript hook function , these hook functions will be called at the right time.
- If the JavaScript hook is not found and the CSS transition / animation is not detected, the DOM operation (insert / delete) is executed immediately in the next frame. (Note: This refers to the browser frame by frame animation mechanism, which is different from Vue's nextTick concept)
Transitional class name
In the transition of entry / exit, there will be 6 class switches.
- v-enter: defines the start state of the transition. Takes effect before the element is inserted and is removed at the next frame after the element is inserted.
- v-enter-active: defines the state when the transition takes effect. Applied throughout the transition phase, it takes effect before the element is inserted and removed after the transition / animation is completed. This class can be used to define the process time, delay and curve function of entering the transition.
- v-enter-to: version 2.1.8 and above definitions enter the end state of transition. After the element is inserted, the next frame takes effect (at the same time, v-enter is removed) and is removed after the transition / animation is completed.
- v-leave: defines the start state of the exit transition. Takes effect immediately when the exit transition is triggered and the next frame is removed.
- v-leave-active: defines the state when the exit transition takes effect. Applied throughout the exit transition phase, it takes effect immediately when the exit transition is triggered and is removed after the transition / animation is completed. This class can be used to define the process time, delay and curve function of leaving the transition.
- v-leave-to: version 2.1.8 and above define the end state of leaving the transition. After the departure transition is triggered, the next frame takes effect (at the same time, v-leave is deleted) and is removed after the transition / animation is completed.
[the external link image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-UqK10wzj-1619407373112)(images / wechat screenshot _20201029212206.png)]
For these class names that are switched during the transition, if you use a < transition > without a name, V - is the default prefix of these class names. If you use < transition name = "my transition" >, v-enter will be replaced by my transition enter.
v-enter-active and v-leave-active can control different transition curves of entry / exit transition, which will be illustrated by an example in the following chapters.
CSS transition
Commonly used transitions are transitions using CSS.
Here is a simple example:
<div id="example-1"> <button @click="show = !show"> Toggle render </button> <transition name="slide-fade"> <p v-if="show">hello</p> </transition> </div>
new Vue({ el: '#example-1', data: { show: true } })
/* Different entry and exit animations can be set */ /* Set duration and animation functions */ .slide-fade-enter-active { transition: all 1s; } .slide-fade-leave-active { transition: all 3s; } .slide-fade-enter, .slide-fade-leave-to /* .slide-fade-leave-active for below version 2.1.8 */ { transform: translateX(30px); opacity: 0; }
CSS animation
The difference between CSS animation and CSS transition is that in animation, the v-enter class name will not be deleted immediately after the node is inserted into DOM, but will be deleted when the animation end event is triggered.
Example: (compatibility prefix omitted)
<div id="example-2"> <button @click="show = !show">Toggle show</button> <transition name="bounce"> <!--style="display: inline-block" Solve the problem when there are few fonts bug--> <p v-if="show" style="display: inline-block">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris facilisis enim libero, at lacinia diam fermentum id. Pellentesque habitant morbi tristique senectus et netus.</p> </transition> </div>
new Vue({ el: '#example-2', data: { show: true } })
.bounce-enter-active { animation: bounce-in .5s; } .bounce-leave-active { animation: bounce-in .5s reverse; } @keyframes bounce-in { 0% { transform: scale(0); } 50% { transform: scale(1.5); } 100% { transform: scale(1); } }
More: https://cn.vuejs.org/v2/guide/transitions.html
filter
Vue.js allows you to customize filters that can be used for some common text formatting.
Function: display the data to be displayed after specific formatting
Note: the original data is not changed, but new corresponding data is generated
Basic grammar
Define filter
You can define local filters (local) in the options of a component:
filters: { // The value passed is the data before the pipeline filterName: function (value[,arg1,arg2,...]) { // Carry out certain data processing return newValue } } // such as filters: { capitalize: function (value) { if (!value) return '' value = value.toString() return value.charAt(0).toUpperCase() + value.slice(1) } }
Or define filters globally before creating Vue instances:
Vue.filter(filterName, function(value[,arg1,arg2,...]){ // Carry out certain data processing return newValue }) // such as Vue.filter('capitalize', function (value) { if (!value) return '' value = value.toString() return value.charAt(0).toUpperCase() + value.slice(1) }) new Vue({ // ... })
When the global filter and local filter have the same name, the local filter will be adopted.
Use filter
Filters can be used in two places: Double curly bracket interpolation and v-bind expressions (the latter is supported from 2.1.0 +). The filter should be added at the end of the JavaScript expression, indicated by the "pipe" symbol:
<!-- In double curly braces --> {{ message | capitalize }} {{ message | capitalize(arg) }} <!-- stay `v-bind` in --> <div v-bind:id="rawId | formatId"></div>
Basic example
Example 1
The following example uses the capitalize filter: change the initial letter of data to uppercase;
<div id="app"> <input type="text" v-model="name"> <br> {{name | capitalize}} </div> <script type="text/javascript"> Vue.filter('capitalize', function (value) { if (!value) return '' value = value.toString() return value.charAt(0).toUpperCase() + value.slice(1) }) new Vue({ el: '#app', data: { name: '' } }) </script>
Example 2
Replace the java in the string with javascript, which is not case sensitive;
<div id="root"> <h2>1.Basic format</h2> <p>{{msg | msgFormat1}}</p> </div> <script type="text/javascript"> //Parameters of anonymous function: //The first parameter is the incoming data to be filtered, that is, the original data. //The second parameter is the parameter passed in when html calls the filter. Vue.filter('msgFormat1', function (msg) { // return msg.replace('java', 'javascript'); // Replace the first Java // return msg.replace(/java/g, 'javascript'); // Replace all Java, but uppercase Java is not replaced return msg.replace(/java/ig, 'javascript'); //Case insensitive replace all }); var vue = new Vue({ el: '#root', data: { msg: 'I love java,java Is the most popular language,Java Love me.' } }); </script>
Pass in parameters. Pass in multiple parameters
Single parameter:
<div id="root"> <h2>2.Format with parameters</h2> <p>{{msg | msgFormat2('vue')}}</p> </div> <script type="text/javascript"> //Dynamically pass a matching string Vue.filter('msgFormat2',function(msg, pattern){ return msg.replace(/java/ig, pattern); }); var vue = new Vue({ el: '#root', data: { msg: 'I love java,java Is the most popular language,Java Love me.' } }); </script>
Multiple parameters
<div id="root"> <h2>3.Format with multiple parameters</h2> <p>{{msg | msgFormat3('python','bigdata')}}</p> </div> <script type="text/javascript"> //In fact, the essence is not very different from the above Vue.filter('msgFormat3',function(msg, pattern1, pattern2){ return msg.replace(/java/ig, pattern1+'And'+pattern2); }); var vue = new Vue({ el: '#root', data: { msg: 'I love java,java Is the most popular language,Java Love me.' } }); </script>
Set multiple filters
<div id="root"> <h2>4.Multiple matchers</h2> <p>{{msg | msgFormat3('python','bigdata') | msgFormat4}}</p> </div> <script type="text/javascript"> //In fact, the essence is not very different from the above Vue.filter('msgFormat3', function (msg, pattern1, pattern2) { return msg.replace(/java/ig, pattern1 + 'And' + pattern2); }); Vue.filter('msgFormat4', function (msg) { return msg + 'Many skills do not weigh on one's body - overall situation'; }); var vue = new Vue({ el: '#root', data: { msg: 'I love java,java Is the most popular language,Java Love me.' }, filters: { msgFormat4(msg) { return msg + 'Many skills do not weigh on one's body - local'; } } }); </script>
Application examples
Format and display the time
<div id="test"> <h2>Displays the formatted date and time</h2> <p>Current time is: {{time}}</p> <p>The most complete time: {{time | dateString}}</p> <p>specific date: {{time | dateString('YYYY-MM-DD')}}</p> <p>Hour, minute and second: {{time | dateString('HH-mm-ss')}}</p> </div> <script type="text/javascript" src="https://cdn.bootcss.com/moment.js/2.22.1/moment.js"></script> <script> // Define filter Vue.filter('dateString', function (value, format) { return moment(value).format(format || 'YYYY-MM-DD HH:mm:ss'); }) new Vue({ el: '#test', data: { time: new Date() }, mounted() { setInterval(() => { this.time = new Date() }, 1000) } }) </script>
Built in instruction and custom instruction
Common built-in instructions
- v:text: update textContent of element
- v-html: update innerHTML of element
- v-if: if it is true, the current tag will be output to the page
- v-else-if: if true, the current tag will be output to the page
- v-else: if it is false, the current tag will be output to the page
- v-show: control display / hide by controlling display style
- v-for: traversing arrays / objects
- v-on: binding event listening, generally abbreviated as@
- v-bind: force binding parsing expression. v-bind can be omitted
- v-model: bidirectional data binding
- V-cloak: Prevent Flash, cooperate with css: [v-cloak] {display: none}
- ref: Specifies the unique identifier. The vue object accesses this element object through the $refs attribute
<div id="example"> <!-- v-text --> <p v-text="content"></p> <!-- v-html --> <p v-html="content"></p> <!-- v-if/v-else --> <p v-if="show">show by true display</p> <p v-else>show by false display</p> <!-- v-show --> <p v-show="show">show by true display</p> <!-- v-for --> <p> <span v-for="v in stus">{{v}}</span> </p> <!-- v-on --> <button @click="clickFun">Click event</button> <br> <!-- v-bind --> <img :src="imgUrl" alt="" style="width: 100px;"> <br> <!-- v-model --> <input type="text" v-model="userName"> <br> <!-- v-cloak --> <p v-cloak>{{content}}</p> <!-- ref --> <p ref="msg">abcd</p> <button @click="hint">Tips</button> </div> <script type="text/javascript"> new Vue({ el: '#example', data: { content: '<a href="http://www.baidu. Com "> Baidu < / a > ', show: true, stus: ["Zhang San", "Li Si", "Wang Wu"], imgUrl: "https://cn.vuejs.org/images/logo.png", userName: "" }, methods: { clickFun() { alert("Click"); }, hint() { alert(this.$refs.msg.innerHTML) } } }) </script>
Custom instruction
In addition to the default built-in instructions for core functions (v-model and v-show), Vue also allows you to register custom instructions. Note that in vue2 The main forms of reusable components are 0 and 0. However, in some cases, you still need to perform the underlying operations on ordinary DOM elements, and custom instructions will be used at this time.
Basic case
When the page loads, this element will get focus (Note: autofocus doesn't work on mobile Safari). In fact, as long as you haven't clicked anything after opening this page, the input box should still be in focus. Now let's implement this function with instructions:
// Register a global custom instruction ` v-focus` Vue.directive('focus', { // When the bound element is inserted into the DOM inserted: function (el) { // Focus element el.focus() } }) // If you want to register local instructions, the component also accepts an option of directives: directives: { focus: { // Definition of instruction inserted: function (el) { el.focus() } } } // For example, the v-text="msg" instruction displays the content corresponding to msg on the page;
Then you can use the new v-focus property on any element in the template, as follows:
<input v-focus>
Hook function
An instruction definition object can provide the following hook functions (all optional):
-
bind: called only once, when the instruction is bound to the element for the first time. One time initialization settings can be made here.
-
Inserted: called when the bound element is inserted into the parent node (only the parent node is guaranteed to exist, but it may not have been inserted into the document).
-
Update: called when the VNode of the component is updated, but it may occur before its child VNode is updated. The value of the instruction may or may not have changed. However, you can ignore unnecessary template updates by comparing the values before and after the update (see the following for detailed hook function parameters).
-
componentUpdated: the VNode and its sub VNode of the instruction component are updated after all updates.
-
unbind: called only once when the instruction is unbound from the element.
Next, let's look at the parameters of the hook function (that is, el, binding, vnode and oldVnode).
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-25gbJpHc-1619407373114)(images/clip_image094.png)]
The difference between the three is mainly the timing of implementation.
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-pGXWX01X-1619407373115)(images/clip_image095.png)]
Hook function parameters
The instruction hook function will be passed in the following parameters:
- el: the element bound by the instruction, which can be used to directly operate the DOM.
- binding: an object containing the following properties:
- Name: instruction name, excluding v-prefix.
- Value: the binding value of the instruction. For example, in: v-my-directive="1 + 1", the binding value is 2.
- oldValue: the previous value of the instruction binding. It is only available in the update and componentUpdated hooks. Available whether the value changes or not.
- Expression: instruction expression in string form. For example, in v-my-directive="1 + 1", the expression is "1 + 1".
- arg: parameter passed to the instruction; optional. For example, in v-my-directive:foo, the parameter is "foo".
- Modifiers: an object that contains modifiers. For example: v-my-directive foo. In bar, the modifier object is {foo: true, bar: true}.
- vnode: the virtual node generated by Vue compilation. Step by step VNode API To learn more.
- oldVnode: the previous virtual node, which is only available in the update and componentUpdated hooks.
Except el, other parameters should be read-only and should not be modified. If you need to share data between hooks, it is recommended to use the dataset Come on.
This example uses a custom hook:
<div id="hook-arguments-example" v-demo:foo.a.b="message"></div>
Vue.directive('demo', function (el, binding, vnode) { var s = JSON.stringify el.innerHTML = 'name: ' + s(binding.name) + '<br>' + 'value: ' + s(binding.value) + '<br>' + 'expression: ' + s(binding.expression) + '<br>' + 'argument: ' + s(binding.arg) + '<br>' + 'modifiers: ' + s(binding.modifiers) + '<br>' + 'vnode keys: ' + Object.keys(vnode).join(', ') }) new Vue({ el: '#hook-arguments-example', data: { message: 'hello!' } })
The results are as follows:
name: "demo" value: "hello!" expression: "message" argument: "foo" modifiers: {"a":true,"b":true} vnode keys: tag, data, children, text, elm, ns, context, fnContext, fnOptions, fnScopeId, key, componentOptions, componentInstance, parent, raw, isStatic, isRootInsert, isComment, isCloned, isOnce, asyncFactory, asyncMeta, isAsyncPlaceholder
Case understanding hook function
For example, to customize an instruction to set the font color, you need to set it in the bind function.
js related operations are best placed in inserted, and style related settings are best placed in bind
<div id="root"> <input type="text" v-model="msg" v-focus /> <h2>{{msg}}</h2> </div> <script type="text/javascript"> Vue.directive('focus', { // Defining an instruction object can provide the following hook functions // bind: called only once, when the instruction is bound to the element for the first time. // The code that sets the style for elements is usually written in bind. bind: function(el){ el.style.width = '240px'; el.style.height = '50px'; el.style.fontSize = '40px'; }, inserted: function(el){ // Inserted: called when the bound element is inserted into the DOM. // When setting js effect for elements, it is usually written in inserted. el.focus(); }, update: function(el){ // update: when the bound DOM structure is refreshed, it will be executed multiple times console.log(el.value); } }) var vue = new Vue({ el: '#root', data:{ msg: 'hello vuejs' } }); </script>
Application case
Text conversion
<!-- demand: Customize 2 instructions 1. Function type in v-text, But convert to all uppercase 2. Function type in v-text, But convert to all lowercase --> <div id="test"> <p v-upper-text="msg"></p> <p v-lower-text="msg"></p> </div> <div id="test2"> <p v-upper-text="msg"></p> <p v-lower-text="msg"></p> </div> <script type="text/javascript"> // Register a global instruction // el: label object where the instruction is located // binding: container object containing instruction related data Vue.directive('upper-text', function (el, binding) { console.log(el, binding) el.textContent = binding.value.toUpperCase() }) new Vue({ el: '#test', data: { msg: "I Like You" }, // Register local instruction directives: { 'lower-text'(el, binding) { console.log(el, binding) el.textContent = binding.value.toLowerCase() } } }) new Vue({ el: '#test2', data: { msg: "I Like You Too" } }) </script>
Change the background
<div id="root"> <div v-bgcolor="'red'"> {{msg}} </div> </div> <script type="text/javascript"> Vue.directive('bgcolor', { bind: function(el, binding){ el.style.background = binding.value; } }); var vue = new Vue({ el: '#root', data: { msg: 'hello vuejs' } }); </script> //Sometimes we don't need other hook functions. We can abbreviate functions as follows: <div id="root"> <div v-bgcolor="'red'"> {{msg}} </div> </div> <script type="text/javascript"> Vue.directive('bgcolor', function(el, binding){ el.style.background = binding.value; }); var vue = new Vue({ el: '#root', data: { msg: 'hello vuejs' } }); </script>
The instruction function can accept all legal JavaScript expressions. The following examples pass in JavaScript objects:
<div id="root"> <div v-bgcolor="{color:'red',background:'yellow',text:'Hello Vue'}"> </div> </div> <script type="text/javascript"> Vue.directive('bgcolor', function(el, binding){ el.style.color = binding.value.color; el.style.background = binding.value.background; el.innerHTML = binding.value.text; }); var vue = new Vue({ el: '#root', data: { msg: 'hello vuejs' } }); </script>
Define private instructions
If you need to define private instructions, you can define them in Vue({}) directive.
<div id="root"> <div v-bgcolor="{color:'red',background:'yellow',text:'Hello Vue'}"> </div> </div> <script type="text/javascript"> var vue = new Vue({ el: '#root', //Private instruction directives:{ "bgcolor":{ bind:function (el,binding){ el.style.color = binding.value.color; el.style.background = binding.value.background; el.innerHTML = binding.value.text; } } } }); </script>
Custom plug-ins
Plug ins are often used to add global functionality to Vue. There are no strict restrictions on the functional scope of plug-ins - there are generally the following types:
- Add a global method or property. For example: vue-custom-element
- Add global resources: instructions / filters / transitions, etc. as vue-touch
- Add some component options through global blending. as vue-router
- Add Vue instance methods by adding them to Vue Implemented on prototype.
- A library that provides its own API and one or more of the functions mentioned above. as vue-router
Develop plug-ins
Vue.js plug-in should expose an install method. The first parameter of this method is the Vue constructor, and the second parameter is an optional option object:
vue-myPlugin.js
(function (window) { const MyPlugin = {} MyPlugin.install = function (Vue, options) { // 1. Add global method or attribute Vue.myGlobalMethod = function () { console.log('Vue Function object myGlobalMethod()') } // 2. Add global resources Vue.directive('my-directive',function (el, binding) { el.textContent = 'my-directive----'+binding.value }) // 4. Add instance method Vue.prototype.$myMethod = function () { console.log('vm $myMethod()') } } window.MyPlugin = MyPlugin })(window)
Using plug-ins
Through the global method Vue Use () uses plug-ins. It needs to be completed before you call new Vue() to start the application:
// Call ` myplugin install(Vue)` Vue.use(MyPlugin) new Vue({ // ... Component options })
<div id="test"> <p v-my-directive="msg"></p> </div> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript" src="vue-myPlugin.js"></script> <script type="text/javascript"> // Declare to use the plug-in (install plug-in: call the plug-in's install()) Vue.use(MyPlugin) // The plug-in object's install() will be called internally const vm = new Vue({ el: '#test', data: { msg: 'Hello Vue' } }) Vue.myGlobalMethod() vm.$myMethod() </script>
3, User management system
Create template page
Page rendering
[the external link image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-WQq7fSlu-1619407373117)(images/demo.png)]
Static page implementation
<!doctype html> <html> <head> <title>Page title</title> <meta charset="utf-8"> <!-- To adapt to the mobile terminal,If you want to use media query Compatible mobile terminal,This sentence must be added --> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> <!-- in order to IE9 The following browsers are compatible HTML5 and CSS3 --> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script> <script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script> <![endif]--> <!-- Give Way IE The browser renders the page in the latest document mode --> <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1"> <!-- introduce bootstrap Provided style file,Font icon files do not need to be imported,Because font icon files are used to be CSS Used --> <link rel="stylesheet" href="css/bootstrap.min.css"> <!-- introduce jQuery file,and jQuery File must be in 1.9 Version above,because Bootstrap The animation provided is based on jQuery To write --> <script src="js/jquery.min.js"></script> <!-- introduce bootstrap.min.js --> <script src="js/bootstrap.min.js"></script> <!-- introduce vue.js --> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <!-- definition Bootstrap container --> <div id="root" class="container"> <!-- Define system title --> <h1 v-cloak>User management system</h1> <!-- Define and add employees --> <div class="panel panel-primary"> <div class="panel-heading"> <h3 class="panel-title">Add user</h3> </div> <div class="panel-body form-inline"> <div class="col-md-7"> <div class="form-group"> <label for="userId">User number:</label> <input type="text" class="form-control" id="userId" placeholder="Please enter user number"> </div> <div class="form-group"> <label for="userName">User name:</label> <input type="text" class="form-control" id="userName" placeholder="Please enter user name"> </div> <button type="submit" class="btn btn-info">add to</button> </div> <div class="col-md-4 col-md-offset-1"> <div class="form-group"> <label for="search" class="sr-only">search:</label> <input type="search" class="form-control" id="search" placeholder="search"> </div> <button type="submit" class="btn btn-primary">search</button> </div> </div> </div> <!-- Define table --> <table class="table table-bordered table-striped table-hover"> <thead> <tr class="bg-primary"> <th>User number</th> <th>User name</th> <th>Creation time</th> <th>operation</th> </tr> </thead> <tbody> <tr> <td>1001</td> <td>Zhang San</td> <td>2019-12-22 09:44:02</td> <td> <button type="button" class="btn btn-warning btn-xs">modify</button> <button type="button" class="btn btn-danger btn-xs">delete</button> </td> </tr> <tr> <td>1002</td> <td>Li Si</td> <td>2018-05-22 22:12:52</td> <td> <button type="button" class="btn btn-warning btn-xs">modify</button> <button type="button" class="btn btn-danger btn-xs">delete</button> </td> </tr> <tr> <td>1003</td> <td>Wang Wu</td> <td>2017-08-22 09:44:02</td> <td> <button type="button" class="btn btn-warning btn-xs">modify</button> <button type="button" class="btn btn-danger btn-xs">delete</button> </td> </tr> </tbody> </table> </div> </body> </html>
Create a template page of html+vue
<!doctype html> <html> <head> <title>Page title</title> <meta charset="utf-8"> <!-- To adapt to the mobile terminal,If you want to use media query Compatible mobile terminal,This sentence must be added --> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> <!-- in order to IE9 The following browsers are compatible HTML5 and CSS3 --> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script> <script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script> <![endif]--> <!-- Give Way IE The browser renders the page in the latest document mode --> <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1"> <!-- introduce bootstrap Provided style file,Font icon files do not need to be imported,Because font icon files are used to be CSS Used --> <link rel="stylesheet" href="css/bootstrap.min.css"> <!-- introduce jQuery file,and jQuery File must be in 1.9 Version above,because Bootstrap The animation provided is based on jQuery To write --> <script src="js/jquery.min.js"></script> <!-- introduce bootstrap.min.js --> <script src="js/bootstrap.min.js"></script> <!-- introduce vue.js --> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <!-- definition Bootstrap container --> <div id="root" class="container"> <!-- Define system title --> <h1 v-cloak>{{system_title}}</h1> <!-- Define and add employees --> <div class="panel panel-primary"> <div class="panel-heading"> <h3 class="panel-title">Add user</h3> </div> <div class="panel-body form-inline"> <div class="col-md-7"> <div class="form-group"> <label for="userId">User number:</label> <!-- Enter the user number into the box and data Medium userId Two way binding --> <input type="text" class="form-control" v-model="userId" id="userId" placeholder="Please enter user number"> </div> <div class="form-group"> <label for="userName">User name:</label> <!-- Enter the user's name in the box and data Medium userName Two way binding --> <input type="text" class="form-control" v-model="userName" id="userName" placeholder="Please enter user name"> </div> <!-- When we click the button,implement addUser method,Adding employees is nothing more than putting data Inside userId and userName Get,Plus get the current system time --> <button type="submit" class="btn btn-info" @click="addUser">add to</button> </div> <div class="col-md-4 col-md-offset-1"> <div class="form-group"> <label for="search" class="sr-only">search:</label> <!-- Put the search box and data Inside searchValue Two way binding --> <input type="search" class="form-control" v-model="searchValue" id="search" placeholder="search"> </div> <!-- When we click the search button,Query according to the entered value --> <button type="submit" class="btn btn-primary" @click="searchUser(searchValue)">search</button> </div> </div> </div> <!-- Define table --> <table class="table table-bordered table-striped table-hover"> <thead> <tr class="bg-primary"> <th>User number</th> <th>User name</th> <th>Creation time</th> <th>operation</th> </tr> </thead> <tbody> <!-- Using circular rendering data in userList Data --> <tr v-for="(item,index) of userList" :key="item.userId"> <!-- obtain userList Specific data of each object --> <td>{{item.userId}}</td> <td>{{item.userName}}</td> <td>{{item.createTime}}</td> <td> <!-- When you click the Modify button,Pass the data binding of the current object to the function as a parameter object --> <button type="button" class="btn btn-warning btn-xs" data-target="#Update toggle "< / button =" button "> Modify <!-- When we click the delete button,Based on incoming id Delete corresponding data --> <button type="button" class="btn btn-danger btn-xs" @click="deleteUser(item.userId)">delete</button> </td> </tr> </tbody> </table> <!-- Modify student's modal box --> <div class="modal fade" id="updateModal" > <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> <h4 class="modal-title" id="myModalLabel">Modify student</h4> </div> <div class="modal-body form-horizontal"> <div class="form-group"> <label for="updateId" class="col-sm-2 control-label">User number:</label> <div class="col-sm-10"> <p class="form-control-static">{{updateItem.userId}}</p> </div> </div> <div class="form-group"> <label for="updateName" class="col-sm-2 control-label">User name:</label> <div class="col-sm-10"> <input type="text" class="form-control" v-model="updateItem.userName" id="updateName" placeholder="Password"> </div> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-primary" data-dismiss="modal">Confirm modification</button> </div> </div> </div> </div> </div> <script type="text/javascript"> var vm = new Vue({ el: "#root", data: { system_title: "User management system", userId: "", userName: "", searchValue: "", userList: [{ userId: 1001, userName: "Zhang San", createTime: new Date() }, { userId: 1002, userName: "Li Si", createTime: new Date() }, { userId: 1003, userName: "Wang Wu", createTime: new Date() } ], updateItem: { userId:"", userName:"" } }, methods: { addUser() { console.log("Add user!") }, deleteUser(id) { console.log("delete user:" + id) }, updateUser(id) { console.log("Modify user:" + id) }, searchUser(str) { console.log("Query user:" + str) } } }) </script> </body> </html>
Add user functions
1. Binding event handlers for adding buttons
2. Create a new user object
3. Add a new user object to the user list
4. Clear the data of two input forms at the same time
addUser() { // console.log("add user!") let newUser = { userId: this.userId, userName: this.userName, createTime: new Date() } this.userList.push(newUser); this.userId = this.userName = ""; }
Format date using filter:
<!-- Using circular rendering data in userList Data --> <tr v-for="(item,index) of userList" :key="item.userId"> <!-- obtain userList Specific data of each object --> <td>{{item.userId}}</td> <td>{{item.userName}}</td> <td>{{item.createTime|dateFormate}}</td> <td> <!-- When you click the Modify button,Bind the current object data to data Inside updateItem upper,Then the modal box pops up,In the modal box updateItem Data --> <button type="button" class="btn btn-warning btn-xs" data-target="#Updatemodal "data toggle =" modal "@ Click =" updateitem = item "> Modify < / button > <!-- When we click the delete button,Based on incoming id Delete corresponding data --> <button type="button" class="btn btn-danger btn-xs" @click="deleteUser(item.userId)">delete</button> </td> </tr>
Vue.filter("dateFormate",function(dateStr){ var dt = new Date(dateStr); var y = dt.getFullYear(); var m = dt.getMonth()+1; var d = dt.getDate(); m<10?m+="0":m; d<10?d+="0":d; return `${y}-${m}-${d}` })
Delete user's function
1. Bind event handler for delete button
2. Traverse the user list, find the element to be deleted according to the parameter id of the incoming handler and delete it
deleteUser(id) { console.log("delete user:" + id) var userList=this.userList; for(let i=0;i<userList.length;i++){ if(userList[i].userId==id){ var tf = confirm("Delete?"); if(tf){ userList.splice(i,1); } } } }
Modify user functions
Idea:
Click the Modify button to save the data of the selected row into the temporary data updateItem. If you click OK, the data in the original list will be replaced by updateItem, and the updateItem will be cleared. Otherwise, only empty updateItem will be requested.
At the same time, the form in the modified data should be bound to updateItem in both directions.
To add two click events to the modal box, there must be two methods.
Modal box effect
<!-- Modify student's modal box --> <div class="modal fade" id="updateModal" > <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close" @click="updateCancel"><span aria-hidden="true">×</span></button> <h4 class="modal-title" id="myModalLabel">Modify student</h4> </div> <div class="modal-body form-horizontal"> <div class="form-group"> <label for="updateId" class="col-sm-2 control-label">User number:</label> <div class="col-sm-10"> <p class="form-control-static">{{updateItem.userId}}</p> </div> </div> <div class="form-group"> <label for="updateName" class="col-sm-2 control-label">User name:</label> <div class="col-sm-10"> <input type="text" class="form-control" v-model="updateItem.userName" id="updateName" placeholder="Password"> </div> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-primary" data-dismiss="modal" @click="updateSure">Confirm modification</button> </div> </div> </div> </div>
Implementation logic
updateUser(item) { this.updateItem.userId = item.userId; this.updateItem.userName = item.userName; }, updateCancel(){ console.log("Cancel modification"); this.updateItem.userId = ""; this.updateItem.userName = ""; }, updateSure(){ console.log("Confirm modification",this.updateItem.userId,this.updateItem.userName) var updateId = this.updateItem.userId; var userList=this.userList; for(let i=0;i<userList.length;i++){ if(userList[i].userId==updateId){ userList[i].userId = this.updateItem.userId; userList[i].userName = this.updateItem.userName; } } this.updateItem.userId = ""; this.updateItem.userName = ""; },
Query user function
Binding search function:
<div class="col-md-4 col-md-offset-1"> <div class="form-group"> <label for="search" class="sr-only">search:</label> <!-- Put the search box and data Inside searchValue Two way binding --> <input type="search" class="form-control" v-model="searchValue" id="search" placeholder="search"> </div> <!-- When we click the search button,Query according to the entered value --> <button type="submit" class="btn btn-primary" @click="searchUser(searchValue)">search</button> </div> <!-- Using circular rendering data in searchUser(searchValue)Data obtained --> <tr v-for="(item,index) of searchUser(searchValue)" :key="item.userId"> <!-- obtain userList Specific data of each object --> <td>{{item.userId}}</td> <td>{{item.userName}}</td> <td>{{item.createTime|dateFormate}}</td> <td> <!-- When you click the Modify button,Bind the current object data to data Inside updateItem upper,Then the modal box pops up,In the modal box updateItem Data --> <button type="button" class="btn btn-warning btn-xs" data-target="#Update toggle "< / button =" button "> Modify <!-- When we click the delete button,Based on incoming id Delete corresponding data --> <button type="button" class="btn btn-danger btn-xs" @click="deleteUser(item.userId)">delete</button> </td> </tr>
Realize js function:
searchUser(str) { console.log("Query user:" + str) let userList = this.userList; //Query results let searchList = []; for(let i=0;i<userList.length;i++){ if(userList[i].userName.indexOf(str) != -1){ searchList.push(userList[i]); } } console.log(searchList) return searchList; }
Binding key function
[add new functions for the button to add data in the project]
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-MRVDyvCO-1619407373120)(images/clip_image167.png)]
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>user management </title> <link href="bootstrap-3.3.7-dist/css/bootstrap.css" rel="stylesheet"> <!--[if lt IE 9]> <script src="https://cdn.jsdelivr.net/npm/html5shiv@3.7.3/dist/html5shiv.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/respond.js@1.4.2/dest/respond.min.js"></script> <![endif]--> </head> <body> <div id="app"> <h1 v-text="tit"></h1> <div class="panel panel-primary"> <div class="panel-heading"> <h3 class="panel-title">Add user</h3> </div> <div class="panel-body form-inline input-group-sm"> <label for="id"> user ID: <input type="text" id="id" class="form-control" v-model="id" /> </label> <label for="name"> User name:<input type="text" id="name" class="form-control" v-model="name" @keyup.enter="addUser"/> </label> <input type="button" class="btn btn-info" id="" value="add to" @click="addUser" > <div class="input-group"> <input type="text" class="form-control" v-model="sv" placeholder="search" v-focus> <span class="input-group-btn"> <button class="btn btn-primary" type="button" @click="search(sv)" >search</button> </span> </div><!-- /input-group --> </div> </div> <table class="table table-bordered table-striped table-hover"> <thead> <tr class="bg-primary"> <th>ID</th><th>full name</th><th>Creation time</th><th>operation</th> </tr> </thead> <tbody> <tr v-for="(items,index) of search(sv)" :key="items.id"> <td v-text="items.id"></td> <td v-text="items.name"></td> <td v-cloak> <!--{{items.ctime}}--> {{ items.ctime | dateFormat('YY-mm-dd') }} </td> <td> <button class="btn btn-warning btn-xs" data-target="#update" data-toggle="modal" @click="editItem=items" >modify</button> <!--<button class="btn btn-danger btn-xs" @click="delUser(items.id-1)">delete</button>--> <!--data-target="#deldata "click the button to point to the element whose id meets the criteria -- > <!--data-toggle="model" Set the display effect to modal type--> <button class="btn btn-danger btn-xs" data-target="#deldata" data-toggle="modal" @click="nowId=items.id">delete</button> </td> </tr> </tbody> </table> </div> <script src="js/vue.js"></script> <script src="js/jquery-1.11.1.js"></script> <script src="bootstrap-3.3.7-dist/js/bootstrap.min.js"></script> <script type="text/javascript"> var vm=new Vue({ el:"#app", data:{ tit:"User management system", id:"", name:"", sv:"", list:[ {id:1,name:"Sun long",ctime:new Date()}, {id:2,name:"Zhao Lei",ctime:new Date()}, {id:3,name:"Zhao Feng",ctime:new Date()} ], nowId:"", editItem:{} }, methods:{ addUser(){ }, delUser(id){ }, updateUser(id){ }, search(str){ } } }) </script> </body> </html>